Objective-C синглтон базовый класс - PullRequest
4 голосов
/ 08 декабря 2010

Есть ли способ создать шаблон Singleton с помощью target-c, который позволил бы клиентскому коду получить общий экземпляр любого из его подклассов?

Я пытался:

@interface Base : NSObject {}
+(id)instance;
@end

@implementation Base
static id _instance;
+(id)instance {
    if (!_instance) {
        _instance = [[self alloc] init];
    }
    return _instance;
}
@end

Но вызов [AmazingThing instance] любого подкласса возвращает только первый экземпляр, созданный с помощью этого механизма, независимо от типа _instance.Есть ли обходные пути?

Редактировать

Я понял (отвечая на удаленный ответ), что могу сделать то, что искал, изменив реализацию на:

static NSMutableDictionary *_instances;

+(id)instance {
    if (!_instances) {
        _instances = [[NSMutableDictionary alloc] init];
    }
    id instance = [_instances objectForKey:self];
    if (!instance) {
        instance = [[self alloc] init];
        [_instances setObject:instance forKey:self];
    }
    return instance;
}

Теперь работает как положено.Тем не менее, мне интересно узнать, есть ли лучший способ сделать это.

Ответы [ 4 ]

7 голосов
/ 08 декабря 2010

Я бы сделал это так:

+(id) instance
{
    static id theInstance = nil;
    if (theInstance == nil)
    {
        theInstance = [[self alloc] init];
    }
    return theInstance;
}

Конечно, вам понадобится этот метод в каждом подклассе вашего базового класса, чтобы получить разные статические переменные для каждого класса.Но вы должны создать #define в заголовке базового класса:

#define CREATE_INSTANCE           \
+(id) instance                    \
{                                 \
    static id theInstance = nil;  \
    if (theInstance == nil)       \
    {                             \
        theInstance = [[self alloc] init]; \
    }                             \
    return theInstance;           \
}

, и тогда у каждой имплементации будет только определение:

@implementation SubClass

CREATE_INSTANCE

// other stuff

@end
1 голос
/ 08 декабря 2010

Если вы используете Objective-C ++ - это нормально. Что вы можете сделать, так это иметь метапрограммируемый класс C ++, который управляет временем жизни одноэлементного объекта. Таким образом, вы можете использовать шаблон Singleton и получить доступ к нему с помощью Derived* d = Singleton<Derived>::get(). Для дальнейшего ознакомления вы можете посмотреть на http://src.chromium.org/viewvc/chrome/trunk/src/base/singleton_objc.h, как chrome удается это сделать.

0 голосов
/ 12 апреля 2013

Вы также можете проверить DOSingleton на https://github.com/stel/DOSingleton

Я использую ту же идею с глобальным словарем.

0 голосов
/ 02 августа 2012

Просто используйте EPPZSingleton .

Создать базовый класс, который может иметь ровно один подкласс, довольно просто, но когда вы начинаете создавать все больше и больше подклассов, вы можете ожидать нежелательного поведения.EPPZSingleton решает эту проблему, поддерживая общую коллекцию синглетонов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...