2012-01-09 5 views
11

Привет У меня была реализация предыдущих версий прошивкой для одноточечного следующим образом:Синглтон в iOS 5?

.h файл

@interface CartSingleton : NSObject 
{ 

} 
+(CartSingleton *) getSingleton; 

.m файл

@implementation CartSingleton 

static CartSingleton *sharedSingleton = nil; 

+(CartSingleton *) getSingleton 
{ 
    if (sharedSingleton !=nil) 
     { 
     NSLog(@"Cart has already been created....."); 
     return sharedSingleton; 
     } 
    @synchronized(self) 
    { 
    if (sharedSingleton == nil) 
     { 
     sharedSingleton = [[self alloc]init]; 
     NSLog(@"Created a new Cart"); 
     } 
    } 
    return sharedSingleton; 
} 
//============================================================================== 
+(id)alloc 
{ 
    @synchronized([CartSingleton class]) 
    { 
    NSLog(@"inside alloc"); 
    NSAssert(sharedSingleton == nil, @"Attempted to allocate a second instance of a singleton."); 
    sharedSingleton = [super alloc]; 
    return sharedSingleton; 
    } 

    return nil; 
} 

//============================================================================== 
-(id)init 
{ 
    self = [super init]; 
} 

Однако в Интернете я вижу, люди реализовали шаблон модели Singleton с использованием этого кода:

+ (id)sharedInstance 
{ 
    static dispatch_once_t pred = 0; 
    __strong static id _sharedObject = nil; 
    dispatch_once(&pred, ^{ 
    _sharedObject = [[self alloc] init]; // or some other init method 
    }); 
    return _sharedObject; 
} 

Может ли кто-нибудь, кто имеет опыт, посоветуйте мне. Я новичок и полностью запутался между старой реализацией iOS Синглтона и новой, и которая является правильной?

спасибо

+0

См http://stackoverflow.com/questions/5720029/create-singleton-using-gcds-dispatch-once-in-objective-c для более современный, более простой, но все же потокобезопасный. –

ответ

19

Строго говоря, вы должны использовать:

+ (MySingleton*) instance { 
    static dispatch_once_t _singletonPredicate; 
    static MySingleton *_singleton = nil; 

    dispatch_once(&_singletonPredicate, ^{ 
     _singleton = [[super allocWithZone:nil] init]; 
    }); 

    return _singleton; 
} 

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

Теперь вы гарантировать, что один не может вызвать Alloc/инициализации и создать еще один экземпляр.

Объяснение: Метод экземпляра находится на уровне класса и является вашим основным методом доступа, чтобы получить ссылку на синглтон. Метод просто использует встроенную очередь dispatch_once(), которая будет выполнять только один блок. Как среда выполнения гарантирует, что блок выполняется только один раз? Используя предикат, который вы предоставляете (типа dispatch_once_t). Этот низкоуровневый вызов гарантирует, что даже если есть несколько потоков, пытающихся вызвать его, только один преуспевает, остальные ждут, пока первый не будет выполнен, а затем вернется.

Причина, по которой мы переопределяем allocWithZone, заключается в том, что alloc вызывает allocWithZone, передающий nil в качестве зоны (для зоны по умолчанию). Чтобы предотвратить изгнание кода изгоев и инициализацию другого экземпляра, мы переопределяем allocWithZone, чтобы возвращаемый экземпляр был уже инициализированным синглтоном. Это предотвращает создание второго экземпляра.

+1

Может кто-нибудь объяснить этот код более подробно, чтобы улучшить ответ? – djskinner

+0

Надеюсь, что объяснение поможет. В противном случае задайте конкретный вопрос для уточнения. –

+0

Отлично, спасибо. – djskinner

9

dispatch_once фрагмент функционально идентичен другой. Вы можете прочитать об этом по адресу http://developer.apple.com/library/mac/#documentation/Darwin/Reference/Manpages/man3/dispatch_once.3.html.

Это то, что я использую для одиночек:

+ (MySingleton*) getOne { 
    static MySingleton* _one = nil; 

    @synchronized(self) { 
     if(_one == nil) { 
      _one = [[ MySingleton alloc ] init ]; 
     } 
    } 

    return _one; 
} 

ПРИМЕЧАНИЕ: В большинстве случаев вам даже не нужно использовать @synchronized (но это безопасно таким образом).

+1

блокирует работу в iOS 4. –

+0

+ Peter DeWeese - вы правы. моя вина. –

+0

Если вы не используете @syncrhonized в другом месте, это приводит к огромному количеству накладных расходов для обработки исключений ObjectiveC - поэтому, если вы их не используете, вы должны использовать выбранный ответ и версию блока. –

0

Singleton - это особый класс, в котором существует только один экземпляр класса для текущего процесса. (В случае приложения iPhone один экземпляр используется во всем приложении.) Некоторые примеры в UIKit - это [UIApplication sharedApplication] (который возвращает единственный экземпляр самого приложения) и [NSFileManager defaultManager] (который возвращает экземпляр файлового менеджера). Синглтоны могут быть простым способом обмена данными и распространенными методами во всем приложении.

Вместо того, чтобы создавать экземпляры одноэлементного класса с помощью alloc/init, вы вызовете метод класса, который вернет объект singleton. Вы можете назвать метод класса любым, но обычной практикой является вызов его sharedName или defaultName.

Пожалуйста, проверьте связь с лучшим ответом : http://www.idev101.com/code/Objective-C/singletons.html