【问题标题】:Tricky memory management in objective-cObjective-c 中棘手的内存管理
【发布时间】:2011-05-04 03:59:48
【问题描述】:

阅读后: Memory management of a view controller in Objective-c

Does UIView's addSubview really retain the view?

我编写了以下代码来切换子视图:

@synthesize switchableView, viewSelector, currentSubview;

//...

if(switchableView.subviews.count != 0)
 [[switchableView.subviews objectAtIndex:0] removeFromSuperview]]
self.currentSubview = (veiwSelector.selectedSegmentIndex == 0) ?
 [ViewA new] : [ViewB new];
[switchableView addSubview:currentSubview.view];

//[currentSubview release]; //<---crashes if I uncomment this line

如果我注释掉那条发布行,它似乎运行良好,但我无法理解为什么。这是我理解发生了什么的方式,也许有人可以告诉我哪里出错了:

让我们考虑一下 currentView:

  • A 被“新”消息分配--retain count=A:1

  • A 被 setter 保留--retain count=A:2

  • A 的视图被(假定)保留--retain count=A:2.1

下次通过...

  • A 的子视图被释放 count=A:2

  • B 被“新”消息分配--retain count=B:1, A:2

  • A 被 setter 自动释放 -- B:1, A:1

  • B 被 setter 保留--B:1, A:1

  • 没有什么能摆脱 A?

那么我应该更改我的代码,还是我对这种语言中内存管理的工作方式有误...或两者兼而有之?-

【问题讨论】:

  • 在 removeFromSuperview 之后你有一个额外的 ]

标签: iphone objective-c memory-leaks


【解决方案1】:

好的,第一步,忽略retainCount。这是苹果应该重命名为lsdjiofsudfoiwjeriowhfiuwhrteiuhweifhsdjkfhsiurwoieuriosfho 这样的东西之一,这样人们就不会猜到它的名字,也不会在文档中列出它。对于你的目的,它完全没用,所以忽略它。

既然我已经说过了,让我们考虑一下:addSubview: 保留其参数,removeFromSuperview 释放接收者。

最后,很难说currentSubview 是什么。它有一个view 属性,该属性倾向于VC,但是,您单独使用它的方式将表明它是正常视图。也许您可以澄清一下,以便我继续回答。

【讨论】:

  • lsdjiofsudfoiwjeriowhfiuwhrteiuhweifhsdjkfhsiurwoieuriosfho ...检查!那么您在 O-C 中遵循哪些规则?因为显然,整个释放或自动释放你分配的所有东西都是一堆废话。
  • 这些是我建议你遵循的:developer.apple.com/library/ios/#documentation/general/… ...一旦你学会了这几个简单的规则,你就会很好地理解你需要了解的大部分内容内存管理在这里。
  • 他没有使用retainCount方法,他只是在计算自己使用的retain和release,这完全没问题。
【解决方案2】:

您对保留和释放的理解是正确的,您的代码也是如此。这表明问题出在您发布的代码之外。例如,如果您的 currentSubView 属性被定义为 assign 而不是 retain,您就会遇到这个问题。

但是,您的代码结构不佳。这会更清楚:

self.currentSubView = [[ViewA new] autorelease];

此外,视图控制器旨在被缓存,而不是在用户每次切换显示时创建和释放。通常,您事先创建视图控制器,并在需要显示视图时访问它们的.view 属性。 UIViewController 将在内存不足的情况下自动取消分配不可见的视图,并在访问 .view 属性时重新分配它们的视图。

【讨论】:

    【解决方案3】:

    将发布行更改为

    self.currentSubview = nil;
    

    我想你会没事的。您正在释放,但没有将属性设置为 nil。因此,当它下一次被重新分配时,将再次调用它。但是你已经发布了它,所以......繁荣。

    【讨论】:

      猜你喜欢
      • 2011-06-28
      • 1970-01-01
      • 2020-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-03
      相关资源
      最近更新 更多