声明的属性

当编译器遇到属性声明时(请参阅Objective-C编程语言声明属性),它会生成与封闭类,类别或协议相关联的描述性元数据。您可以在类或协议上按名称查找属性,将属性类型作为@encode字符串获取,以及将属性列表作为C字符串数组复制的函数来访问此元数据。每个类和协议都有一个声明的属性列表。

属性类型和功能

Property结构定义了属性描述符的不透明句柄。

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_getPropertyprotocol_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属性的名称和类型字符串。有关编码类型字符串的详细信息,请参阅类型编码 ; 有关此字符串的详细信息,请参阅属性类型字符串属性属性描述示例

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函数来发现名称,@encode属性的类型字符串以及属性的其他属性。

该字符串以a开头,T后跟@encode类型和逗号,并以a 结尾,后跟V后备实例变量的名称。在这些属性之间,属性由以下描述符指定,用逗号分隔:

Table 7-1

Declared property type encodings

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.

有关示例,请参见属性属性描述示例

属性属性描述示例

鉴于这些定义:

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

Last updated

Was this helpful?