OC属性关键字

目录

一、nonatomic与atomic

二、assign、strong、retain、weak、copy和unsafe_unretained

三、readonly和readwrite


一、nonatomic与atomic

        决定编译器生成的getter和setter是否为原子操作(即是否线程安全),也可以理解为属性是否适合在多线程的场景下使用。

        atomic:在声明属性的时候,默认选择的是该属性。该属性是一个原子属性,使用了这个属性后,系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。getter 总是能得到一个完好无损的对象(可以保证数据的完整性),具体的实现方法是编译器会自动生成一些互斥加锁代码,如果发现有其它线程正在执行锁定的代码,线程会用死循环的方式,一直等待锁定的代码执行完成,以此避免读写不同步问题。

        nonatomic:该属性是一个非原子属性,如果该对象无需考虑多线程的情况,可以加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。nonatomic返回的对象可能不是完整的value,但nonatomic的处理速度要比atomic快。

OC中的锁:互斥锁和自旋锁

共同点:使程序在同一时间只有一个线程访问

互斥锁:1.读写方法都是线程安全的

                2.如果发现其他线程正在执行锁定代码,线程会进入休眠(就绪状态),等其它线程时间片到打开锁后,线程会被唤醒(执行)。

自旋锁:1.单写多读,即写的时候是线程安全的,但是读的时候是非线程安全的

                2.如果发现有其他线程正在执行锁定的代码,就会进入到死循环,直到被锁定的代码执行完成,自旋锁更适合执行不耗时的代码

二、assign、strong、retain、weak、copy和unsafe_unretained

        这几个关键字是内存管理特性,可以决定程序的引用计数类型。

        assign:对属性只是简单赋值,不更改对所赋的值的引用计数,这个指示符主要适用于NSInteger等基本类型,以及short、float、double、结构体等各种C数据类型。它是一个弱引用声明类型,我们一般不使用assign来修饰对象,因为被assign修饰的对象,在被释放掉以后,指针的地址还是存在的,也就是说指针不会被置为nil,造成野指针,可能导致程序崩掉。那为什么assign就能用来修饰基本数据类型呢,是因为基本数据类型一般分布在栈上,栈的内存会由系统自动处理,因此不会造成野指针。

        weak:该属性也是一个弱引用声明类型,使用weak修饰的对象是不会造成引用计数器+1的,并且引用的对象如果被释放了以后会自动变成nil,不会出现野指针,很好的解决了内存引起的崩溃情况。通常我们会在block和协议的时候使用weak修饰,通过这样的修饰,我们可以规避掉循环引用的问题。

        strong:​​​​​​​该属性是一个强引用声明类型,只要该强引用指向被赋值的对象,那么该对象就不会自动回收。

         retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1;在ARC模式下很少使用,通常用于指针变量,就是说你定义了一个变量,然后这个变量在程序的运行过程当中会改变,并且影响到其他方法。一般用于字符串、数组等

        copy:若使用copy指示符,则调用setter方法给变量赋值的时候,会将被赋值的对象复制一个副本,再将该副本赋值给成员变量。copy指示符会将原成员变量所引用对象的计数减1。
         相当于就是说,不用copy的话,会创建一个新的空间,它的内容和原对象内容一模一样,然后指针是指向新空间的。当再有什么操作在对那个对象操作的话,只是在原空间上操作,对新空间没有影响。当成员变量的类型是可变类型,或其子类是可变类型的时候,被赋值的对象有可能在赋值后被修改,如果程序不需要这种修改影响setter方法设置的成员变量的值,此时就可考虑用copy指示符。

copy与retain的区别: 
copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。 
eg:   一个NSString 对象,地址为0×1111 ,内容为@”STR” 
Copy 到另外一个NSString 之后,地址为0×2222 ,内容相同,新的对象retain为1 ,旧有对象没有变化 
retain 到另外一个NSString 之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1 
也就是说,retain 是指针拷贝,copy 是内容拷贝。 

        unsafe_unretained:类似于assign,在离开作用域后不会自动赋值为nil,适用于“对象类型”,该特质表达一种“非持有关系” 。unsafe_unretained与其他几种属性关键字的区别在于引用计数类型不同。unsafe_unretained表示不可变的指针引用,不会自动释放内存,需要手动释放。strong表示可变的指针引用,会自动释放内存;weak表示弱引用,不会增加引用计数,当对象被释放时,弱引用会自动变为nil。另外,copyretain表示指针拷贝,会增加引用计数,而assign表示指针赋值,不会增加引用计数。

强引用和弱引用:OC里ARC中的强引用和弱引用_oc 强引用例_AlgolStep的博客-CSDN博客

深浅拷贝:​​​​​​​OC学习之——Foundation框架_晓美焰丶的博客-CSDN博客——深复制与浅复制

        strong和copy的区别:用一个实例说明:

首先,我们自定义一个Test类,该类有两个属性,都是可变字符串,属性关键字一个是copy一个是strong。

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Test : NSObject

@property (nonatomic, copy) NSMutableString *strTest1;
@property (nonatomic, strong) NSMutableString *strTest2;

@end

NS_ASSUME_NONNULL_END

然后在主函数中创建一个该类的实例对象, 然后使用NSMutableString型变量对该实例对象中的两个属性赋值。

#import <Foundation/Foundation.h>
#import "Test.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Test *t1 = [[Test alloc] init];
        
        NSMutableString *str1 = [NSMutableString stringWithString:@"test1"];
        t1.strTest1 = str1;
        
        NSMutableString *str2 = [NSMutableString stringWithString:@"test2"];
        t1.strTest2 = str2;
        
        NSLog(@"%p",t1.strTest1);
        NSLog(@"%p",str1);
        NSLog(@"%p",t1.strTest2);
        NSLog(@"%p",str2);
    }
    return 0;
}

结果发现:使用copy关键字的字符串属性的strTest1和str1的地址不相同,即没有指向同一个对象,这是一次深拷贝;而使用strong关键字的strTest2和str2的地址相同,即指向了同一个对象,这是一次浅拷贝。原因是我们前面说过,strong是一个强引用类型,因此str2会持有strTest2所持有的对象,并使strTest2的引用计数加一,此时就是一个浅拷贝,而copy就不会这样。这就是strong和copy的区别。

三、readonly和readwrite

        这个就是访问权限的控制,决定该属性是否可读和可写,默认是readwrite,所以我们定义属性的时候,一般不需要这个修饰。只有只读属性才需要加上readonly的修饰。
    readonly来控制读写权限的方式就是只生成getter方法,不生成setter方法。                

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值