What's the correct method to subclass a singleton class in Objective -C?

后端 未结 9 914
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-09 18:23

I have created a singleton class and I want to create a class which is subclass of this singleton class, what is the correct method to do it

相关标签:
9条回答
  • 2020-12-09 18:33

    If what you are looking for is a quick way to setup new singletons. This pseudo abstract singleton base class is what I use:

    Reusable base class

    H

    #define CREATE_SHARED_INSTANCE          \
    + (instancetype)sharedInstance {        \
        static dispatch_once_t once;        \
        static id instance = nil;           \
        dispatch_once(&once, ^{             \
            instance = [[self alloc] init]; \
        });                                 \
        return instance;                    \
    }
    
    @interface SharedObject : NSObject
    + (instancetype)sharedInstance;
    @end
    

    M

    @implementation SharedObject
    + (instancetype)sharedInstance {
        [NSException raise:@"Call to unimplemented sharedInstance" format:@"%@ does not implement sharedInstance.", NSStringFromClass([self class])];
        return nil;
    }
    @end
    

    Then each subclass

    H

    #import "SharedObject.h" 
    @interface SomeSubclass : SharedObject
    @end
    

    M

    @implementation SomeSubclass
    CREATE_SHARED_INSTANCE 
    @end
    

    ...and use like any singleton.

    [[SomesSubclass SharedInstance] someMethod];
    

    If you call the abstract base class, or forget to include CREATE_SHARED_INSTANCE in your subclass, you will get a friendly exception raised.

    This way you can setup a new singletons easily at no performance hit.

    0 讨论(0)
  • 2020-12-09 18:34

    If Jon didn't convinced you to not do it, you should do it this way:

    In your superclass, init your singleton instance with [[[self class] alloc] init] so then you always get an instance of the class with which you are calling the sharedInstance method. And you don't have to overwrite the sharedInstance method in your subclass.

     [SuperClass sharedInstance] //-> instance of SuperClass
     [SubClass sharedInstance] //-> instance of Class
    
    0 讨论(0)
  • 2020-12-09 18:38

    I don't know about Objective-C in particular, but in general singleton classes should prevent subclassing. If you've got an instance of the base class and an instance of the subclass, then you've effectively got two objects you can regard as instances of the base "singleton" class, haven't you?

    As soon as you've got two instances, it's not really a singleton any more... and that's leaving aside the possibilities that there are multiple subclasses, or that the subclass itself allows multiple instances to be created.

    Of course you can change your base class so it just has a way of getting at a single "default" instance, but that's not quite the same as making it a singleton.

    0 讨论(0)
  • 2020-12-09 18:42

    The simplest way to achieve this is implement the standard singleton accessor in both the class and the subclass. This way each class behaves as a proper singleton, that is there is only ever one instance of both. If you attempt to reuse the accessor of the parent class in the subclass and then if you make use of both classes, you run the risk of the accessor returning the wrong instance because their behaviour would depend on the order of how they are accessed.

    You should not use instancetype for the singleton accessor to help prevent this mistake. You'll notice Apple don't use it for their singletons e.g. UIApplication and CKContainer.

    If you would like existing code that accesses the super-class's singleton method be given an instance of the subclass then likely you need to redesign, see MrJre's answer.

    0 讨论(0)
  • 2020-12-09 18:43

    I had the same problem. This is how to solve: You need to use a static dictionary to subclass a singleton. For exemple:

    Class A : NSObject -> Singleton

    Class B : A

    Class C : A

    @implementation A
    
    // Dictionary that holds all instances of API subclasses
    static NSMutableDictionary *_sharedInstances = nil;
    
    + (instancetype)sharedInstance
    {
        id sharedInstance = nil;
        @synchronized(self)
        {
           NSString *instanceClass = NSStringFromClass(self);
    
           if (_sharedInstances == nil)
               _sharedInstances = [NSMutableDictionary dictionary];
    
           // Looking for existing instance
           sharedInstance = [_sharedInstances objectForKey:instanceClass];
    
           // If there's no instance – create one and add it to the dictionary
           if (sharedInstance == nil) 
           {
              sharedInstance = [[super allocWithZone:nil] init];
              [_sharedInstances setObject:sharedInstance forKey:instanceClass];
           }
       }
       return sharedInstance;
    

    }

    Now you can use [B sharedInstance] and [C sharedInstance] without problems!

    0 讨论(0)
  • 2020-12-09 18:45

    I made an example "base class" for singleton, you can check it here: https://github.com/stel/DOSingleton

    0 讨论(0)
提交回复
热议问题