Objective-C: статическое поле и реализация одиночного шаблона - PullRequest
2 голосов
/ 02 августа 2011

Добрый день, друзья.

Еще раз глупый вопрос об Obj-C от новичка:)

Я пытаюсь реализовать шаблон проектирования Singleton в Obj-C:

@interface SampleSingleton : NSObject {
@private
    static SampleSingleton* instance;
}
+(SampleSingleton*) getInstance;

Компилятор возвращает ошибку: «ожидаемый список спецификаторов-спецификаторов перед статическим».

Ответы [ 5 ]

8 голосов
/ 02 августа 2011

Ниже приведен фрагмент кода Objective C, который я использую, для правильной многопоточной реализации одноэлементной *

заголовочный файл:

/*
 *
 * Singleton interface that match Cocoa recommendation
 * @ http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32
 * extended with thread-safe pattern
 */
@interface MyCustomManager : NSObject { 
}

#pragma mark Singleton Thred-Safe Pattern

+ (MyCustomManager *) sharedInstance;
+ (id)allocWithZone:(NSZone *)zone;
- (id)copyWithZone:(NSZone *)zone;
- (id)retain;
- (NSUInteger)retainCount;
- (void)release;
- (id)autorelease;

#pragma mark -

файл реализации:

/*
 * My custom manager Class singleton implementation
 */
@implementation MyCustomManager

#pragma mark Initializers

/*
 * specific initialize goes here
 */
- (void) specificInitialize
{
    // ...
}

/*
 * Ensure any owned object is properly released
 */
- (void) dealloc
{
[super dealloc];
}

#pragma mark -

#pragma mark Singleton Thred-Safe Pattern

//- use Volatile to make sure we are not foiled by CPU caches
static void * volatile sharedInstance = nil;                                                

/*
 * retrieve sharedInstance based on OSAtomicCompareAndSwapPtrBarrier that 
 * acts as both a write barrier for the setting thread and a read barrier from the testing thread
 * more info @ http://stackoverflow.com/questions/145154/what-does-your-objective-c-singleton-look-like/2449664#2449664
 * and http://stackoverflow.com/questions/6915/thread-safe-lazy-contruction-of-a-singleton-in-c/6943#6943
 */
+ (MyCustomManager *) sharedInstance {  
    //- check sharedInstance existenz 
    while (!sharedInstance) {  
        //- create a temporary instance of the singleton    
        id temp = [super allocWithZone:NSDefaultMallocZone()];
        //- The OSAtomicCompareAndSwapPtrBarrier function provided on Mac OS X 
        //- checks whether sharedInstance is NULL and only actually sets it to temp to it if it is. 
        //- This uses hardware support to really, literally only perform the swap once and tell whether it happened.
        if(OSAtomicCompareAndSwapPtrBarrier(0x0, (void *)temp, &sharedInstance)) {
            //- compute singleton initialize
        MyCustomManager *singleton = (MyCustomManager *) sharedInstance;
            [singleton specificInitialize];
        }
        else {
            //- if the swap didn't take place, delete the temporary instance
            [temp release]; 
            temp = nil;
        }                                                                                                 
    }   
    //- return computed sharedInstance
    return sharedInstance;                                                                        
}

/*
 * method to ensure that another instance is not allocated if someone tries to allocate 
 * and initialize an instance of your class directly instead of using the class factory method. 
 * Instead, it just returns the shared object.
 */
+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedInstance] retain];
}

/*
 * Implements the base protocol methods to do the appropriate things to ensure singleton     status. 
 * Applies to memory-managed code, not to garbage-collected code
 */
- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

/*
 * Implements the base protocol methods to do the appropriate things to ensure singleton status. 
 * Applies to memory-managed code, not to garbage-collected code
 */
- (id)retain
{
    return self;
}

/*
 * Implements the base protocol methods to do the appropriate things to ensure singleton status. 
 * Applies to memory-managed code, not to garbage-collected code
 */
- (NSUInteger)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

/*
 * Implements the base protocol methods to do the appropriate things to ensure singleton status. 
 * Applies to memory-managed code, not to garbage-collected code
 */
- (void)release
{
    //do nothing
}

/*
 * Implements the base protocol methods to do the appropriate things to ensure singleton status. 
 * Applies to memory-managed code, not to garbage-collected code
 */
- (id)autorelease
{
    return self;
}

#pragma mark -

Просто, чтобы помочь вам начать с target-c и не потеряться в структуре вашего проекта, вы можете подумать о том, чтобы структура проекта соответствовала вашей файловой системе, чтобы по мере роста вашего проекта вы не потерялись.

Также, пожалуйста, подумайте об использовании правильного соглашения об именах классов и придерживайтесь его.

Я могу предоставить вам мой пример:

  • Любой класс, который соответствует одноэлементному шаблону, назван с использованием суффикса Manager (например, MyCustomManager) .

  • Любой статический класс назван с использованием суффикса Helper (например, MyCustomHelper) .

  • Назван любой класс, предназначенный для управления конкретным процессом.с использованием суффикса контроллера (например, MyParticularTaskConstroller) .

  • Любой элемент управления пользовательского интерфейса, который наследуется от другого элемента управления, должен содержать суффикс элемента управления (например, MyCustomDetailCell, наследующий от UITableViewCell)

Hopeэто помогает.

8 голосов
/ 02 августа 2011

Вы не можете использовать static внутри объявления интерфейса класса.Одиночка должна быть объявлена ​​как статическая автономная переменная в файле .m.Обычно я делаю это (если я чувствую, что не могу избежать синглтона):

@interface SampleSingleton : NSObject 
{
@private
}

+(SampleSingleton*) theSingleton;

@end

// .m file 

@implementation SampleSingleton

+(SampleSingleton*) theSingleton
{
    static SampleSingleton* theSingleton = nil;

    if (theSingleton  == nil)
    {
        theSingleton = [[SampleSingleton alloc] init];
    }
    return theSingleton;
}
1 голос
/ 02 августа 2011

Пожалуйста, проверьте мой вопрос здесь и замечательный ответ Ника ДеМура (с множеством комментариев и исправлений кода). Наличие синглтона, который вы можете подключить в IB (ну, как бы вы его ни называли в XCode 4), действительно полезно.

Круто то, что вы можете использовать один и тот же синглтон и соединить некоторые из его выходов в одном NIB, а некоторые из его выходов - в другом ... поскольку это действительно синглтон, во всей среде выполнения может быть только один экземпляр система. Работает на удивление хорошо.

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

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

Вот как я обычно реализую метод синглтона

+(SampleSingleton * )sampleSingleton
{
    static SampleSingleton   * theSampleSingleton = nil;
    if( theSampleSingleton == nil )
        theSampleSingleton = [[SampleSingleton alloc] init];
    return theSampleSingleton;
}

чтобы сделать эту тему безопасной, вы должны сделать

+(SampleSingleton * )sampleSingleton
{
    static SampleSingleton   * theSampleSingleton = nil;
    if( theSampleSingleton == nil )
    {
        @syncronise([SampleSingleton class])
        {
            if( theSampleSingleton == nil )
                theSampleSingleton = [[SampleSingleton alloc] init];
        }
    }
    return theSampleSingleton;
}

Кроме того, вместо использования синглтона, у вас уже есть синглтон в форме UIApplicationDelegate, вы всегда можете добавить свой делегат метод для получения вашего SampleSingleton от вашего делегата.

Еще один момент, который следует учитывать применительно к синглетам, это то, что действительно необходимо применять синглеты. UIApplication имеет sharedApplication, которая выполняет функцию создания синглтона, но ничто не мешает вам создать новый экземпляр.

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

Статическая строка SampleSingleton* instance; не может находиться в разделе @interface.Большинство людей ставят это выше.

Objective-c на самом деле не поддается шаблону синглтона, как некоторые другие языки.Однако в этом вопросе .

. *1008* есть множество различных реализаций. Некоторые люди утверждают, что синглтон - не очень хорошая модель, и я пытаюсь отучить себя, используяэто - но это мой выбор.

...