声明属性(Declared Properties)

本文介绍了如何使用Objective-C运行时API来访问和操作类及协议的属性信息。具体包括使用函数检索属性数组、获取属性的类型及属性列表等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


当编译器遇到属性声明时(参见The Objective-C 编程语言中的声明属性),它生成与封闭类、分类或协议相关的描述性元数据。可以通过函数访问元数据,该函数支持通过类或协议名称查找属性,获取属性的类型作为@encode 字符串,并复制property的属性列表作为C字符串数组。声明的属性列表可用于每个类和协议。

属性类型和函数

属性结构为属性描述符定义了一个不透明句柄。
typedef struct objc_property *Property;


可以使用class_copyPropertyList 和 protocol_copyPropertyList 函数分别检索属性数组和类(包括加载的类别)和协议:
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount)


例如,类声明如下:
@interface Lender : NSObject {
    float alone;
}
@property float alone;
@end


使用如下代码,可以得到属性列表:
id LenderClass = objc_getClass("Lender");
unsigned int outCount;
objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);


可以使用property_getName函数来找到属性名称:
const char *property_getName(objc_property_t property)


可以使用class_getProperty和protocol_getProperty函数分别获取类和协议中给定名称的属性的引用:
objc_property_t class_getProperty(Class cls, const char *name)
objc_property_t protocol_getProperty(Protocol *proto, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty)


可以使用property_getAttributes 函数获取属性的名称和@encode类型字符串。编码类型字符串详情可查看类型编码;字符串详情可查看属性类型字符串和property属性描述例子。
const char *property_getAttributes(objc_property_t property)


把这些放在一起,使用如下代码,可以打印所有与类关联的属性列表:
id LenderClass = objc_getClass("Lender");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);
for (i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}


属性类型字符串

可以使用property_getAttributes函数来获取名字,property的@encode类型字符串和其他property的属性。
该字符串以T开头,随后是@encode 类型和逗号,最后是V和实例变量名称。在这之间,用以下描述符来指定属性,并用逗号分隔:

表7-1 声明属性类型编码

Code

Meaning

R

The property is read-only (readonly).

C

The property is a copy of the value last assigned (copy).

&

The property is a reference to the value last assigned (retain).

N

The property is non-atomic (nonatomic).

G<name>

The property defines a custom getter selector name. The name follows the G (for example, GcustomGetter,).

S<name>

The property defines a custom setter selector name. The name follows the S (for example, ScustomSetter:,).

D

The property is dynamic (@dynamic).

W

The property is a weak reference (__weak).

P

The property is eligible for garbage collection.

t<encoding>

Specifies the type using old-style encoding.


更多例子,可查看property属性描述示例。

property属性描述示例

给出以下定义:
enum FooManChu { FOO, MAN, CHU };
struct YorkshireTeaStruct { int pot; char lady; };
typedef struct YorkshireTeaStruct YorkshireTeaStructType;
union MoneyUnion { float alone; double down; };


下面的表格显示了属性声明和property_getAttributes返回的相应字符串:

Property declaration

Property description

@property char charDefault;

Tc,VcharDefault

@property double doubleDefault;

Td,VdoubleDefault

@property enum FooManChu enumDefault;

Ti,VenumDefault

@property float floatDefault;

Tf,VfloatDefault

@property int intDefault;

Ti,VintDefault

@property long longDefault;

Tl,VlongDefault

@property short shortDefault;

Ts,VshortDefault

@property signed signedDefault;

Ti,VsignedDefault

@property struct YorkshireTeaStruct structDefault;

T{YorkshireTeaStruct="pot"i"lady"c},VstructDefault

@property YorkshireTeaStructType typedefDefault;

T{YorkshireTeaStruct="pot"i"lady"c},VtypedefDefault

@property union MoneyUnion unionDefault;

T(MoneyUnion="alone"f"down"d),VunionDefault

@property unsigned unsignedDefault;

TI,VunsignedDefault

@property int (*functionPointerDefault)(char *);

T^?,VfunctionPointerDefault

@property id idDefault;

Note: the compiler warns: "no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed"

T@,VidDefault

@property int *intPointer;

T^i,VintPointer

@property void *voidPointerDefault;

T^v,VvoidPointerDefault

@property int intSynthEquals;

In the implementation block:

@synthesize intSynthEquals=_intSynthEquals;

Ti,V_intSynthEquals

@property(getter=intGetFoo, setter=intSetFoo:) int intSetterGetter;

Ti,GintGetFoo,SintSetFoo:,VintSetterGetter

@property(readonly) int intReadonly;

Ti,R,VintReadonly

@property(getter=isIntReadOnlyGetter, readonly) int intReadonlyGetter;

Ti,R,GisIntReadOnlyGetter

@property(readwrite) int intReadwrite;

Ti,VintReadwrite

@property(assign) int intAssign;

Ti,VintAssign

@property(retain) id idRetain;

T@,&,VidRetain

@property(copy) id idCopy;

T@,C,VidCopy

@property(nonatomic) int intNonatomic;

Ti,VintNonatomic

@property(nonatomic, readonly, copy) id idReadonlyCopyNonatomic;

T@,R,C,VidReadonlyCopyNonatomic

@property(nonatomic, readonly, retain) id idReadonlyRetainNonatomic;

T@,R,&,VidReadonlyRetainNonatomic






官方原文地址:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW1
<think>好的,用户的问题是关于在CCS(Code Composer Studio)中遇到'declared implicitly'报错的解决方案。首先,我需要回忆一下这类错误通常是什么原因导致的。根据之前的经验,这个错误通常是因为编译器找不到函数的声明,也就是说函数没有在头文件中正确声明,或者头文件没有被包含进来。 用户提供的引用信息是来自RTC模块的代码,具体是RCC_APB1PeriphClockCmd函数被隐式声明。这可能意味着用户在使用这个函数之前没有包含相应的头文件。对于STM32的开发,RCC相关的函数通常定义在stm32fxxx_rcc.h头文件中,所以用户可能需要检查是否包含了正确的头文件。 接下来,我需要分步骤思考解决方案。首先,检查头文件包含情况,确保包含了对应的外设库头文件。其次,检查函数名是否正确,是否有拼写错误。然后,确认是否启用了对应的外设时钟宏定义,有时候需要先定义启用某个外设的时钟。另外,工程配置是否正确,比如编译器路径是否包含必要的库文件目录。最后,可能需要更新库文件,如果使用的库版本过旧,可能会有函数声明缺失的问题。 还需要考虑用户可能没有正确配置工程,比如在CCS中添加头文件路径的方法是否正确,或者是否遗漏了链接必要的库文件。此外,有些函数可能在特定的条件下才被启用,比如需要定义某个宏来启用外设功能。 在生成相关问题的时候,需要围绕这个错误可能涉及的其他方面,比如如何添加头文件路径,如何检查拼写错误,或者如何确认函数是否过时等。这些问题可以帮助用户更全面地理解和解决类似的问题。 总结一下,解决步骤可能包括:包含正确的头文件、检查函数拼写、启用外设宏、检查工程配置、更新库文件。每个步骤都需要详细说明,确保用户能够跟随操作。同时,需要提醒用户注意不同STM32系列可能头文件名称不同,比如F1、F4的区别,避免混淆。 最后,生成的相关问题需要覆盖常见的相关错误,比如头文件包含问题、拼写错误、宏定义缺失等,这样用户可以通过这些问题进一步排查其他潜在问题。</think>在CCS中出现`declared implicitly`报错通常表示函数未声明或未正确包含头文件。以下是分步解决方案: 1. **检查头文件包含** - 确保调用的函数(如`RCC_APB1PeriphClockCmd`)所属的头文件已包含。STM32标准库中该函数声明在`stm32fxxx_rcc.h`中,例如: ```c #include "stm32f10x_rcc.h" //根据芯片型号选择对应头文件 ``` - 若使用HAL库,可能需要包含`stm32fxxx_hal_rcc.h`[^1] 2. **验证函数拼写** - 检查函数名是否拼写错误,例如: ```c RCC_APB1PeriphClockCmd(...); //正确 RCC_APB1_PeriphClockCmd(...); //错误:多了下划线 ``` 3. **启用外设宏定义** - 在头文件包含前添加宏定义启用外设: ```c #define STM32F10X_MD //示例:针对中等密度芯片 #include <stm32f10x.h> ``` 4. **检查工程配置** - 在CCS工程属性中确认包含路径: ``` Project > Properties > Build > Include Options ``` - 添加标准外设库路径(如`../Libraries/STM32F10x_StdPeriph_Driver/inc`) 5. **更新库文件** - 若使用旧版固件库,建议更新至与芯片型号匹配的版本 - 通过STM32CubeMX生成初始化代码可避免配置错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值