美文网首页
iOS property关键字详解

iOS property关键字详解

作者: Devbrave | 来源:发表于2019-06-20 13:19 被阅读0次

    前言

    property属性关键字我们在日常的开发中经常会用到,所以我们有必要对其有充分的了解,这样对于我们日常开发使用时就能做到知其所以然。

    property关键字介绍

    property关键字分为四类:

    1. 原子性:atomicnonatomicproperty中默认是atomic,也就是线程安全,但是我们一般使用的是nonatomic。因为atomic的线程安全系统资源开销相对较大,影响性能,即使我们需要使用线程安全,我们也可以使用其他方法实现。atomic实现原理是在gettersetter中使用@synchronized同步锁关键字进行代码块锁定而实现的。

    补充atomic是自旋锁,即当上一线程没有执行完毕(被锁住),下一线程会一直等待(不会进入睡眠状态),当上一线程执行完毕,下一线程立即执行。他区别于互斥锁,互斥锁在等待的时候,会进入睡眠状态,当上一个线程执行完毕,睡眠状态就会被唤醒,然后再执行。

    1. 引用计数相关:assignretainweakstrongcopy、iOS5以前使用的unsafe_unretained
      assign:主要修饰基本数据类型,不能修饰对象类型,如NSInterger,CGFloat等类型。并且统一由系统栈进行内存管理。
      retain:修饰对象类型,强引用对象,并是对象引用计数加1,可用于MRC环境中。
      weak:修饰对象类型,对对象弱引用,不增加对象的引用计数。如果对象销毁了,指针会自动指向nil,所以可以防止野指针的问题。
      strong:修饰对象类型,对对象强引用,会增加对象的引用计数。如果指向了空对象,会造成野指针。只能用于ARC环境。
      copy:在一个新对象引用计数为1,赋值时对传入值进行一份拷贝,所以才使用copy关键字。你将一个对象赋值给一个属性,该属性并不会持有对象,而是会创建一个新对象,并将这个对象拷贝给它。使用copy关键字的对象必须实现NSCoding协议。
      unsafe_unretained:跟weak类似,声明一个弱引用,区别是当引用计数为0时,变量不会自动设置为nil

    2. 读写权限相关:默认是readwrite(可读可写),还有readonly,修饰属性时,属性不能被外界修改。

    3. 方法名:可设置属性的settergetter方法名。

    补充介绍

    weak关键字

    • 使用场景
      用于一些对象互相引用时,避免出现互相强引用而导致的循环引用,对象不能释放的。
    • 实现原理
      weak修饰时,runtime会维护一个hash表(也称为weak表),用于存储对象的所有weak指针,hash表的key是该对象的地址,valueweak指针的地址(这个地址的值是所指对象的地址)数组。(备注strong是通过runtime维护的一个自动引用计数表)
      weak的实现原理总结:
    1. 初始化时,runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象地址;
    2. 添加引用时,objc_initWeak函数会调用objc_storeWeak函数,objc_storeWeak的作用是更新指针指向,创建对应的弱引用表(hash表);
    3. 释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取weak指针地址的数组,然后遍历这个数组把其中指向空对象的指针设为nil,最后把这个指针从weak表中删除,最后清理对象的记录。

    copystrong
    讲这两个字之前我们需要了解深复制和浅复制相关的只是,可以参考这里。具体示例如下:

    @property (nonatomic, copy) NSMutableArray *mutArray;
    NSMutableArray *mutArray1 = [NSMutableArray array];
    self.mutArray = mutArray1;
    

    等同于

    @property (nonatomic, strong) NSMutableArray *mutArray;
    NSMutableArray *mutArray1 = [NSMutableArray array];
    self.mutArray = [mutArray1 copy];
    

    经过测试之后我们知道使用copy修饰的mutArray数组,当调用它的setter方法,它会建立一个引用计数为1的新对象,然后释放旧对象。而copy修饰的属性赋值时经过copy其实已经变成了不可变数组。而使用可变数组的增、删、改、查函数是会发现找不到相关的实例方法而crash

    NSString 为什么用 copy 而不用 retain
    我们通过实例来看看:

    @property (nonatomic, retain) NSString *string;
    NSMutableString *string1 = [[NSMutableString alloc] initWithString:@"abc"];
    self.string = string1;
    [string1 appendString:@"123"];
    NSLog(@"==============  %@ =========", self.string);
    2019-06-19 17:08:58.114333+0800 ThinTableVIew1[96955:2656816] ==============  abc123 =========
    
    

    从打印的信息可以看到当改变string1的值时,self.string的值也改变了。下面我们通过查看string属性setter方法的实现来探究一下原理:

    @property (nonatomic, retain) NSString *string;
    
    - (void)setString:(NSString *)string {
        if (_string != string) {
            [_string release];
            _string = [string retain];
            //相当于
            //[string retain];
            //_string = string;
        }
    }
    ==================
    @property (nonatomic, copy) NSString *string;
    
    - (void)setString:(NSString *)string {
        if (_string != string) {
            [_string release];
            _string = [string copy];
        }
    }
    

    我们可以知道:

    • 当使用retain修饰string时调用的是_string = [string retain],这样只会增加string的引用,而_string指针和string是指向同一块内容。所以改变string的内容同样的会改变_string的内容。
    • 当使用copy修饰string时,当传入的对象是可变对象时,调用的是[string copy];会创建一个新的对象赋值给_string,所以_stringstring不会互相干扰,而改变string的内容不会影响_string

    相关文章

      网友评论

          本文标题:iOS property关键字详解

          本文链接:https://www.haomeiwen.com/subject/nunofctx.html