iOS-@property-所有权修饰符

2018-05-19  本文已影响21人  明若晴空

自己生成的对象,自己所持有;

非自己生成的对象,自己也能持有;

自己持有的对象不再需要时释放;

非自己持有的对象无法释放;

所有权修饰符:

OC将变量类型定义为id类型或各种对象类型;类型上必须附加所有权修饰符。

所有权修饰符共有四种:

strong修饰符; weak修饰符;

unsafe_unretained修饰符; autoreleasing修饰符;

strong修饰符: strong修饰符是id类型和对象类型默认的所有权修饰符。

strong修饰符表示对对象的“强引用”。持有强引用的变量在超出其作用域时被废弃,随着强引用的失效,引用的对象会随之释放。 strong修饰符的变量,不仅仅只在变量作用域中,在赋值上也能够正确的管理对象的所有者。

通过废弃带__strong修饰符的变量(变量作用域结束或者成员变量所属对象废弃)或者对变量赋值,都可以做到“不再需要自己持有对象时释放”。

weak修饰符: strong修饰符虽然已经能解决大部分内存管理的问题,但是有些重大问题还是不能解决,比如循环引用的问题。

循环引用容易引发内存泄漏的问题。

循环引用包括,对象之间互相引用,以及对象对自身的引用。

weak修饰符可以避免循环引用。weak修饰符提供弱引用,弱引用不能持有对象实例。

在持有某个对象的弱引用时,若该对象被废弃,则此弱引用将自动失效且处于nil状态。

weak修饰符只能用于iOS5以上及OS X Lion以上版本的应用程序。

iOS4以及OS X Snow Leopard的应用程序中可使用

unsafe_unretained修饰符来代替。

unsafe_unretained修饰符: unsafe_unretained修饰符和weak修饰符在使用上是一样的。

但是在使用

unsafe_unretained修饰符赋值给附有strong修饰符的变量时,有必要确保被赋值的对象确实存在。

这种修饰符存在的原因就是因为在iOS4以及OS X Snow Leopard的应用程序中,需要使用其来代替

weak修饰符。赋值给附有__unsafe_unretained修饰符变量的对象在通过该变量使用时,如果没有确保其确实存在,那么应用程序可能就会崩溃。

__autoreleasing修饰符:

后续再加

常用的@property属性有:

strong:强引用。ARC中不再使用retain,使用strong替代,因此strong和retain同义,可使对象的引用数加1;

weak:弱引用。不持有对象,不会对对象的引用计数加1;当对象被释放后,会指向nil,不会产生野指针;一般在可能出现循环引用的情况下是呀,如delegate。

assign:修饰非对象类型和基础数据类型的属性,不涉及内存管理,因此也不会被引用计数。

copy:创建一个新的对象,新对象的引用计数+1,但不会改变原来的对象的引用计数。

nonatomic:和atomic相对,是非原子性操作,非线程安全;

atomic:原子性操作,线程安全,但是会影响性能;

readwrite:可读可写,getter/setter

readonly:可读不可写,getter

writeonly:可写不可读,setter

NSString为什么要用copy修饰,而不是strong?

copy和strong修饰的区别,其实只在传入NSMutableString的表现上有所区别。下面举例来说明,代码如下:

NSString *strTest = [NSString stringWithFormat:@"hello!"];

    self.strStrong= strTest;

    self.strCopy= strTest;

    NSLog(@"strTest = %@, content = %p, address = %p", strTest, strTest, &strTest);

    NSLog(@"self.strStrong = %@ content = %p, address = %p", _strStrong, _strStrong, &_strStrong);

    NSLog(@"self.strCopy = %@ content = %p, address = %p", _strCopy, _strCopy, &_strCopy);

    NSMutableString *mutabllStrTest = [NSMutableString stringWithFormat:@"How are you?"];

    self.strStrong= mutabllStrTest;

    self.strCopy= mutabllStrTest;

    NSLog(@"mutabllStrTest = %@, content = %p, address = %p", mutabllStrTest, mutabllStrTest, &mutabllStrTest);

    NSLog(@"self.strStrong = %@, content = %p, address = %p", _strStrong, _strStrong, &_strStrong);

    NSLog(@"self.strCopy = %@, content = %p, address = %p", _strCopy, _strCopy, &_strCopy);

    [mutabllStrTestappendString:@"  I'm fine."];

    NSLog(@"---------------------------------------");

    NSLog(@"mutabllStrTest = %@, content = %p, address = %p", mutabllStrTest, mutabllStrTest, &mutabllStrTest);

    NSLog(@"self.strStrong = %@, content = %p, address = %p", _strStrong, _strStrong, &_strStrong);

    NSLog(@"self.strCopy = %@, content = %p, address = %p", _strCopy, _strCopy, &_strCopy);

首先分别声明strong和copy修复的变量;

然后我们将NSString类型的字符串赋给这两个变量:

根据打印的字符串内容和内存地址,可以看出: strStrong和 strCopy都指向NSString的 strTest地址,并且指向的内容也是相同的。也就是说, strStrong和 strCopy对strTest都做了浅拷贝,只拷贝了其指向的内容。

而当我们将 NSMutableString类型的字符串复制给这两个变量时:

根据打印的字符串内容和内存地址,可以看出:strStrong仍然指向的是 mutabllStrTest的地址,而strCopy则是对mutabllStrTest做了一次深拷贝,也就是对strCopy指向了一个新生成的对象,这个对象的内容和mutabllStrTest暂且保持一致。这个strCopy新生成的对象不会使mutabllStrTest的引用计数发生变化。

而当我们对NSMutableString类型的mutabllStrTest做了一些变化时,可以发现:strStrong跟随mutabllStrTest做了变化,而strCopy依然是如复制初时的样子。

因此,当传入的字符串为NSString类型时,copy和strong的效果是一致的。但是如果是NSMutableString类型,就要注意copy和strong的修饰符了。

上一篇 下一篇

猜你喜欢

热点阅读