objective-c中的特性

一,retain, copy, assign区别 

概念: 
assign: 简单赋值,不更改索引计数(reference counting)。 
copy: 创建一个索引计数为1的对象,而后释放旧对象 
retain:释放旧的对象,将旧对象的值赋予输入对象,再提升输入对象的索引计数为1 

例: 
nsstring *pt = [[nsstring alloc] initwithstring:@"abc"]; 
上面一段代码会执行如下两个动做 
1 在堆上分配一段内存用来存储@"abc"  好比:内存地址为:0x1111 内容为 "abc" 
2 在栈上分配一段内存用来存储pt  好比:地址为:0xaaaa 内容天然为0x1111   
下面分别看下assign retain copy 
assign的状况:nsstring *newpt = [pt assign];     
此时newpt和pt彻底相同 地址都是0xaaaa  内容为0x1111  即newpt只是pt的别名,对任何一个操做就等于对另外一个操做。 所以retaincount不须要增长。 
retain的状况:nsstring *newpt = [pt retain];     
此时newpt的地址再也不为0xaaaa,可能为0xaabb 可是内容依然为0x1111。 所以newpt 和 pt 均可以管理"abc"所在的内存。所以 retaincount须要增长1   
copy的状况:nsstring *newpt = [pt copy];   
此时会在堆上从新开辟一段内存存放@"abc" 好比0x1122 内容为@"abc 同时会在栈上为newpt分配空间 好比地址:0xaacc 内容为0x1122 所以retaincount增长1供newpt来管理0x1122这段内存 
  
理解: 
1,假设你用malloc 分配了一块内存,并把它的地址赋值给了指针a,   后来你但愿指针b也共享这段内存,因而你又把a赋值给  (assign)了 b。此时a和b指向同一块内存,当a不须要使用这段内存时是不能直接释放它,由于a并不知道 b也在使用这块内存,若是 a释放了,那么b在使用这块内存的时候程序会crash掉 
2,为了解决1中的问题,最简单的一个方法就是使用引用计数,在上面的那个例子中,咱们给那块内存设一个引用计数,当内存被分配而且赋值给a时,引用计数是1。当把a赋值给b时引用计数增长到 2。这时若是a再也不使用这块内存,它只须要把引用计数减1,代表本身再也不拥有这块内存。b再也不使用这块内存时也把引用计数减1。当引用计数变为0的时候, 表明该内存再也不被任何指针所引用,系统能够把它直接释放掉。 
3. 上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引发1中的问题,当数据为int, float等原生类型时,可使用assign。retain就如2中所述,使用了引用计数,retain引发引用计数加1, release引发引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。 
4.copy是在你不但愿a和b共享一块内存时会使用到。a和b各自有本身的内存。 

总结: 
使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等) 
使用copy: 对NSString 
使用retain: 对其余NSObject和其子类 

二,ios5中新加入RAC的strong,week,unsafe_unretained 

说明: 
iOS5中新的关键字strong, weak, unsafe_unretained. 能够与之前的关键字对应学习strong与retain相似,weak与unsafe_unretained功能差很少(有点区别,等下会介绍,这两个新关键字与assign相似)。在iOS5中用这些新的关键字,就能够不用手动管理内存了 
具体使用: 
strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切 

    1.    @property (nonatomic, strong) NSString *string1;   
    2.    @property (nonatomic, strong) NSString *string2;  

// 附注:nonatomic关键字: 

 noatomic是Objc使用的一种线程保护技术,基本上来说,是防止在写未完成的时候被另一个线程读取,形成数据错误。而这种机制是耗费系统资源的,因此在iPhone这种小型设备上,若是没有使用多线程间的通信编程,那么nonatomic是一个很是好的选择。 

有这样两个属性, 

    1.    @synthesize string1;   
    2.    @synthesize string2;  

猜一下下面代码将输出什么结果? 

    1.    self.string1 = @"String 1";   
    2.    self.string2 = self.string1;   
    3.    self.string1 = nil;  
    4.    NSLog(@"String 2 = %@", self.string2);  

结果是:String 2 = String 1 

因为string2是strong定义的属性,因此引用计数+1,使得它们所指向的值都是@"String 1", 若是你对retain熟悉的话,这理解并不难。 

接着咱们来看weak关键字: 
若是这样声明两个属性: 

    1.    @property (nonatomic, strong) NSString *string1;   
    2.    @property (nonatomic, weak) NSString *string2;  

并定义 

    1.    <pre name="code" class="cpp">@synthesize string1;   
    2.    @synthesize string2;  


再来猜一下,下面输出是什么? ios

    1.    self.string1 = @"String 1";   
    2.    self.string2 = self.string1;   
    3.    self.string1 = nil;  
    4.    NSLog(@"String 2 = %@", self.string2);  

结果是:String 2 = null 

分析一下,因为self.string1与self.string2指向同一地址,且string2没有retain内存地址,而self.string1=nil释放了内存,因此string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。 

接着咱们来看unsafe_unretained 
从名字能够看出,unretained且unsafe,因为是unretained因此与weak有点相似,可是它是unsafe的,什么是unsafe的呢,下面看实例。 
若是这样声明两个属性: 
并定义 
    1.    @property (nonatomic, strong) NSString *string1;   
    2.    @property (nonatomic, unsafe_unretained) NSString *string2;  

再来猜一下,下面的代码会有什么结果? 
    1.    self.string1 = @"String 1";   
    2.    self.string2 = self.string1;   
    3.    self.string1 = nil;  
    4.    NSLog(@"String 2 = %@", self.string2);  

请注意,在此我并无叫你猜会有什么输出,由于根本不会有输出,你的程序会crash掉。 

缘由是什么,其实就是野指针形成的,因此野指针是可怕的。为什么会形成野指针呢?同于用unsafe_unretained声明的指针,因为self.string1=nil已将内存释放掉了,可是string2并不知道已被释放了,因此是野指针。而后访问野指针的内存就形成crash.  因此尽可能少用unsafe_unretained关键字。 

strong,weak, unsafe_unretained每每都是用来声明属性的,若是想声明临时变量就得用__strong,  __weak, __unsafe_unretained,  __autoreleasing, 其用法与上面介绍的相似。 
仍是看看实例吧。 

    1.    __strong NSString *yourString = @"Your String";   
    2.    __weak  NSString *myString = yourString;   
    3.    yourString = nil;   
    4.    __unsafe_unretained NSString *theirString = myString;  
    5.    //如今全部的指针都为nil  

再看一个: 

    1.    __strong NSString *yourString = @"Your String";   
    2.    __weak  NSString *myString = yourString;   
    3.    __unsafe_unretained NSString *theirString = myString;  
    4.    yourString = nil;   
    5.    //如今yourString与myString的指针都为nil,而theirString不为nil,可是是野指针。
相关文章
相关标签/搜索