简体   繁体   English

Objective-C中的棘手内存管理

[英]Tricky memory management in objective-c

After reading: Memory management of a view controller in Objective-c 阅读后: Objective-c中视图控制器的内存管理

and

Does UIView's addSubview really retain the view? UIView的addSubview是否真的保留了视图?

I wrote the following code to toggle a subview: 我编写了以下代码来切换子视图:

@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

It seems to run fine if I comment out that release line, but I can't wrap my head around why. 如果我注释掉该发布行,这似乎运行得很好,但是我不能为之困惑。 Here's the way I understand what happens and maybe someone can tell me where I go wrong: 这是我了解会发生什么的方式,也许有人可以告诉我我哪里出了问题:

So lets consider currentView: 因此,让我们考虑currentView:

  • A gets alloc-ed by the 'new' message--retain count=A:1 A由“新”消息分配-保留计数= A:1

  • A gets retained by the setter--retain count=A:2 A被设置员保留-保留计数= A:2

  • A's view gets (supposedly) retained--retain count=A:2.1 A的视图(据说)被保留了-保留计数= A:2.1

next time through... 下次通过...

  • A's subview gets released count=A:2 A的子视图被释放count = A:2

  • B gets alloc-ed by the 'new' message--retain count=B:1, A:2 B被'new'消息分配-保留count = B:1,A:2

  • A gets autoreleased by the setter-- B:1, A:1 A由设置员自动释放-B:1,A:1

  • B gets retained by the setter--B:1, A:1 B被设置者保留-B:1,A:1

  • nothing ever gets rid of A? 没有什么能摆脱A?

So should I change my code, or am I wrong about the way memory management works in this language...or both?- 因此,我应该更改代码,还是在这种语言下的内存管理工作方式错了?

Ok, step one, ignore the retainCount . 好的,第一步,忽略了retainCount It's one of those things Apple should rename to something like lsdjiofsudfoiwjeriowhfiuwhrteiuhweifhsdjkfhsiurwoieuriosfho so people won't guess it's name, and not list it in the documentation. 苹果应该将其重命名为lsdjiofsudfoiwjeriowhfiuwhrteiuhweifhsdjkfhsiurwoieuriosfho之类的东西lsdjiofsudfoiwjeriowhfiuwhrteiuhweifhsdjkfhsiurwoieuriosfho这样人们就不会猜到它的名字,并且不在文档中列出。 For your purposes, it's entirely useless, so ignore it. 对于您的目的,它完全没有用,所以请忽略它。

Now that I've said that, let's consider something: addSubview: DOES retain its argument, and removeFromSuperview releases the receiver. 现在,我已经说了,让我们考虑一下: addSubview:确实保留其参数,而removeFromSuperview释放接收方。

Finally, it's hard to tell what currentSubview is. 最后,很难说出currentSubview是什么。 It has a view property which would lean towards a VC, however, the way you're using it by itself, would indicate its a normal view. 它具有view属性,该属性倾向于VC,但是,按其自身使用的方式,将指示其正常视图。 Perhaps you can clarify so I can continue my answer. 也许您可以澄清一下,以便我继续回答。

Change the release line to 将发布行更改为

self.currentSubview = nil;

and I think you'll be fine. 我想你会没事的。 You're releasing, but not setting the property to nil. 您正在释放,但未将属性设置为nil。 So, when it gets re-assigned next time through, release will be called again on it. 因此,当下次重新分配它时,将在其上再次调用release。 But you already released it so... boom. 但是您已经发布了它……繁荣。

Your understanding of retain and release is correct, as is your code. 您对保留和释放的理解以及您的代码都是正确的。 That suggests that the problem lies outside of the code you've posted. 这表明问题出在您已发布的代码之外。 For example, you would have this problem if your currentSubView property was defined as assign instead of retain . 例如,如果你的currentSubView财产被定义为你有这样的问题, assign而不是retain

You code is not structured well, however. 但是,您的代码结构不好。 This would be much clearer: 这将更加清楚:

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

Furthermore, view controllers are meant to be cached, not created and released each time the user toggles a display. 此外,每次用户切换显示时,视图控制器都应被缓存,而不是创建和释放。 Typically, you create your view controllers beforehand, and access their .view property when necessary to display the view. 通常,您需要预先创建视图控制器,并在需要显示视图时访问它们的.view属性。 UIViewController will automatically deallocate non-visible views in low memory conditions, and re-allocate their view when the .view property is accessed. UIViewController将在内存不足的情况下自动取消分配不可见的视图,并在访问.view属性时重新分配其视图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM