重拾iOS-@property

注意在ARC环境下:

1、在类中

@property的本质:

@property = ivar(实例变量) + getter/setter方法声明 + getter/setter方法实现;

当在类中使用@property声明属性时,无论是在.h中的还是在.m中,
编译器会自动生成一个带下划线的实例变量 + 对应的getter/setter方法的声明 + 对应的getter/setter方法的实现;

例如:

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@end

此时,会给Person类的.h中默认添加一个名为_name的成员变量,setName和name:两个方法(getter/setter)的声明,如:

@interface Person : NSObject
{
    NSString *_name;
}
- (void)setName:(NSString *)name;
- (NSString *)name;

@end

并且在Person类的.m中添加setName和name:两个方法(set/get)的实现,如:

- (void)setName:(NSString *)name{
    _name = name;
}
- (NSString *)name{
    return _name;
}

2、在分类中

@property的本质:

@property = getter/setter方法声明;

可以发现,当我们在分类中使用@property声明属性时,只是生成了getter/setter方法的声明,并不会自动生成ivar(实例变量) 和 getter/setter方法的实现。

例如:

@interface Person (test)

@property (nonatomic, copy) NSString *name;

@end

此时,只是在分类的.h中自动生成了setName和name:两个方法(set/get)的声明,如:

@interface Person (test)

- (void)setName:(NSString *)name;
- (NSString *)name;

@end

并且,在.m中有会提示:

提示需要提供setter/getter方法的实现;

如果,不提供setter/getter方法的实现,在使用是会报错unrecognized selector,
如下:


所以,一般我们会通过runtime添加关联对象,来间接的实现给分类添加属性。如下:

#import "Person+test.h"
#import 

@implementation Person (test)

- (NSString *)name {
    return objc_getAssociatedObject(self, @selector(name));
}
- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

@end

分类(Category)具体的实现原理,这里暂不详细说明;

你可能感兴趣的:(重拾iOS-@property)