Question

I just ran myself round in circles, all coming down to having instantiated an app delegate object in a secondary NIB that wasn't the NSMainNibFile. Amazing how having two app delegates kicking around means you have separate managedObjectContexts.

Here's a thought-- could I make my application delegate class a singleton? And safely instantiate it in more XIBs? What would that break?

Also, there are some mentions on stackoverflow that [[UIApplication sharedApplication] delegate] is a "singleton" but it doesn't appear that UIApplicationDelegate protocol guarantees that, nor is the superclass UIResponder a singleton, either. So could I shoot myself in the foot in this regard on iOS as well?

[edit] Looks like you could nil out the delegateClassName in UIApplicationMain for iOS and have the main NIB load the delegate object, so you could create the App Delegate object pattern seen on OSX, if using a main NIB.

[edit2] Screenshot of what MainMenu.xib looks like for a new non-document application. The project gets created with this object, app delegate class gets created with a window property. The issue is getting that nice handy object in other NIBs, and that object being the same as [NSApp delegate] enter image description here

Was it helpful?

Solution 3

Okay, after the question having been voted up, and then voted down to zero because of who-knows-why, I've continued to investigate my own answer. I think it's useful to make your app delegate classes true singletons so you can't cause headaches with NIBs. I can't see why it would be harmful. And I think if your app has a single user interface, it's not unreasonable to have the app delegate own the core data stack for all NIBs. However, the recommended design pattern would be to then have each window or view controller be passed the ManagedObjectContext pointer, and to access the MOC through the File's Owner placeholder rather than using an App Delegate object.

Yet on the other hand, things are different with the "Shared User Defaults Controller" singleton, which gets a special object in every NIB. We don't have to pass every controller a pointer to it so that every view can access it. It's just omnipresent. The app delegate is different. There's no "Shared App Delegate" object in every NIB. Yes, there are reasons to never talk to the app delegate in NIBs, but that's not an answer to the question.

So, an answer.

Singleton design patterns: Covered long ago by Apple in this deprecated reference document-- Creating a Singleton Instance.

Turns out what I want my application delegate class to implement is the "strict" implementation, rather than having a factory method which could create other objects of the app delegate class. The one different feature here is having [NSApp delegate] be the master pointer rather than an app delegate class function.

The strict implementation has to override allocWithZone for my application delegate class (as alloc calls allocWithZone).

+ (MYAppDelegate*)allocWithZone:(NSZone *)zone
{
    if ([NSApp delegate] == nil) return [super allocWithZone:zone];
    return [NSApp delegate];
}

- (MYAppDelegate*)copyWithZone:(NSZone *)zone
{
    return self;
}

Init just returning [super init] is fine, so it needs no override.

Seems to work. I'll update this if not.

[update] I have also been investigating NIB loading using NSBundle's loadNibNamed:owner:topLevelObjects: -- but it appears that I'd get an array back with a new app delegate object, even from that method. The method allows getting pointers to the top-level objects in the NIB without having otherwise created outlets for them. Still seems the best method to get an app delegate object in a XIB other than MainMenu is to use something like the code above.

[another update] Why it could be harmful: According to the the section "Top-level Objects in OS X May Need Special Handling" in this document, there's good reason for me to believe that, even with ARC, this answer of mine increases the retain count on [NSApp delegate], but heck if I feel okay doing a bridge and a release on the app delegate in dealloc for the window/view controllers that have a top-level object for the app delegate. Plus that means code outside the app delegate class.

OTHER TIPS

Just do this in your existing App Delegate (There will only be one!)

// In the header file    
+ (AppDelegate*) sharedInstance;


// In the body
+ (AppDelegate*) sharedInstance {

    return (AppDelegate*) [[UIApplication sharedApplication] delegate];

}

Then anywhere you want to refer to your App Delegate, you can simply use [AppDelegate sharedInstance] followed by the property or instance method you want to call.

You shouldn't be using the app delegate for stuff to do with core data anyway. So making it an enforced singleton is pointless.

Ideally nothing should need to reference back to it at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top