目标C – 分配,复制,保留

我是Objective C的新手。我拥有C语言的基本知识,包括指针的概念。 我有两个基本的问题:

  1. 有人可以用一些比喻来解释分配,复制和保留之间的区别吗?
  2. 如何处理返回指针variables的函数,以及如何通过返回指针执行消息传递?

已更改的文档更新答案

信息现在分散在文档中的几个指南。 这是一个必读的列表:

  • cocoa核心能力:声明的财产
  • 用Objective-C编程:封装数据
  • 过渡到ARC发行说明
  • 高级内存pipe理编程指南
  • Objective-C运行时编程指南:声明的属性

现在,这个问题的答案完全取决于您是否使用ARCpipe理的应用程序(新项目的现代默认值)或强制手动内存pipe理。

赋值vs弱 – 使用赋值来设置一个属性指针指向的对象的地址,而不保留它或以其他方式处理; 如果分配给它的对象被释放,使用weak可以使属性指向nil。 在大多数情况下,你会想要使用弱,所以你不试图访问一个释放对象(非法访问的内存地址 – “ EXC_BAD_ACCESS ”),如果你不执行适当的清理。

保留与复制 – 声明的属性默认使用保留 (所以你可以完全忽略它),并将自动pipe理对象的引用计数是否另一个对象分配给属性或设置为零; 使用副本自动发送新分配的对象一个-copy消息(这将创build传递的对象的副本,并将该副本分配给属性,而不是有用的(甚至是必需的)在某些情况下,可能会修改分配的对象后设置为某个其他对象的属性(这意味着该属性也将适用修改/突变)。

iOS参考库中的“ 内存pipe理编程指南”具有分配,复制和保留的基础知识,并附有类比和示例。

复制制作对象的副本,并返回保留数为1.如果复制对象,则拥有该副本。 这适用于任何包含单词copy的方法,其中“copy”指的是返回的对象。

保留将对象的保留计数增加1.获取对象的所有权。

释放将对象的保留计数减1。放弃对象的所有权。

复制vs分配vs保留

赋值是为BOOL,NSInteger或double等原始值。 对于使用保留或复制的对象,取决于是否要保留对原始对象的引用或复制它。

隐藏的function

 NSString * string ; 

当你调用这个expression式

 string = @"Your name"; 

一个方法会自动调用

 - (void)setString:(NSString*)newString { } 
  • 分配

在属性的setter方法中,将实例variables简单分配给新值,

 - (void)setString:(NSString*)newString { string = newString; } 

这可能会导致问题,因为Objective-C对象使用引用计数,因此通过不保留对象,有可能在您仍在使用它时释放该string。

  • 保留

这在你的setter方法中保留了新的价值。 例如:这是更安全的,因为你明确声明你要维护对象的引用,并且在释放它之前你必须释放它。

 - (void)setString:(NSString*)newString { [newString retain]; [string release]; string = newString; } 
  • 复制

这会在你的setter方法中创build一个string的副本:这通常与string一起使用,因为创build原始对象的副本可以确保在使用它时不会改变它。

  - (void)setString:(NSString*)newString { if(string!=newString){ [string release]; string = [newString copy]; } } 

·赋值是为BOOL,NSInteger或double等原始值。 对于使用保留或复制的对象,取决于是否要保留对原始对象的引用或复制它。 ·assign:在属性的setter方法中,有一个简单的实例variables赋值给新值,例如:

 -(void)setString:(NSString*)newString{ string = newString; } 

这可能会导致问题,因为Objective-C对象使用引用计数,因此通过不保留对象,有可能在您仍在使用它时释放该string。 保留:这将保留您的setter方法的新值。 例如:这是更安全的,因为你明确声明你要维护对象的引用,并且在释放它之前你必须释放它。

 - (void)setString:(NSString*)newString{ [newString retain]; [string release]; string = newString; } 

·复制:在setter方法中创build一个string副本:这通常用于string,因为创build原始对象的副本可确保在使用它时不会更改。

 - (void)setString:(NSString*)newString{ if(string!=newString){ [string release]; string = [newString copy]; } } 
  1. 分配

    • assign是一个默认属性属性
    • assign是一个属性属性,告诉编译器如何综合属性的setter实现
  2. 复制:

    • 当对象是可变的时,复制是必需的
    • copy会返回一个你必须在非垃圾回收环境中明确释放的对象(例如dealloc)
    • 您需要在完成后释放对象,因为您保留了该副本
  3. 保留:

    • 指定在赋值时应将新值发送“-retain”,并将旧值发送给“-release”
    • 如果你写保留它会自动工作像强
    • 诸如“alloc”的方法包括一个隐含的“保留”
 NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"First",@"Second", nil]; NSMutableArray *copiedArray = [array mutableCopy]; NSMutableArray *retainedArray = [array retain]; [retainedArray addObject:@"Retained Third"]; [copiedArray addObject:@"Copied Third"]; NSLog(@"array = %@",array); NSLog(@"Retained Array = %@",retainedArray); NSLog(@"Copied Array = %@",copiedArray); array = ( First, Second, "Retained Third" ) Retained Array = ( First, Second, "Retained Third" ) Copied Array = ( First, Second, "Copied Third" ) 

保留与复制与分配

分配 ”是默认值。 在由@synthesize创build的setter中,该值将被简单地分配给该属性。 我的理解是“分配”应该用于非指针属性。

当属性是指向对象的指针时,需要“ 保留 ”。 @synthesize生成的setter将保留(也就是添加保留计数)对象。 完成后您需要释放对象。

当对象是可变的时候需要“ 复制 ”。 如果此时需要对象的值,则可以使用此值,而不希望该值反映对象的其他所有者所做的任何更改。 您将需要释放对象,因为您保留副本。