重学iOS-属性关键字@property (上)

226 阅读2分钟

第一个最重要的问题:为什么要有@property?

在没有@property之前,定义实例变量是这样:

@interface Person : NSObject {
@public
    NSString *name;
@private
    int age;
}
@end

然后在.h文件,声明setter和getter方法(setter和getter统称「accessors/存取器/访问器」),再在.m文件实现setter和getter,这样就可以封装起来,供其他类访问(取值、赋值)了。然而,即使不使用setter和getter,其他类也可以通过->来直接访问。

第二个问题:为什么要getter和setter呢?

1 在非ARC时代,可以在在getter和setter中进行内存管理 2 可以在getter和setter中添加额外的代码,实现特定的目的。比如赋值前(set)需要实现一些特定的内部计算,或者更新状态,缓存数据等等。 3 KVC和KVO都是基于此实现的

第三个问题:在早起版本中@property做了哪些事情?

1 在.h文件,用@property声明了属性——这只是帮我们在声明了getter和setter 2 还需要手动声明实例变量,后来,不需要为属性声明实例变量了,@synthesize会默认自动生成一个「下划线+属性名」的实例变量。 3 然后在.m文件,还要用@synthesize自动合成getter和setter的实现

第四个问题:现在如果面试官问你:如果我们写@property声明属性做了哪些事情?

1 .h: 声明了getter和setter方法 2 .h: 声明了实例变量(默认:下划线+属性名); 3 .m: 实现了getter和setter方法。

第五个问题:@property中()内的内容到底是什么呢?

这里大类可以分为三种类型:1 atomicity(原子性) 2 Access(存取特性) 3 Storage(内存管理特性)(管理对象的生命周期的)

第六个问题:atomic 一定是线程安全的吗?为什么我们看到大多数都是用nonatomic

系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。getter 还是能得到一个完好无损的对象(可以保证数据的完整性),但这个对象在多线程的情况下是不能确定的 atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的 因此,在多线程的环境下原子操作是非常必要的,否则有可能会引起错误的结果。但仅仅使用atomic并不会使得对象线程安全,我们还要为对象线程添加lock来确保线程的安全。在某个小项目中将所有的nonatomic删除,内存占用平均升高1M左右

 @property (nonatomic) NSObject *nonatomicObj;
 @property (atomic) NSObject *atomicObj;
 
 
- (void)setNonatomicObj:(NSObject *)nonatomicObj{
    if (_nonatomicObj != nonatomicObj) {
        [_nonatomicObj release];
        _nonatomicObj = [nonatomicObj retain];
    }
}
 
- (NSObject *)nonatomicObj{
    return _nonatomicObj;
}
 
- (void)setAtomicObj:(NSObject *)atomicObj{
    @synchronized(self) {
        if (_atomicObj != atomicObj) {
            [_atomicObj release];
            _atomicObj = [atomicObj retain];
        }
    }
}
 
- (NSObject *)atomicObj{
    @synchronized(self) {
        return _atomicObj;
    }
}

第七个问题:内存管理特性(strong、copy、assgin、copy)