【问题标题】:Should I retain an autoreleased object when assigned to a retained property?分配给保留属性时是否应该保留自动释放的对象?
【发布时间】:2011-07-01 01:43:47
【问题描述】:

在我的一个保留属性的 getter 中,我为我的模型对象(“模型”)分配并分配了一个 NSArray。然后我使用“sortedArrayUsingSelector:”方法对该 NSArray 进行排序。根据文档,这会返回一个自动释放的 NSArray。然后我将其重新分配给我的“模型”数组。

起初,我从来没有保留这个自动释放的排序数组,并发现当我从堆栈中弹出这个 viewController 时,我的应用程序会崩溃,说我试图减少一个已释放对象的引用计数或类似的东西。然后我添加了一个保留,如下面的代码所示,一切正常。

我的问题是,即使我在声明中保留此属性并在我的 dealloc 中释放它,我也应该保留 autoreleased 对象是否正确?

- (NSArray *)models {

    if (!models) {
        models = [[NSArray alloc] initWithArray:[self.modelDictionary allKeys]];
        models = [[models sortedArrayUsingSelector:@selector(compare:)] retain];
    }
    return models;

}

【问题讨论】:

    标签: iphone objective-c properties retain autorelease


    【解决方案1】:

    除非我遗漏了什么,否则您似乎只是将结果设置为您的实例变量之一。我认为您应该改用您的属性。

    self.models =  [NSArray arrayWithArray:[self.modelDictionary allKeys]];
    

    如果没有 self. 部分,您就不会使用 setter 方法,因此永远不会保留任何东西。

    【讨论】:

    • 我认为在您的示例中,您将保留它两次。 init 不会自动释放,如果我没记错的话,而像 [NSArray arrayWithArray:[self.modelDictionary allKeys]] 这样的东西应该。因此,可能需要记住一些事情。编辑:被打败一分钟。
    • 你有更多的词和更好的解释...... :)
    【解决方案2】:

    一般来说,如果你想让一个自动释放的对象一直存在,你必须retain它。

    这段代码有几个问题:

    - (NSArray *)models {
    
        if (!models) {
            models = [[NSArray alloc] initWithArray:[self.modelDictionary allKeys]];
            models = [[models sortedArrayUsingSelector:@selector(compare:)] retain];
        }
        return models;
    }
    
    • 您正在使用第二行代码 models= 泄漏 alloc/initd 数组

    • 您说“在其声明中保留此属性,但在上面的代码中您直接分配给实例变量,绕过了可能由@synthesize生成的setter方法

    • 它是一个改变被获取变量状态的 getter 方法......虽然这种惰性初始化可能很有吸引力,但必须非常小心地完成。 Core Data 竭尽全力——通过相当多的内部复杂性——以这种方式允许状态的惰性填充。上面的代码也意味着 models 属性的键值观察者在执行 getter 时不会看到变化。然而,如果您从 getter 手动调用 willChangeValueForKey:/didChangeValueForKey:,您最终会从 getter 中发送更改通知,这很可能会导致在先调用 getter 的人之前消耗值检索值。听起来很混乱?它是——这可能会也可能不会导致问题。根据我的经验,这可能会在某天引起问题。


    一些建议:

    • 如果可以,请使用 Core Data。为了使 Core Data 非常高效并与系统很好地集成,我们投入了大量的工程工作。

    • 将 getter/setter 与其他逻辑分开。很可能,您的应用程序中有一个逻辑点,您需要“获取”模型。当你这样做的时候,告诉对象通过其他方法让他们出错然后获取模型。这似乎很痛苦,但构建对象图是一项非常专业的任务,而不是查询该图以获取信息(或使用 Core Data,它对此有解决方案)。

    【讨论】:

      【解决方案3】:

      谢谢!我明白你的意思。我想我很困惑,并认为在我的 getter 中调用 self.models 会创建一个无限循环。我现在看到,如果我从 getter 内部调用 getter,而不是从 getter 内部调用 setter。我将代码更改为:

      - (NSArray *)models {
          if (!models) {
              self.models = [[NSArray alloc] initWithArray:[self.modelDictionary allKeys]];
              self.models = [models sortedArrayUsingSelector:@selector(compare:)];
          }
          return models;
      }
      

      一切都可以编译并且工作正常...这看起来像是一个更正确的解决方案吗?感谢您的宝贵时间。

      【讨论】:

      • 假设您的资源设置为保留,您仍然缺少发布。
      • 好的,你的意思是我应该分配 self.models = [NSArray arrayWithArray:[self.modelDictionary allKeys]];反而?感谢您的输入。我对编程比较陌生。
      • 那行得通,是的....请注意,您可能会遇到我描述的一些严重问题。
      • 感谢您的反馈。如果不是在 getter 中懒惰地实例化它,您建议哪种方法最适合实例化该 Array 并对其进行排序?我试图以这种方式提高效率。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多