开发者

Tricky memory management in objective-c

After reading: Memory management of a view controller in Objective-c

and

Does UIView's addSubview really retain the view?

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:

  • A gets alloc-ed by the 'new' message--retain count=A:1

  • A gets retained by the setter--retain count=A:2

  • A's view gets (supposedly) retained--retain count=A:2.1

next time through...

  • A's subview gets released count=A:2

  • B gets alloc-ed by the 'new' message--retain count=B:1, A:2

  • A gets autoreleased by the setter-- B:1, A:1

  • B gets retained by the setter--B:1, A:1

  • nothing ever gets rid of A?

So should I change my code, or am I wrong about the way memory management works in this开发者_StackOverflow中文版 language...or both?-


Ok, step one, ignore the 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. 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.

Finally, it's hard to tell what currentSubview is. 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. Perhaps you can clarify so I can continue my answer.


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.

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. UIViewController will automatically deallocate non-visible views in low memory conditions, and re-allocate their view when the .view property is accessed.


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. So, when it gets re-assigned next time through, release will be called again on it. But you already released it so... boom.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜