Singleton Design

半城伤御伤魂 提交于 2019-12-06 11:09:44

It sounds like an infinite loop. Make sure that -[AppController init] isn't calling +[AppController instance].

Why does every card need a reference to the app controller?

If it's just to access its words, it's simpler to let each card own its words directly. Make a new method named initWithWords: the designated initializer for the GameCard class. Initialize each card with the array of its five words, and have the card own that array for its lifetime.

Removing the cards' references to the app controller would resolve the infinite loop that Tom astutely detected.

Also, if no word should appear on two cards at once, remember to take that into account when drawing from the app controller's Great Big Array Of Words, and when destroying cards (you may or may not want the words to go back into the pile for future cards).

It sounds like you're on the right track. I've never tried to put a reference to a singleton in a nib file, though. You may want to create a separate singleton class that maintains a copy of the data (DataManager, maybe?), and then call it from within your instance of AppController to fetch the words.

You may find that putting a singleton within a nib (using the code for a singleton in Stu's post) works just fine, though. Good luck!

It looks like you may be calling your class instance method from within your init method. Try something like this:

static AppController* _instance = nil;

- (id)init
{
    // depending on your requirements, this may need locking
    if( _instance ) {
        [self release];
        return _instance;
    }
    if( (self = [super init]) ) {
        _instance = [self retain];
        // do your initialization
    }
    return self;
}

+ (AppController*)instance
{
    if( _instance ) return _instance;
    else            return [[AppController alloc] init];
}

This makes sure that only one instance of AppController is ever available and also that it's safe to allocate it as well as getting a copy through the instance class method. It's not thread safe, so if it's going to be accessed by multiple threads, you should add some locking around the checks to _instance.

The normal way to create an AppController/AppDelegate is to add a custom NSObject to your MainMenu/MainWindow.xib file. Set the class to be AppController. Link your UIApplication/NSApplication delegate reference to your AppController object. Then you can get your single AppController with either

(AppController*)[NSApp delegate];

or

(AppController*)[[UIApplication sharedApplication] delegate];

You never have to create it with alloc/init because it will be created when your application is launched. You don't have to worry about making it a singleton because no one will ever try to create another one. And you don't have to worry about how to access it because it will be the delegate of the UIApplication/NSApplication object.

All that said, if you need a global variable holding an array of words, then forget about the AppController and make a new singleton object which holds/reads the array. In which case you just need:

+ (NSArray *)sharedWordListArray 
{
    static NSArray *wordList;
    if( !wordList ) {
        wordList = [[NSMutableArray alloc] init];
        // read array
    }
    return wordList;
}

If you really need thread safety, then simply call [WordList sharedWordListArray] from your app delegate's applicationDidFinishLaunching: method before starting any threads, or add an NSLock if you really want to defer the loading to later, but often its better to take the load time hit at the start of the program rather than unexpectedly when the user takes some later action.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!