Синглтон в iOS 5?

Привет, у меня была реализация предыдущих версий iOS для singleton следующим образом:

.h файл

@interface CartSingleton : NSObject 
{

}
+(CartSingleton *) getSingleton;

.m file

@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 Синглтона и новой и которая является правильной?

Спасибо большое

Ответ 1

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

+ (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/init и создать другой экземпляр.

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

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

Ответ 2

Фрагмент 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 (но это безопасно таким образом).

Ответ 3

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

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

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