【问题标题】:In arc what happens when you don't synthesize在弧中,当你不合成时会发生什么
【发布时间】:2012-11-08 21:08:27
【问题描述】:

在启用了 iOS ARC 的项目中,当我不合成属性时会发生什么,因为不允许保留/释放?

@interface SomeClass : NSObject {
    NSMutableArray*     _pieces;
}
@end

在这种情况下,iVar _pieces 的内存语义是什么? 假设我使用 _pieces = whatever 设置它。

当我的 SomeClass 的实例被释放时,_pieces 是否设置为 nil? _pieces 是否存储为弱引用? 如果所有其他保留 _pieces 的对象都释放它,当我尝试访问它时它会为 null 吗?

【问题讨论】:

  • 为什么这个被标记下来,这似乎是一个非常有效的有用问题

标签: objective-c ios automatic-ref-counting


【解决方案1】:

根据其他人的反馈,有几点意见,其中大部分可能已经很清楚了:

  1. 您合成的是属性,而不是实例变量,在您的示例中,您向我们展示了一个实例变量的示例,而不是属性。

  2. 您的问题可能暗示合成与执行retain/release 的能力之间存在某种假定联系,但没有这种联系。执行retainrelease 的能力取决于您是否使用ARC。它与合成属性无关。

  3. 正如其他人所观察到的,默认情况下,显式声明的实例变量(例如您的示例)是 strong 引用。因此,在您的示例中,_piecesstrong 引用。

  4. 是的,当您的SomeClass 对象被释放时,它将删除其strong_pieces 对象的引用。显然,如果这是对_pieces 指向的对象的最后一个强引用,它将被释放,并且您在其他地方对它的任何其他weak 引用都将设置为nil。有关内存管理的更完整讨论,请参阅 Apple 的 Advanced Memory Management Programming GuideTransitioning to ARC

  5. 您问“如果所有其他保留_pieces 的对象都释放它,当我尝试访问它时它会是nil 吗?”显然,如果 _piecesweak 引用,那将是正确的,但考虑到它在 SomeClass 中隐式引用 strong,不,事实并非如此。

  6. 如果您想将 pieces 设为 declared property,则语法应为

    @property (nonatomic, strong) NSMutableArray* pieces;

    strongweak 的指定(或其他)决定属性的内存管理。

  7. 如果你声明一个属性,你不仅不再需要显式定义实例变量,而且现在建议你真的不应该这样做(因为当它被合成时,编译器将创建 ivar为你)。但是,如果您碰巧为您的属性有一个正确名称的显式声明的实例变量,编译器将使用该属性。但这不仅是不必要的,而且是不可取的(因为如果您输入错误的实例变量的名称,您可能会在不知不觉中得到两个实例变量)。只需让编译器为您的属性合成实例变量,这种潜在的歧义就会消失。

  8. 将为属性合成的实例变量的名称由property implementation directive 的语法控制,即@synthesize 语句。因此,如果您的pieces 属性具有@synthesize 语句,格式为:

    @synthesize pieces;

    那么实例变量将被称为pieces。但是,如果您使用首选的@synthesize 语法:

    @synthesize pieces = _pieces;

    那么实例变量名称将有前面的下划线(按照惯例,这是首选的,以避免在属性和实例变量之间的代码)。而且,从 Xcode 4.4 开始,如果您为 @property 省略了 @synthesize 语句,它将使用后一种语法为您隐式合成它,即实例变量将带有前导下划线)。

    李>

【讨论】:

  • 假设@synthesize 属性用于公共变量,而iVar 用于类外变量的假设不应该关心吗?
  • @1dayitwillmake 你当然想在你的 .h 文件中使用declare public properties for exposed data(即你的“公共变量”)。就个人而言,我将我的私有 ivars 和属性放在 .m 文件中的 private class extension 中。
  • @1dayitwillmake 将私有数据存储为 ivars 还是作为属性是个人喜好的问题(我通常使用 ivars,但理解人们为什么使用私有属性,但我出于务实的考虑,不是宗教狂热)。另外,请注意您可以在 .h 文件中 limit the scope 的 ivars(例如,使用 @private 指令),但我认为将私有内容放在类扩展中会更干净。
【解决方案2】:

假设您没有创建使用它的属性,它会覆盖假定的行为,ARC 项目中的实例变量被假定为强,因此声明确实是

@interface SomeClass : NSObject {
    __strong NSMutableArray* _pieces;
}
@end

所以,回答你的问题

当我的 SomeClass 的实例被释放时,_pieces 是否设置为 nil?

不,但为它分配一个实例不会导致它被释放。

_pieces 是否存储为弱引用?

不,这是一个强有力的参考。

如果所有其他保留了_pieces的对象都释放它,我尝试访问它时它会为null吗?

不,这与您的第一个问题相同。

【讨论】:

  • 我如何'释放'引用然后允许它被释放
  • 好吧,更改_pieces 所指的内容。它是被释放的变量引用的对象,并且该对象跟踪引用它的内容(它的保留计数)。如果一个强变量正在引用一个对象,则保留计数会增加。如果对象不再被特定变量引用,则保留计数会减少。一旦保留计数为 0,就可以将其释放。
【解决方案3】:

您是在声明一个名为 pieces 的属性还是直接 ivar?

如果您定义一个属性,那么内存使用量取决于您如何定义该属性。

如果这是一个直接的 ivar,那么默认情况下 ivar 将是 strong。这实质上意味着 ivar 将正确地保留和释放您分配给它的任何对象。您可以放心使用它。

【讨论】:

    【解决方案4】:

    据我所知,ARC 会像您对待它一样对待它,其方式类似于strong。当您分配给它时,传入的值将是retained,不再指向的值将是released。只有当它以某种方式过度释放时,它才会悬挂。如果你有一个属性声明,ARC 将遵守那里指定的规则,访问器会自动为你合成@synthesize someObject = _someObject 的形式。当对象被释放时,我假设对象被发送release,这样如果没有其他东西声明所有权,指针指向的对象也将被释放。

    【讨论】:

      【解决方案5】:

      使用新的运行时,您只需要 @properties btw - 不要声明 ivars,不要合成

      【讨论】:

      • 这假设他想要一个财产。拥有一个没有属性的 ivar 完全没问题。
      • 如果我不合成它会报错:自动属性合成正在合成未显式合成的属性
      猜你喜欢
      • 2011-05-05
      • 1970-01-01
      • 2013-04-29
      • 1970-01-01
      • 2013-10-16
      • 2019-01-19
      • 1970-01-01
      • 2012-04-07
      • 1970-01-01
      相关资源
      最近更新 更多