iOS开发知识点:理解assign,copy,retain变strong

 

一、.h和.m文件的变化说明

 

1.对于.h头文件,主要是将属性定义由retain变为strong 

 

  1. @property (retain, nonatomic)  

变为

  

  1. @property (strong, nonatomic)  


2.在ARC之前,我们经常在.m中使用分类拓展来增加私有的property

 

  1. @interface MJViewController ()  
  2. @property (nonatomic, retain) NSArray *data;  
  3. @end  

这 样做主要是简化实例对象的手动内存管理,让property的setter方法自动管理原来对象的释放,以及新对象的retain。但是有了ARC,这样 的代码就不再需要了。一般来说,仅仅为了简化内存管理,是不再需要使用property的,虽然你仍然可以这样做,但直接使用实例变量是更好的选择。只有 那些属于public的实例变量,才应该定义为property

我们可以直接在.m类实现中定义private实例变量,不必写分类拓展了:

 

  1. @implementation MJViewController {  
  2.     NSArray *data;  
  3. }  

不过还是要在viewDidUnload方法中将data设置为nil,因为data是个strong指针,当不再使用一个对象时,应该设置为nil

 

  1. - (void)viewDidUnload {  
  2.     [super viewDidUnload];  
  3.     data = nil;  
  4. }  


二、IBOutlet

在ARC中,所有IBOutlet属性都推荐使用weak, 这些view对象已经属于View Controller的view hierarchy,不需要再次定义为strong。因此,这些定义为weak的IBOutlet属性都不需要在IBOutlet中设置为nil

  

三、@property的修饰符小结

• strong : 该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者,等同于"retain"
• weak : 该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被释放之后,对象将被自动赋值nil,记住IBOutlet应该使用weak
• unsafe_unretained : 等效于__unsafe_unretaind关键字声明的变量,等同于之前的"assign",iOS 5之前的系统用该属性代替 weak 来使用
• copy : 和之前的copy一样,复制一个对象并创建strong关联
• assign : 对象不能使用assign,但原始类型(BOOL、int、float)仍然可以使用

 

举个例子:

    NSString *houseOfMM = [[NSString alloc] initWithString:'装梵几的三室两厅']; 

上面一段代码会执行以下两个动作: 
1 在堆上分配一段内存用来存储@' 装梵几的三室两厅 ' ,比如:内存地址为 0X1111  内容为 ' 装梵几的三室两厅' , 
2 在栈上分配一段内存用来存储 houseForWife ,比如:地址为 0XAAAA  内容自然为 0X1111   


下面分别看下(assign,retain,copy): 
1.assign的情况: NSString  * myHouse  = [ houseOfMM   assign ]; 
此时 myHouse 和 houseOfMM 完全相同,地址都是 0XAAAA  ,内容为 0X1111  ,即 myHouse 只是 houseOfMM 的别名,对任何一个操作就等于对另一个操作。因此 retainCount 不需要增加.(同进同出,关系好,一把钥匙,给我拿着) 
2.retain的情况: NSString  *  myHouse  = [ houseOfMM   retain ]; 
此时 myHouse 的地址不再为 0XAAAA ,可能为 0XAABB ,但是内容依然为 0X1111 .因此 myHouse 和 houseOfMM 都可以管理' 装梵几的三室两厅 '所在的内存。因此  retainCount 需要增加1.(有些独立,各自进出,两把钥匙) 
3.copy的情况: NSString  *  myHouse  = [ houseOfMM   copy ]; 

此时会在堆上重新开辟一段内存存放@'装梵几的三室两厅',比如0X1122,内容为@'装梵几的三室两厅',同时会在栈上为myHouse分配空间,比如地址:0XAACC,内容为0X1122,因此retainCount增加1供myHouse来管理0X1122这段内存.(两套@'装梵几的三室两厅',条件好,分居了,房子一人一套,所以钥匙一人一把。)



什么时候用assign,当然是破房子,简装的房子拉
基础类型(简单类型,原子类型):NSInteger,CGPoint,CGFloat,C数据类型(int,float,double,char等)


什么时候用copy
含有可深拷贝的mutable子类的类,如NSArray,NSSet,NSDictionary,NSData的,NSCharacterSet,NSIndexSet,NSString
(可深度拷贝的房子)
但是NSMutableArray这样的不可以,Mutable的不能用copy,不然初始化会有问题。切记

什么时候用retain
其他NSObject和其子类对象好嘛 (大多数)


ARC中的strong相当于非ARC中的retain,ARC来了以后多搞一把钥匙就strong了啦。

原文:http://wenku.baidu.com/view/ab6ed804bed5b9f3f90f1c7d.html

浅拷贝和深拷贝 

浅拷贝

浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。如:


1
2
char* str = (char*)malloc(100);
char* str2 = str;

浅拷贝只是对对象的简单拷贝,让几个对象共用一片内存,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。

iOS 里面的浅拷贝:

在 iOS 里面, 使用retain 关键字进行引用计数,就是一种更加保险的浅拷贝。他既让几个指针共用同一片内存空间,又可以在release 由于计数的存在,不会轻易的销毁内存,达到更加简单使用的目的。

深拷贝:

深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。

copy 与 retain 的区别:

copy 是创建一个新对象,retain 是创建一个指针,引用对象计数加一。 copy属性标识两个对象内容相同,新的对象retain count为1, 与旧有对象引用计数无关,旧有对象没有变化。copy减少对象对上下文的依赖。

iOS里的深拷贝:

iOS提供了copy和mutableCopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutableCopy就是复制了一个mutable的对象。以下将举几个例子来说明。
这里指的是NSString, NSNumber等等一类的对象。

1 NSString *string = @”dddd";
2 NSString *stringCopy = [string copy];
3 NSMutableString *stringDCopy = [string mutableCopy];
4 [stringMCopy appendString:@"!!"];
查看内存可以发现,string和stringCopy指向的是同一块内存区域(weak reference),引用计数没有发生改变。而stringMCopy则是我们所说的真正意义上的复制,系统为其分配了新内存,是两个独立的字符串内容是一样的。

拷贝构造:

当然在 ios 中并不是所有的对象都支持copy,mutableCopy,遵守NSCopying协议的类可以发送copy消息,遵守NSMutableCopying协议的类才可以发送mutableCopy消息。

假如发送了一个没有遵守上诉两协议而发送copy或者 mutableCopy,那么就会发生异常。但是默认的ios类并没有遵守这两个协议。如果想自定义一下copy 那么就必须遵守NSCopying,并且实现 copyWithZone: 方法,如果想自定义一下mutableCopy 那么就必须遵守NSMutableCopying,并且实现 mutableCopyWithZone: 方法。

如果是我们定义的对象,那么我们自己要实现NSCopying , NSMutableCopying这样就能调用copy和mutablecopy了。举个例子:

 
1 @interface MyObj : NSObject<NSCopying, NSMutableCopying>{
2     NSMutableString *_name;
3     NSString * _imutableStr ;
4     int _age;
5 }     
6 @property (nonatomic, retain) NSMutableString *name;
7 @property (nonatomic, retain) NSString *imutableStr;
8 @property (nonatomic) int age;

copy拷贝构造:
1 - (id)copyWithZone:(NSZone *)zone{
2     MyObj *copy = [[[self class] allocWithZone :zone] init];
3     copy->name = [_name copy];
4     copy->imutableStr = [_imutableStr copy];
5     copy->age = age;
6     return copy;
7 }

 

mutableCopy拷贝构造:

1 - (id)mutableCopyWithZone:(NSZone *)zone{
2     MyObj *copy = NSCopyObject(self, 0, zone);
3     copy->name = [_name mutableCopy];
4     copy->age = age;
5     return copy;
6 }

 

有空的话翻译一下好嘛:

http://clang.llvm.org/docs/AutomaticReferenceCounting.html

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html


先看这个 :

http://blog.csdn.net/favormm/article/details/7023322

http://www.crifan.com/object_c_property_setter_assign_retain_copy_weak_strong/

http://www.crifan.com/object_c_property_setter_assign_retain_copy_weak_strong/

posted on 2015-07-03 20:00  MichaelMao  阅读(676)  评论(0编辑  收藏  举报