Возврат статического с помощью allocWithZone - PullRequest
0 голосов
/ 06 марта 2012

Отрабатывая идею из руководства Big Nerd Ranch по программированию на iOS, я пытаюсь определить одноэлементный объект следующим образом:

@implementation ImageStore

static ImageStore *defaultImageStore = nil;

- (id)init
{
    if (defaultImageStore) {
        return defaultImageStore;
    }

    self = [super init];
    if (self) {
        dictionary = [[NSMutableDictionary alloc] init];
    }

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self selector:@selector(clearCache) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

    return self;
}

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

+ (ImageStore *)defaultImageStore
{
    if (!defaultImageStore) {
        defaultImageStore = [[super allocWithZone:NULL] init];
    }
    return defaultImageStore;
}

Это работает нормально, но анализатор жалуется на allocWithZone,поговорка

Объект с +0 счетами удержания возвращается вызывающей стороне, где ожидается +1 (счет владения), сохраняющий счет

Я думаю, что код просто обманывает анализатор и чтовсе в порядке, но есть ли лучшая модель, чтобы делать то, что я пытаюсь сделать?

Ответы [ 2 ]

2 голосов
/ 06 марта 2012

Я не беспокоюсь обо всем этом.Это мой шаблон:

@ реализация MyClass

-(id) init { ... } /* normal init */

+(MyClass*) defaultMyClass
{
    static MyClass* theObject = nil;
    @synchronized([MyClass class])  // remove synchronzed block in single threaded app
    {
        if (theObject == nil)
        {
            theObject = [[self alloc] init];
        }
    }
    return theObject;
}

Возможно, вы можете скрыть инициализатор в расширении класса, чтобы было задокументировано, что вы не должны его использовать.

Есть также метод GCD (ниже украдено из ссылки Роба Напира), который на самом деле более легкий.

+ (id) defaultMyClass
{
    static dispatch_once_t pred;
    static MyClass* theObject = nil;

    dispatch_once(&pred, ^{ theObject = [[self alloc] init]; });
    return theObject;
}

Я всегда сопротивлялся шаблону GCD, потому что на мой взгляд это выглядит менее очевиднопроисходит.Тем не менее, это ничего не может быть исправлено с комментариемБлокировки, используемые GCD, более легкие по сравнению с @synchronized, поэтому это будет быстрее.

0 голосов
/ 07 марта 2012

Как я уже упоминал в комментарии, решение предупреждения компилятора было столь же простым, как добавление сохранения к выражению, которое упоминается в Apple doc .

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

Примечание.Я не упоминал об этом, но я разрабатываю для iOS и обнаружил, что метод dispatch_once, кажется, останавливает выполнение моего приложения.

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