Пример запроса Apple Singleton? - PullRequest
1 голос
/ 09 марта 2010

Меня немного смущает этот фрагмент кода (представленный в руководстве CocoaFundamentals), который переопределяет некоторые методы при создании экземпляра синглтона.

static id sharedReactor = nil;

+(id)sharedInstance {
    if(sharedReactor == nil) sharedReactor = [[super allocWithZone:NULL] init];
    return sharedReactor;
}

.

+(id)allocWithZone:(NSZone *)zone {
    return[[self sharedInstance] retain];
}

-(id)retain {
    return self;
}

В коде, где создается экземпляр singleton, метод + sharedInstance вызывает [super allocWithZone: NILL] из суперкласса (в моем случае это NSObject). Вышеуказанный allocWithZone вызывается, только если вы пытаетесь использовать его для создания нового синглтон.

Что меня смущает, так это использование retain, особенно учитывая, что retain также отвергается, чтобы вернуть себя. Может кто-нибудь объяснить это, не может быть написано:

+(id)allocWithZone:(NSZone *)zone {
    return [self sharedInstance];
}

-(id)retain {
    return self;
}

EDIT_001:

Основываясь на комментариях и прочтении различных постов в Интернете, я решил перейти к следующему (см. Ниже), который я выбрал для совместного использования синглтона, где при необходимости у меня будет возможность создать второй или третий экземпляр. , Также на этом этапе, так как я использую только синглтон для модельной части MVC для простого приложения для iPhone, я решил не использовать безопасность потоков. Я знаю, что это важно, и по мере знакомства с программированием на iPhone я, скорее всего, вместо этого буду использовать + initialize (имея в виду проблему с подклассом, когда он может вызываться дважды) быть освобожденным, но также и убирать вещи должным образом, если синглтон больше не требуется.

@interface SharedManager : NSObject
+(id)sharedInstance;
@end

@implementation SharedManager

static id myInstance = nil;

+(id)sharedInstance {
    if(myInstance == nil) {
        myInstance = [[self alloc] init];
    }
    return myInstance;
}

-(void)dealloc {
    NSLog(@"_deal: %@", [self class]);
    [super dealloc];
    myInstance = nil;
}
@end

При тестировании я обнаружил, что у меня установлена ​​статическая переменная в nil в значении nil, или он сохранил свой указатель на исходный объект. Первоначально меня это немного смутило, поскольку я ожидал, что область действия статического объекта будет являться экземпляром, я думаю, что вместо этого это класс, что имеет смысл.

Ура Гэри

Ответы [ 2 ]

5 голосов
/ 09 марта 2010

Во-первых, не используйте этот код. Почти никогда нет причин делать все это для простого синглтона. Apple демонстрирует «Принудительный синглтон», в котором невозможно создать два из них. Очень редко это действительно нужно. Вы почти всегда можете использовать подход «синглтон с общим доступом», используемый большинством объектов Какао, имеющих конструктор синглтона.

Вот мой предпочтительный способ реализации общего синглтона:

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

Вот и все. Никакого другого кода не требуется. Вызывающие абоненты, использующие +sharedManager, получат общий экземпляр. Вызывающие абоненты, которые вызывают +alloc, могут создавать уникальные экземпляры, если они действительно этого хотят. Так работают такие знаменитые «синглтоны», как NSNotificationCenter. Если вы действительно хотите иметь свой собственный частный центр уведомлений, то нет причин, по которым класс должен это запрещать. Этот подход имеет следующие преимущества:

  • Меньше кода.
  • Более гибкий в тех случаях, когда полезен экземпляр без общего доступа.
  • Самое главное: код делает то, что говорит. Вызывающий объект, который думает, что создает уникальный экземпляр с +alloc, не сталкивается с удивительным поведением «жуткое действие на расстоянии», которое требует, чтобы он знал внутренние детали реализации объекта.

Если вам действительно нужен принудительный синглтон, потому что рассматриваемый объект сопоставляется с уникальным ресурсом, который не может быть совместно использован (и в такой ситуации очень редко встречается), тогда вам все равно не следует использовать +alloc обман, чтобы обеспечить его соблюдение. Это просто маскирует ошибку программирования при попытке создать новый экземпляр. Вместо этого вы должны поймать ошибку программирования следующим образом:

+ (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;
}
3 голосов
/ 09 марта 2010

Вот хороший пример различных одноэлементных методов с комментариями к SO: Как выглядит ваш синглтон Objective-C?

Если это поможет, в примере используется другой подход к allocWithZone: возвращается ноль.

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