美文网首页
关于OC修饰词的反思

关于OC修饰词的反思

作者: 民谣里不是故事就是诗丶 | 来源:发表于2018-09-06 16:02 被阅读17次

    代码写久了,对于一些基础的东西记忆反而慢慢变得模糊
    一些已经习以为常的东西,知道如何去用但是表达不清晰
    有时候自己说得清楚,被面试官一绕就要反应一下,
    不如自己静下心来总结总结

    Objective-C 是OOP(面向对象)的语言
    有面向对象就有 类和对象
    有类就有属性 (实例变量暂且不提)
    而OC的属性(property)是通过用@property定义的公有或私有的方法

    例如工程中Appdelegate.h中 系统默认生成
    @property (strong, nonatomic) UIWindow *window;

    ===============
    修饰词
    上述例子中()内的部分叫修饰词,用于表明对象的属性。

    OC中的属性property按照其功能分为以下三种类型:
    线程安全:atomic/nonatomic
    内存管理:assign/strong/weak/copy
    读写权限:readonly/readwrite

    Objective-C 中,
    基本数据类型 默认关键字是atomic, readwrite, assign;
    普通属性(带*的) 默认关键字是atomic, readwrite, strong。

    //atomatic nonatomic区别和理解

    atomic和nonatomic区别用来决定编译器生成的getter和setter是否为原子操作。
    atomic提供多线程安全,是描述该变量是否支持多线程的同步访问,如果选择了atomic 那么就是说,系统会自动的创建lock锁,锁定变量。
    nonatomic禁止多线程,变量保护,提高性能。
    主要的区别在于多线程操作一个对象时,用nonatomic的话,getter可能会取到只更改了其中一个变量时候的状态,这样取到的东西会有问题,就是不完整的。而atomic可以保证在多线程环境下,解析的访问器提供一个对属性的安全访问,但是性能会比较低。
    *如果要保证绝对的线程安全,可通过加锁的方式,例如@synchronized.

    //ARC下的内存属性

    strong: 表示指向并拥有该对象。其修饰的对象引用计数会增加1。该对象只要引用计数不为0则不会被销毁。当然强行将其设为nil可以销毁它。
    weak: 表示指向但不拥有该对象。其修饰的对象引用计数不会增加。无需手动设置,该对象会自行在内存中销毁。
    assign: 主要用于修饰基本数据类型,如NSInteger和CGFloat,这些数值主要存在于栈上。表示对属性只进行简单的赋值操作,不更改所赋的新值的引用计数,也不改变旧值的引用计数,常用于标量类型,如NSInteger,NSUInteger,CGFloat,NSTimeInterval等。assign修饰的对象被释放后,指针的地址依然存在,造成野指针,在堆上容易造成崩溃。而栈上的内存系统会自动处理,不会造成野指针。

    //MRC下的内存属性

    retain:OC对象类型
    copy:NSString、Block等类型
    assign:非OC对象类型, 基本数据类型
    (两个对象相互引用的时候,一端用retain, 一端用assign???。。。此处存疑。。。)

    //copy和strong的区别
    copy与strong类似。不同之处是strong的复制是多个指针指向同一个地址,而copy的复制每次会在内存中拷贝一份对象,指针指向不同地址。copy一般用在修饰有可变对应类型的不可变对象上,如NSString, NSArray, NSDictionary。

    //strong和weak的区别
    想起来第一次看书的时候有个例子讲,对象是狗(感觉怪怪的。。),引用就是绳子。强引用就是绳子牵着狗,弱引用就是目光看着狗。有多少强引用就有多少条绳子,所有绳子都脱落,狗才会跑(得到释放),而弱引用没有绳子绑着狗,当这个狗其他的强引用放掉了就跑了,再多目光都没有用,只能得到一个nil。所以,只要最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除。

    //UIView应该用strong还是weak修饰
    都存在。

    使用 sb 或者 xib 给控件拖线的时候,拖出来的线属性都是用 weak 修饰,原因是由于在向 xib 或者 sb 里面添加控件的时候,添加的子视图是添加到了根视图 View 上面, 而 控制器 Controller 对其根视图 View 默认是强引用的,当我们的子控件添加到 view 上面的时候, [self.view addSubView: xxx]这个方法会对添加的控件进行强引用,如果在用 strong 对添加的子控件进行修饰的话,相当于有两条强指针对子控件进行强引用, 为了避免这种情况,所以用 weak 修饰。

    在纯手码实现界面布局时,如果通过懒加载处理界面控件,需要使用strong强指针。假如你是弱引用,在removeFromSuperview的时候将自动引用计数-1,等你第二次addSubview的时候,这个view可能已经被释放了,就会造成崩溃。

    在ARC中,对象释放的最终根据还是根据引用计数为0时去释放。而weak与strong的根本区别是在set方法中,weak的set方法和strong的set方法都是释放旧值保留新值,但是weak的set方法会对其autorelease,即延迟release一次,而strong的set方法也是释放旧值保留新值,但是其不会延迟release。最终效果是strong会+1,weak不会+1。

    //关于copy的深拷贝,浅拷贝,以及相关引用计数
    浅拷贝:拷贝地址,仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
    深拷贝Deep Copy:在计算机中开辟了一块新的内存地址用于存放复制的对象。

    Copy在Objetive-C中的实现方式。如果要调用一个对象的copy方法,这个对象必须遵循NSCopying的协议。这个协议中规定了一个方法:- (id)copyWithZone:(NSZone *)zone;我们就是通过实现这个方法给对象提供拷贝的功能。对于很多现有类,如NSString,NSDictionary...这个方法已经实现。假设我们现在自定义了一个类,需要为这个类提供拷贝的功能,就需要自己来动手写CopyWithZone的方法。

    实际使用中区分深拷贝和浅拷贝有个技巧,[string copy]就是浅拷贝,[string mutableCopy]就是深拷贝,前者返回的NSString在runtime下“真身”是__NSCFConstantString,而NSMutableString的“真身”是__NSCFString,然后我们就能很清楚的看到,只要是copy得到的值就是不可变类型,而mutablecopy得到的是可变类型。

    相关文章

      网友评论

          本文标题:关于OC修饰词的反思

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