iOS 开发中常见Property关键字解读
来源:互联网 发布:河边软件职业技术学院 编辑:程序博客网 时间:2024/06/07 22:46
(一) weak assgin retain strong unsafe_unretained copy
背景
ARC苹果新引用了strong
与 weak
对象变量属性。
ARC引入了新的对象的新生命周期限定,即零弱引用。如果零弱引用指向的对象被deallocated的话,零弱引用的对象会被自动设置为nil。
strong 与 weak 强应用与弱引用
强引用也就是我们通常所讲的引用,其存亡直接决定了所指对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示列表中,则此对象会被从内存中释放。
弱引用除了不决定对象的存亡外,其它与强引用相同。即使一个对象被持有无数个若引用,只要没有强引用指向他,那么其还是会被清除。
使用强引用指向的对象,引用计数器会+1
使用弱引用指向的对象,引用计数器不变化
strong 与 retain
在ARC下,用strong代替了retain,strong等同于retain。
声明Block,使用retain,Block会在++栈++中。必须使用copy关键字,才能使Block在堆中。
声明Block, 使用strong,Block会在++堆++中。
weak 与assign
assign: 简单赋值,不更改索引计数
weak比assign多了一个功能,当对象消失后自动把指针变成nil
一个简单例子
@interface ViewController ()@property (nonatomic, weak) NSDate *weakDate;@property (nonatomic, assign) NSDate *assignDate;@property (nonatomic, strong) NSDate *strongDate;@end
_strongDate = [NSDate date];_weakDate = _strongDate;_assignDate = _strongDate;NSLog(@"_strongDate %p, %p, %@", _strongDate, &_strongDate, _strongDate);NSLog(@"_weakDate %p, %p, %@", _weakDate, &_weakDate, _weakDate);NSLog(@"_assignDate %p, %p, %@", _assignDate, &_assignDate, _assignDate);_strongDate = nil;NSLog(@"\n"); NSLog(@"_strongDate : %@", _strongDate);NSLog(@"_weakDate : %@", _weakDate);NSLog(@"_assignDate : %@", _assignDate);
_strongDate 0x60400000c160, 0x7f997ec38608, Wed Nov 15 10:38:24 2015_weakDate 0x60400000c160, 0x7f997ec385f0, Wed Nov 15 10:38:24 2015_assignDate 0x60400000c160, 0x7f997ec385f8, Wed Nov 15 10:38:24 2015_strongDate : (null)_weakDate : (null)(lldb)
小结:
- weak 修饰对象时候,当对象被释放掉后,指针会指向 nil
- strong 修饰对象时候,当对象被释掉后,指针会指向 nil
- assgin 修饰对象时候,当对象被释掉后,会产生悬空指针,再次调用会导致程序崩溃。
- assgin 一般用在修饰基础数据类型
后期新增 ++unsafe_unretained++(等价assgin)
__unsafe_unretained 主要跟 C 代码交互。另外 __weak 是有代价的,需要检查对象是否已经消亡,而为了知道是否已经消亡,自然也需要一些信息去跟踪对象的使用情况。__unsafe_unretained 比 __weak 快。当明确知道对象的生命期时,选择 __unsafe_unretained 会有一些性能提升。当 A 拥有 B 对象,当 A 消亡时 B 也消亡。这样当 B 存在,A 就一定会存在。而 B 又要调用 A 的接口时,B 就可以存储 A 的 __unsafe_unretained 指针。
在细微不同的方式下,__unsafe_unretained和__weak都防止了参数的持有。对于__weak,指针的对象在它指向的对象释放的时候回转换为nil,这是一种特别安全的行为。就像他的名字表达那样,__unsafe_unretained会继续指向对象存在的那个内存,即使是在它已经销毁之后。这会导致因为访问那个已释放对象引起的崩溃。
__weak只支持iOS 5.0和OS X Mountain Lion作为部署版本。如果你想部署回iOS 4.0和OS X Snow Leopark,你就不得不用__unsafe_unretained标识符。(了解即可)
(二) 原子性和非原子性 atomic和 nonatomic
//@property(nonatomic, retain) UITextField *userName;//系统生成的代码如下:- (UITextField *) userName { return userName;}- (void) setUserName:(UITextField *)userName_ { [userName_ retain]; [userName release]; userName = userName_;}
而 atomic 版本的要复杂一些
//@property(retain) UITextField *userName;//系统生成的代码如下:- (UITextField *) userName { UITextField *retval = nil; @synchronized(self) { retval = [[userName retain] autorelease]; } return retval;}- (void) setUserName:(UITextField *)userName_ { @synchronized(self) { [userName release]; userName = [userName_ retain]; }}
简单来说,就是 atomic 会加一个锁来保障线程安全,并且引用计数会 +1,来向调用者保证这个对象会一直存在。假如不这样做,如有另一个线程调 setter,可能会出现线程竞态,导致引用计数降到0,原来那个对象就释放掉了。要注意那个锁++并不能++『保证线程安全』
(三) 深复制与浅复制
概念
对象拷贝有两种方式:浅复制和深复制。
浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针。
深复制, 是直接拷贝整个对象内存到另一块内存中。
再简单些说:浅复制就是指针拷贝;深复制就是内容拷贝。
copy与mutableCopy方法
- copy返回immutable(不可变)对象;
- mutableCopy返回mutable对象;
1、 NSString非集合类对象的copy与mutableCopy
场景1: 原对象为immutable不可变对象
NSString *origin = @"origin";NSString *stringCopy = [string copy];NSMutableString *stringMCopy = [string mutableCopy];
可以通过查看内存,可以看到 stringCopy 和 origin 的地址一样的,进行了指针的拷贝。而 stringMCopy 的地址和 origin 不一样,进行了内容拷贝;
场景2: 原对象为mutable可变对象
NSMutableString *origin = [NSMutableString stringWithString: @"origin"];NSString *stringCopy = [origin copy];NSMutableString *mStringCopy = [origin copy];NSMutableString *stringMCopy = [origin mutableCopy];origin : 0x60000024f630, 0x7fff5d559788, originstringCopy : 0xa006e696769726f6, 0x7fff5d559780, origin_strongString : 0xa006e696769726f6, 0x7fff5d559778, originstringMCopy : 0x600000248580, 0x7fff5d559770, origin
看内存,发现 string、stringCopy、mStringCopy、stringMCopy 四个对象的内存地址都不一样,说明此时都是做内容拷贝。
综上两个例子,我们可以得出结论:
在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;对mutable对象进行copy和mutableCopy都是内容复制。用代码简单表示如下:
- [immutableObject copy] // 浅复制
- [immutableObject mutableCopy] //深复制
- [mutableObject copy] //深复制
- [mutableObject mutableCopy] //深复制
2、 NSArray集合类对象的copy与mutableCopy
集合类对象是指NSArray、NSDictionary、NSSet … 之类的对象。:
场景1: 原对象为immutable不可变对象
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];NSArray *copyArray = [array copy];NSMutableArray *mCopyArray = [array mutableCopy];array : 0x60000003ef00, 0x7fff558cb750copyArray : 0x60000003ef00, 0x7fff558cb748mCopyArray : 0x6000002596b0, 0x7fff558cb740
查看内容,可以看到copyArray和array的地址是一样的,而mCopyArray和array的地址是不同的。说明copy操作进行了指针拷贝,mutableCopy进行了内容拷贝。
需要强调的是:此处的内容拷贝,仅仅是拷贝array这个对象,array集合内部的元素仍然是指针拷贝。(可以自行去验证)
场景2: 原对象为immutable不可变对象
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"",@"b",@"c",nil];NSArray *copyArray = [array copy];NSMutableArray *mCopyArray = [array mutableCopy];array : 0x60000025ce00, 0x7fff57481788copyArray : 0x600000441aa0, 0x7fff57481780mCopyArray : 0x60000025d8b0, 0x7fff57481778
copyArray、mCopyArray和array的内存地址都不一样,说明copyArray、mCopyArray都对array进行了内容拷贝。
综上两个例子,我们可以得出结论:
在集合类对象中,对immutable对象进行copy,是指针复制,mutableCopy是内容复制;对mutable对象进行copy和mutableCopy都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //单层深复制
[mutableObject copy] //单层深复制
[mutableObject mutableCopy] //单层深复制
单层深复制: 容器对象进行深拷贝,容器内部对象浅拷贝。
p str 会打印对象本身的内存地址和对象内容po &str 则打印的是引用对象的指针所在的地址
- iOS 开发中常见Property关键字解读
- IOS开发中常见的关键字
- IOS开发 @property中assign、copy 、retain等关键字的理解
- IOS开发 @property中assign、copy 、retain等关键字的理解
- [IOS]在xcode开发编译环境中@property关键字的理解
- IOS开发 @property中assign、copy 、retain等关键字的理解
- IOS开发 @property中assign、copy 、retain等关键字的理解
- [iOS] ARC, @property 关键字
- iOS中属性@property中的关键字的使用说明
- iOS中property属性的关键字(史上最详解)
- ios开发中@property的属性介绍
- ios开发中@property的属性介绍
- iOS开发中@property的属性介绍
- iOS开发中@property的属性介绍
- iOS开发中@property的属性介绍
- iOS开发中@property的属性介绍
- iOS开发中@property的属性介绍
- iOS开发中@property的属性介绍
- Property xx cannot be found in forward class object "XXXX"
- 单linux服务器同时拨多条ADSL和挂多个固定公网ip通过squid实现代理池方案
- 编辑平台图层IP占用后解决办法
- MySQL中文乱码问题
- 2017软考考前准备必看
- iOS 开发中常见Property关键字解读
- MongoDB 之 用户管理
- jq.validate 中自定义方法根据不同的业务给出不同的提示信息(2017.05.19)
- ffmpeg开发之旅(3):AAC编码格式分析与MP4文件封装(MediaCodec+MediaMuxer)
- FCC--Chunky Monkey(数组分组)和Slasher Flick(截断数组)
- javascript原理
- Android 高德的路线规划一个小坑
- ImportError: No module named input_data
- jQuery版本的区分