Apple Singleton example query?

前端 未结 2 1950
北恋
北恋 2021-01-24 06:46

I am a little confused by this snippet of code (presented in the CocoaFundamentals guide) that overrides some of the methods when creating a singleton instance.

         


        
相关标签:
2条回答
  • 2021-01-24 07:16

    There is a good example of different singleton methods with comments here on SO: What does your Objective-C singleton look like?

    If it helps, the example has a different approach to allocWithZone: which returns nil.

    0 讨论(0)
  • 2021-01-24 07:19

    First, don't use this code. There is almost never a reason to do all this for a simple singleton. Apple is demonstrating a "Forced Singleton," in that it is impossible to create two of them. It is very rare to really need this. You can almost always use the "shared singleton" approach used by most of the Cocoa objects that have a singleton constructor.

    Here's my preferred way of implementing shared singleton:

    + (MYManager *)sharedManager
    {
        static MYManager *sharedManager = nil;
        if (sharedManager == nil)
        {
            sharedManager = [[self alloc] init];
        }
        return sharedManager;
    }
    

    That's it. No other code is required. Callers who use +sharedManager will get the shared instance. Callers who call +alloc can create unique instances if they really want to. This is how such famous "singletons" as NSNotificationCenter work. If you really want your own private notification center, there is no reason the class should forbid it. This approach has the following advantages:

    • Less code.
    • More flexible in cases where a non-shared instance is useful.
    • Most importantly: the code does what it says it does. A caller who thinks he's making a unique instance with +alloc doesn't encounter surprising "spooky action at a distance" behavior that requires him to know an internal implementation detail of the object.

    If you really need a forced singleton because the object in question maps to a unique resource that cannot be shared (and it's really rare to encounter such a situation), then you still shouldn't use +alloc trickery to enforce it. This just masks a programming error of trying to create a new instance. Instead, you should catch the programming error this way:

    + (MYManager *)sharedManager
    {
        static MYManager *sharedManager = nil;
        if (sharedManager == nil)
        {
            sharedManager = [[self alloc] initSharedManager];
        }
        return sharedManager;
    }
    
    - (id)init
    {
        NSAssert(NO, @"Attempting to instantiate new instance. Use +sharedManager.");
        return nil;
    }
    
    // Private method. Obviously don't put this in your .h
    - (id)initSharedManager
    {
        self = [super init];
        ....
        return self;
    }
    
    0 讨论(0)
提交回复
热议问题