iOS ------ 关键字
关键字可以分为以下六类
- 修饰器类型:@property、@synthesize、@dynamic
- 原子安全类型: nonatomic、atomic
- 计数引用类型: strong、weak、assign、copy、retain、unsafe_unretained
- 读写类型:readonly,readwrite
- 访问类型:extern、static、const
- 局部引用类型:__weak、__block、__strong
1、修饰器类型:@property、@synthesize、@dynamic
1.1@property
@property (nonatomic,copy) NSString *str;
用来声明属性,相当于声明了_str,并且默认实现了str的getter和setter方法
1.2synthesize
#import "ClassA.h"
@interface ClassA()
@property NSString * str3;
@end
@implementation ClassA
// 或者写成 @synthesize str3
@synthesize str3 = str4;
@end
@synthesize要用的话,必须得声明了同名的属性,例如我已经声明了str3,再用@synthesize声明str3,那么就相当于编译器默认生成了一个str3属性和一个str3成员变量.str3的getter个setter实际上操作的都是str4
1.3@dynamic
@dynamic声明属性就相当于告诉编译器不用生成属性的getter和setter方法,该属性的getter和setter方法由我自己生成
2、原子安全类型: nonatomic、atomic
这两个类型就是跟线程相关的,atomic与nonatomicd的主要区别就是系统自动生成的getter/setter方法不一样。
2.1、nonatomic
nonatomic(默认情况)表示非原子属性,也就是线程不安全类型,系统自动生成的getter/setter方法不会进行加锁操作。其内部的具体实现如下:
@property (nonatomic,strong) UIImage *image0;
@synthesize image0 = _image0;
/// MRC模式下
- (UIImage *)image0{
return _image0;
}
- (void)setImage0:(UIImage *)image0 {
if (_image0 != image0) {
[_image0 release];
_image0 = [[image0 retain] autorelease];
}
}
2.2、atomic
atomic
表示原子属性,表示线程安全,系统自动生成的getter/setter
方法会进行加锁操作。其内部的具体实现如下:
@property (atomic,strong) UIImage *image1;
@synthesize image1 = _image1;
/// MRC模式下
- (UIImage *)image1 {
@synchronized (self) {
return _image1;
}
}
- (void)setImage1:(UIImage *)image1 {
@synchronized (self) {
if (_image1 != image1) {
[_image1 release];
_image1 = [[image1 retain]autorelease];
}
}
}
atomic修饰的属性也不一定安全,当修饰NSMutableArray
时,当我们进行remove
和add
的时候,此时也不是线程安全的,它不是原子操作。它保证的是getter
和setter
的线程安全。
3、计数引用类型: strong、weak、assign、copy、retain、unsafe_unretained
3.1 strong
当使用strong关键字修饰一个属性时,该属性不仅指向该对象,而且拥有该对象。该对象的引用计数会加1,属于强引用用。在ARC环境下,相当于retain。也称为浅拷贝(指针拷贝)。内存地址不变,只是生成了一个新的指针,新指针和引用对象的指针指向同一个地址。
注意:因为使用的是同一个内存地址,当该内存地址存储的内容发生变更的时候。属性也会变更。
3.2weak
同样经常用于修饰OC对象类型的数据,修饰的对象在释放后,指针地址会自动被置为nil,这是一种弱引用。
注意:在ARC环境下,为了避免循环引用,会把delegate属性用weak修饰,在MRC环境下使用assign修饰。当一个strong类型的指针不在指向它的时候,它就会被释放,即使还有weak的指针指向他,这些weak指针也会被值为nil。
weak属性修饰的变量,如何实现在变量没有强引用后自动置为 nil ?
runtime 维护了一个weak_table_t 弱引用表
,用于存储指向某一个对象的所有weak指针。weak表其实是一个哈希表,key是所指对象的地址,value是weak指针的地址的数组。在对象回收的时候,根据对象的地址将所有weak指针地址的数组,遍历数组把其中的数据置为nil。
3.3 assign
一般用来修饰非指针变量,用于基础数据类型 (例如NSInteger)和C数据类型(int, float, double, char, 等),另外还有id类型。也可用来修饰对象,但被assign修饰的额对象被释放后后,指针还是指针对象之前的地址,就变成了野指针。(如果用了assign修饰的对象,需要在dealloc函数中将该对象指针手动值为nil,可以消除野指针。
3.4 copy
copy和strong相同点在于都是属于强引用,都会是属性的计数加一,但是copy和strong不同点在于,它所修饰的属性当引用一个属性值时,是内存拷贝(深拷贝),就是在引用是,会生成一个新的内存地址和指针地址来,和引用对象完全没有相同点,因此它不会因为引用属性的变更而改变(当引用的属性值是不可变对象时,是浅拷贝)
具体的用例可以参考:strong和copy的区别
copy修饰的关键字不同在于属性setter的有一个关键语句:
_copyyStr = [copyyStr copy];
所以只有在用点语法赋值时copy关键字才会生效
@property (copy) NSMutableString* name;
如果用copy
来修饰NSMutableArray
,NSMutableDictionary
,NSMutableString
这种不可变对象会导致问题,初始化后通过copy生成的是该类型对应的不可变对象,例如NSArray
、NSDictionary
、NSString
。如果我们按照可变对象进行修改属性操作,就有可能报错。
3.5 retain
retain主要用在MRC模式下,作用和strong几乎等同
3.6 unsafe_unretained
unsafe_unretained
类型指针指向一块内存时,内存的引用计数也不会增加,这一点与weak
一致。但是与weak
类型不同的是,当其所指向的内存被销毁时,unsafe_unretained
类型的指针并不会被赋值为nil
,也就是变成了一个野指针。对野指针指向的内存进行读写,程序就会crash
4,读写类型 readonly readwrite
4.1 readonly
readonly
相当于是系统只会默认生成该属性的getter
方法,只可读不可写,用点属性的形式去赋值,那么就会编译报错。
如果是在该类的外部访问readonly
属性,利用kvc
直接赋值。可以通过在类的内部重写accessInstanceVariablesDirectly
,固定返回No
,那么外界就无法再通过kvc
形式来更改
4.2 readwrite
readwrite
就是声明该属性可读可写,一般默认就是readwrite
,可以不用额外声明
5, 访问类型
5.1 extern
对于跨文件访问全局变量需要借助extern
关键字声明,通过extern
有两种方式可以访问其他文件的全局变量。
方式一
我们想要在B类访问A类中声明和定义的全局变量时,不导入A类的头文件,在B类中使用extern声明A类中的全局变量
方式二
我们在A.m文件中声明和定义的全局变量时,同时在A.h文件中做extern声明,在B类访问A类中全局变量时导入A的头文件就可以了,这种方式在代码中比较常见。
5.2 static
static
除了可以修饰全局变量,还可以修饰局部变量,被static修饰的变量叫做静态变量。
主要作用:
- 隐藏
当程序有多个文件时,将全局变量或函数的作用域的作用范围限制在当前文件,对其他文件隐藏 - 保持变量内容的持久化
将函数的局部变量储存在全局数据区,使它不会随着函数的调用结束而被销毁
5.3 const
const用于修饰指针变量和基本数据类型,const放在谁前面,谁就是常量不可在更改。
不管是extern
声明的全局变量还是用static
、const
修饰的全局变量和局部变量,它们的生命周期都是从定义到程序结束。
6,局部引用类型:__weak,__strong,__unsafe_unretained,__autoreleasing
- __strong
-
- 强引用持有对象,可以对应 strong、retain、copy 关键字。
-
- 编译器将为 strong、retain、copy 修饰的属性生成带 __strong 所有权修饰符的实例变量.
- __weak
-
- 弱引用持有对象,对应 weak 关键字,ARC下用来防止循环引用。
-
- 编译器将为 weak 修饰的属性生成带 __weak 所有权修饰符的实例变量。
- __unsafe_unretained
-
- 弱引用持有对象,对应 unsafe_unretained、assign 关键字,MRC下用来防止循环引用。
-
- 编译器将为 unsafe_unretained 修饰的属性生成带 __unsafe_unretained 所有权修饰符的实例变量。
-
- 与 __weak 相比,它不需要遍历 weak 表来检查对象是否 nil,性能上要更好一些。但是它会产生悬垂指针
- __autoreleasing
+在 MRC 中我们可以给对象发送 autorelease 消息来将它注册到 autoreleasepool 中,而在 ARC 中我们可以使用 __autoreleasing 修饰符修饰对象将对象注册到 autoreleasepool 中。
原文地址:https://blog.csdn.net/m0_73974056/article/details/140619625
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!