Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting self-releasing objects to ARC

OK, so Apple brought ARC to us, which is great. After refactoring my Application to ARC almost everything works fine and it is a lot easier now to develop and maintain.

There is just one problem I still can't figure out.

My job management program shows different detail information of proposals, orders and so on in their own windows. So I have a special class where WindowControllers gets allocated and initiated with initWithWindowNibName and then the window is shown with showWindow:

DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:@"ThePorposalWindow"];
[proposalWindowController showWindow:nil];

Before ARC the Instance of the WindowController did the release like shown in the documentation:

- (void)windowWillClose:(NSNotification *)notification
{
   [self autorelease];
}

But now with ARC this is not possible anymore and what makes it even worse, in my special class where the WindowController is allocated and initiated, the same windowController is released by ARC because there is no pointer to the windowController.

My idea was to copy the windowController into an mutuable array:

[proposalWindowArray addObject:proposalWindowController];
[[proposalWindowArray lastObject] showWindow:nil];

And in the windowControllers delegate method windowWillClose I post a notification to my special class:

- (void)windowWillClose:(NSNotification *)notification
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ProposalWindowWillClose" object:[[self window] windowController] userInfo:nil];
}

In my special class I listen to the notification and remove the object from the array:

- (void) proposalWindowWasClosed: (NSNotification *) notification
{
    [proposalWindowArray removeObjectIdenticalTo:[notification object]];
}

It works, but I still do not believe that this is the correct way.

Does anybody has the same problem or a tip to make it better?

like image 880
archibaldtuttle Avatar asked Feb 22 '12 11:02

archibaldtuttle


1 Answers

I'd probably use a delegate approach rather than notifications. Generally it is better to have an external object that keeps track of the open windows. Self-retaining objects, like your old system, break the basic points of object ownership and make it hard to find things (such as "give me a list of open windows"). Non-Singletons that are just "floating" out there often come back to bite you in your architecture (I've had to fix this often enough).

That said, sometimes self-ownership is at least convenient, and at worst not-the-end-of-the-world. So self-own. The only difference is that you need to do it explicitly rather than matching a leak and an over-release (which is what your old code was doing).

Create a private strong property. Assign self to it. That will create a retain loop that will keep you around until you set the property to nil.

like image 191
Rob Napier Avatar answered Oct 29 '22 15:10

Rob Napier