在启用iOS ARC的项目中,当我不合成属性时会发生什么,因为不允许保留/释放?
@interface SomeClass : NSObject {
NSMutableArray* _pieces;
}
@end
在这种情况下,iVar _pieces的内存语义是什么?
假设我使用_pieces = whatever
设置它。
当我的SomeClass实例被解除分配时,_pieces是否设置为nil? _pieces是否存储为弱引用? 如果保留_pieces的所有其他对象释放它,当我尝试访问它时它是否为null?
答案 0 :(得分:16)
一些观察结果,其中很多观点可能基于其他人的反馈而明确:
您合成了属性,而不是实例变量,在您的示例中,您向我们展示了一个实例变量的示例,而不是属性。
您的问题可能意味着在合成和执行retain
/ release
的能力之间存在一些假设的联系,但没有这样的联系。执行retain
和release
的功能取决于您是否使用ARC。它与合成属性无关。
正如其他人所观察到的,默认情况下,显式声明的实例变量(例如您的示例)是strong
引用。因此,在您的示例中,_pieces
是strong
引用。
是的,当您的SomeClass
对象被取消分配时,它将删除对strong
对象的_pieces
引用。显然,如果这是_pieces
指向的对象的最后一个强引用,它将被释放,并且您在其他地方使用的任何其他weak
引用将被设置为nil
。有关内存管理的更完整讨论,请参阅Apple的Advanced Memory Management Programming Guide和Transitioning to ARC。
您问“如果保留_pieces
的所有其他对象都将其释放,那么当我尝试访问它时,它是nil
吗?”显然,如果_pieces
是weak
引用,那将是正确的,但鉴于它strong
中隐含SomeClass
引用,不,情况并非如此。
如果您想pieces
成为declared property,则语法为
@property (nonatomic, strong) NSMutableArray* pieces;
strong
与weak
(或其他)的约束决定了财产的记忆管理。
如果你声明一个属性,你不仅不再需要显式定义实例变量,而是现在建议你真的不应该这样做(因为当它被合成时,编译器将创建ivar为了你)。但是,如果您碰巧有一个显式声明的属性正确名称的实例变量,编译器将使用该属性。但这不仅是不必要的,而且也是不可取的(因为如果你错误输入实例变量的名称,你可能会在不知不觉中最终得到两个实例变量)。只需让编译器为您的属性合成您的实例变量,这种潜在的歧义就会消失。
将为属性合成的实例变量的名称由property implementation directive的语法控制,即@synthesize
语句。因此,如果您对表单的@synthesize
属性有pieces
声明:
@synthesize pieces;
那么实例变量将被称为pieces
。但是,如果您使用首选@synthesize
语法:
@synthesize pieces = _pieces;
则实例变量名将具有前面的下划线(即约定,首选,以避免在属性和实例变量之间的代码中出现歧义)。并且,从Xcode 4.4开始,如果省略@synthesize
的{{1}}语句,它将使用后一种语法隐式合成它,即实例变量将带有前导下划线。
答案 1 :(得分:3)
假设您尚未创建使用此属性的属性(覆盖假定的行为),ARC项目中的实例变量将被假定为强,因此声明确实是
@interface SomeClass : NSObject {
__strong NSMutableArray* _pieces;
}
@end
所以,回答你的问题
当我的SomeClass实例被解除分配时,_pieces是否设置为nil?
不,但为其分配实例不会导致它被解除分配。
_pieces是否存储为弱引用?
不,这是一个很好的参考。
如果保留_pieces的所有其他对象都释放它,当我尝试访问它时它是否为空?
不,这与你的第一个问题相同。
答案 2 :(得分:2)
您是否声明了一个名为pieces
的属性,或者这是一个直的ivar?
如果定义属性,则内存使用量取决于您定义属性的方式。
如果这是一个直的ivar,那么默认情况下,ivar将是strong
。这实际上意味着ivar将正确地保留和释放您分配给它的对象。你可以安全地使用它而不必担心它。
答案 3 :(得分:0)
据我所知,ARC将以与strong
类似的方式对待它。分配给它时,传入的值将为retain
,不再指向的值将为release
d。如果它以某种方式变得过度释放,它只会摇摆不定。如果您有财产声明,ARC将遵守其中指定的规则,并且将以@synthesize someObject = _someObject
的形式自动为您合成访问者。当对象被释放时,我假设对象被发送release
,这样如果没有其他东西断言所有权,指针所指向的对象也将被释放。
答案 4 :(得分:0)
使用新的运行时你只需要@properties btw - 不要声明ivars,不要合成