使用alloc和init

loc*_*ope 6 cocoa memory-management allocation initialization objective-c

我们知道必须组合alloc和init的alloc/init的完整模式.

NSObject *myObj = [[NSObject alloc] init];
Run Code Online (Sandbox Code Playgroud)

1- init方法从另一个源接收对象(不是来自alloc,new,copy或类似或保留),因此根据基本的内存管理规则,它不是所有者,也不能释放它.但是,"分配和初始化对象/返回对象"文章说init可以释放接收器.

当它违背基本规则时,这怎么可能呢?

2-此外,从同一篇文章中,init可以返回另一个对象或nil.因此,在这种情况下,当我们使用alloc/init的完整模式时,我们无法释放alloc返回的对象,但我们只能释放从init返回的对象,并且init释放它从alloc而不是我们收到的对象.

但是init不是alloc,new,copy或者类似的方法,因此我们不能释放从它返回的对象,因为它不会给我们对象的所有权.

我们如何释放从init返回的对象,尽管这违反了基本规则?

3-或者,为了遵守同一篇文章的最后一段,我们必须接受init方法作为特例并使用alloc/init模式作为基本规则的例外吗?

内存管理基本规则:

分配和初始化对象/返回的对象:

但是,在某些情况下,此责任可能意味着返回与接收者不同的对象.例如,如果一个类保留了一个命名对象列表,它可能会提供一个initWithName:方法来初始化新实例.如果每个名称只能有一个对象,initWithName:可能会拒绝为两个对象分配相同的名称.当要求为新实例分配一个已被另一个对象使用的名称时,它可以释放新分配的实例并返回另一个对象 - 确保名称的唯一性,同时提供所要求的内容,实例请求的名称.

在少数情况下,init ...方法可能无法按照要求执行操作.例如,initFromFile:方法可能从作为参数传递的文件中获取所需的数据.如果传递的文件名与实际文件不对应,则无法完成初始化.在这种情况下,init ...方法可以释放接收器并返回nil,表示无法创建请求的对象.

因为init ... 方法可能返回除了新分配的接收者以外的对象,甚至返回nil,所以程序使用初始化方法返回的值,而不仅仅是alloc或allocWithZone返回的值,这一点很重要.以下代码非常危险,因为它忽略了init的返回.

id anObject = [SomeClass alloc];
[anObject init];
[anObject someOtherMessage];
Run Code Online (Sandbox Code Playgroud)

相反,为了安全地初始化对象,您应该在一行代码中组合分配和初始化消息.

id anObject = [[SomeClass alloc] init];
[anObject someOtherMessage];
Run Code Online (Sandbox Code Playgroud)

http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html

Pet*_*sey 8

init方法不接收对象; 对象接收init消息.物体不具备自身; 相反,它总是知道自己(通过self每条消息中的隐含参数).

不过,你说对象不是自己的,这是对的.如果alloc并且init在单个new方法中融合,那么该方法将是它自己的(super)调用者,因此它将拥有该对象(直到它返回),因此毫无疑问正确地释放它.既然它们是独立的,并且init不是调用者alloc,那么它是不对的,它不拥有该对象,所以你对这种做法提出质疑是正确的.

这是少数几个可以让一个对象代表另一个对象释放对象(在本例中为自身)的情况之一.另一种方法是不释放它,如果你要返回nil或抛出异常,那将是一个泄漏.

一般来说,只要你有一个对象保留或释放自己,你应该感觉很脏.在这种特定情况下,没关系,因为您正在防止错误(泄漏)而不是创建错误.

2-此外,从同一篇文章中,init可以返回另一个对象或nil.因此,在这种情况下,当我们使用alloc/init的完整模式时,我们无法释放alloc返回的对象,但我们只能释放从init返回的对象,并且init释放它从alloc而不是我们收到的对象.

但是init不是alloc,new,copy或者类似的方法,因此我们不能释放从它返回的对象,因为它不会给我们对象的所有权.

init代表其调用者释放旧对象时,如果它创建一个新对象,它代表其调用者执行此操作.调用者拥有init为其创建或检索的替代对象.

作为推论,如果init检索以前存在的对象,它必须保留它,以便调用者拥有它.

再次检查假设的*new方法,它还需要释放旧对象并创建(自己)或保留替代品.

在所有这些情况下,它init代表其调用者行事.对于一种方法来说,进行另一种内存管理通常很狡猾,但对于这些情况,init代表其调用者执行此操作是必要的.

*该new方法确实存在,但简单地发送allocinit,所以没有必要单独实施.