【问题标题】:Confusing about memory management on IOS对IOS上的内存管理感到困惑
【发布时间】:2012-03-04 00:13:27
【问题描述】:

我的应用有一点不常见的情况,就是

每次要显示视图时,我都必须重新加载一些保留属性,

代码如下所示:

// .h
@property (nonatomic, retain) NSArray *myData;
// .m
@synthesize myData;
- (void)viewWillAppear:(BOOL)animated {
    ... // get FetchRequest and so on
    self.myData = [self.context executeFetchRequest:request error:&error]; // Line 1
[super viewWillAppear:animated];
}
- (void)viewDidUnload {
    self.myData = nil;
    [super viewDidUnload];
}
- (void)dealloc {
    [myData release];  // Line 2
    [super dealloc];
}

有几点:

第一。如您所见,属性“myData”是保留,所以我认为我为它设置了一些对象,它会自动保留该对象?

第二。每次出现视图时我都必须重新加载“myData”,就像上面第 1 行的代码一样。

第三。由于它是一个retain属性,所以我必须自己正确释放它。

现在,问题是,我是否正确地管理了内存,而没有使用上面的代码泄漏任何“myData”?

如果视图在解除分配之前会出现多次,(例如在 UINavigationController 中推入另一个视图并弹出多次),

那么 myData 会多次保留某个对象,但我只在第 2 行的 dealloc for 1 中释放它一次,这样可以吗?

但是如果我将此方法添加到 viewController,我认为这对于避免内存泄漏更安全:

- (void)viewWillDisappear:(BOOL)animated {
    self.myData = nil;
    [myData release];
[super viewWillDisappear:animated];
}
- (void)dealloc {
 //   [myData release];  // don't release it here.
    [super dealloc];
}

在我推入并弹出视图一两次后,我的应用程序会崩溃,

那么到底哪一个是错的呢?

非常感谢!

【问题讨论】:

    标签: ios memory-management properties retain


    【解决方案1】:

    您不仅在第 2 行中发布它,它还将在替换时在第 1 行以及viewDidUnload 中发布,因此您的顶部代码很好。关键是

    self.myData = anything;
    

    扩展为

    [self->myData release];
    self->myData = [anything retain];
    

    因此,通过分配任何内容(包括nil),您已经在隐式调用release。实际上,您可以将第 2 行替换为 self.myData = nil;,从而永远不必调用 release,因为您没有任何明确的 retain

    【讨论】:

    • 请注意,如果代码按照您的建议运行,self.property = self.property 可能会导致对象被释放。它实际上在objc_release 之前调用了objc_retain,参见objc_setProperty_non_gc
    • 谢谢大家,我开始明白了,所以即使retain也是在release之前,我以前的代码应该是正确的吧?
    • @SedateAlien 是的,我应该补充一点,没有变化的特殊情况不会通过那条路线,但这与上述情况无关。这只是这个概念的一个例证。
    • 非常感谢!所以这意味着如果我在 viewDidUnload 方法中将一个 retain 属性设置为 nil,我什至不需要在 dealloc 中手动释放它?
    • 如果你能保证在删除视图之前总是调用viewWillDisappear:,是的。 dealloc 中的 release 仅适用于由于某种原因而未收到 viewWillDisappear: 消息的视图被释放的情况。但是因为你不能保证它(只有 dealloc 是保证的),你应该保留它 - 在大多数情况下它将是一个无操作(因为到那时 myData 很可能是 nil)但它是一个安全措施。
    【解决方案2】:

    .h

    @property (nonatomic, retain) NSArray *myData;
    

    .m

    @synthesize myData;
    

    通过在代码中包含这些行,将为您的属性 myData 创建一个 setter 和 getter。在运行时为对象生成的 setter 看起来像这样,

    - (void)setMyData: (id)newValue
    {
        if (myData != newValue)
        {
            [myData release];
            myData = newValue;
            [myData retain];
        }
    }
    

    总的效果是,每当您通过在前面附加 self 来访问属性时,您实际上是在调用 setter 和 getter。所以下面两行是完全一样的。

    self.myData = nil;
    [self setMyData:nil];
    

    所以你的原始代码已经正确了。

    【讨论】:

      猜你喜欢
      • 2012-05-24
      • 2011-10-02
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 2021-10-22
      • 1970-01-01
      相关资源
      最近更新 更多