Reputation: 15069
I am new to cocoa, since I am programming cocoa app I always get confused how to release an object which tells its delegate that I am done. And the listener tries to release it.
So I have an AppController which lunches a updateCheckWindowController and also acts as a delegate to it so that when updateCheckWindow ends it can take further action (in my case release it). The UpdateCheckWindowController calls the delegate when window ends, so that call goes to AppController's method which tries to release the calling Object updateCheckWindowController.
Since AppController was the only one retaining it, calling a release should destroy the updateCheckWindowController , but updateCheckWindowController object is currently on the callStack because it is the one calling delegate method on AppController and AppController tries to release it. Its kind of circular call
How does it work in objective-c ? this looks like a pretty bad pattern unlike there is a fair justification for that. Or is my way of doing it is incorrect ?
Upvotes: 1
Views: 86
Reputation: 18554
This could be as simple as using autorelease instead of release. Autorelease often doesn't perform an actual release until the call stack is unwound.
Upvotes: 0
Reputation: 7469
The call stack does not pose any problems here. As long as UpdateCheckWindowController does not do anything after the call after which it's released, you'll be fine.
See bbrame's answer for how you might organize your controller life cycles better. I will just explain the memory management consequences of your original architecture.
So, if I got your situation right, you have something like the following. It's going to work fine even if the object may be released before returning back to someMethod
provided that you're not referencing self
in any way after the delegate method call.
Note that your view controller is probably still referenced by UIKit by the time delegate method returns. That is, if that view controller is still part of the navigation stack. In this case, you shouldn't worry about it being released too early, it'll only happen after your methods return and the control goes back to the run loop.
@interface AppController: NSObject
@property (nonatomic, strong) UpdateCheckWindowController *ctrl;
- (void)updateCheckWindowController;
- (void)iAmDoneReleaseMe;
@end
@implementation AppController
- (void)updateCheckWindowController {
UpdateCheckWindowController *ctrl = [[UpdateCheckWindowController alloc] initWithDelegate:self];
// ...
// Retain the controller
self.ctrl = ctrl;
}
- (void)iAmDoneReleaseMe {
self.ctrl = nil;
}
@end
@interface UpdateCheckWindowController: NSObject
// Make it weak so we don't have a retain cycle
@property (nonatomic, weak) AppController *delegate;
@end
@implementation UpdateCheckWindowController
- (void)someMethod
{
// do all the finishing work here
// ...
// now call the delegate that will release us
[self.delegate iAmDoneReleaseMe];
// don't do anything else here and you'll be fine
}
@end
Upvotes: 0
Reputation: 18554
You're judgement is probably right that there is a better pattern to use that avoids the circular call altogether.
If you have a view controller that is presented for a short period of time and then should be released when dismissed, you can use this method of UIViewController:
presentViewController:animated:completion:
You can autorelease the view controller you are presenting before you present it. Calling this method will retain it. When the controller should be dismissed, it can tell its delegate and the delegate can call
dismissViewController:animated:completion.
When the delegate dismisses it then it will be released.
Is this the situation or is it more complicated?
Upvotes: 1