Objective-C:静态字段和实现单例模式

发布于 2024-11-27 09:33:38 字数 266 浏览 2 评论 0原文

美好的一天,朋友们。

新手再次提出关于 Obj-C 的愚蠢问题:)

我正在尝试在 Obj-C 中实现单例设计模式:

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

编译器返回错误:“在‘静态’之前预期有说明符限定符列表”。

Good day, friends.

Once again stupid question about Obj-C from newbie :)

I'm trying to implement singleton design pattern in Obj-C:

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

Compiler returns error: "expected specifier-qualifier-list before 'static'".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

别挽留 2024-12-04 09:33:38

请在下面找到我正在使用的 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 -

只是为了帮助您从 Objective-C 开始并且不会迷失在项目结构中,您可以考虑拥有该项目结构与您的文件系统相匹配,这样当您的项目变得更大时,您就不会迷失方向。

另请考虑使用正确的类命名约定,并坚持下去。

我为您提供了我的示例:

  • 任何匹配单例模式的类都使用 Manager 后缀 命名(例如 MyCustomManager )

  • 任何静态类都使用 Helper 后缀(例如 MyCustomHelper) 命名。

  • 任何专用于控制特定进程的类都使用控制器后缀命名(例如MyPspecialTask​​Constroller)

  • 任何从另一个控件继承的 UI 控件都需要提供控件后缀(例如从 UITableViewCell 继承的 MyCustomDetailCell )

希望这有帮助。

Please find below the Objective-C code snippet I am using, for proper thread-safe singleton implementation

header file :

/*
 *
 * 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 -

implementation file :

/*
 * 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 -

Just to help you starting in objective-c and not get lost in your project structure, you can consider having the project structure matching your file system so as your project becomes bigger you won't get lost.

Also please consider using a proper class naming convention, and stick to it.

I a providing you mine as sample:

  • Any class that match singleton pattern is named using Manager suffix (E.g. MyCustomManager ).

  • Any static class is named using Helper suffix (E.g. MyCustomHelper).

  • 
Any class dedicated to control particular process is named using Controller suffix ( E.g. MyParticularTaskConstroller ).


  • Any UI control that inherit from another control needs provide control suffix ( E.g. MyCustomDetailCell inheriting from UITableViewCell )

Hope this helps.

浪荡不羁 2024-12-04 09:33:38

您不能在类接口声明中使用 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;
}

You can't use static inside a class interface declaration. The singleton should be declared as a static stand alone variable in the .m file. I normally do this (if I feel I can't avoid having a singleton):

@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;
}
故笙诉离歌 2024-12-04 09:33:38

请查看我的问题此处以及 Nick DeMoore 的精彩回答(有很多评论和代码修复)。拥有一个可以在 IB 中连接的单例(好吧,无论你在 XCode 4 中如何称呼它)确实很有帮助。

最酷的事情是,您可以使用相同的 Singleton,并将其一些插座连接到一个 NIB 中,并将其一些插座连接到另一个 NIB 中……因为它实际上是一个单例,所以整个运行时系统中只能有一个实例。效果非常好。

注意:每次你使用 Singleton 时,人们都会说这是一个坏主意。

Please check out my question here and the wonderful answer by Nick DeMoore (with lots of comments and code fixes). Having a singleton that you can wire up in IB (well, whatever you call it in XCode 4) is really helpful.

The cool thing is that you can use the same Singleton and wire some of its outlets in one NIB, and some of its outlets in another... since it's really a singleton, there can be only one instance in the entire runtime system. Works amazingly well.

Note: Every time you use Singleton people will say it's a bad idea.

櫻之舞 2024-12-04 09:33:38

static SampleSingleton* instance; 行不能位于 @interface 部分中。大多数人都把它放在上面。

Objective-c 并不像其他一些语言那样真正适合单例模式。然而,在这个问题。

有些人认为 Singleton 根本不是一个伟大的模式,我正在努力戒掉它 - 但这是我的选择。

The static SampleSingleton* instance; line can't go in the @interface section. Most people put it above.

Objective-c doesn't really lend itself to the singleton pattern as well as some other languages. However there are a bunch of different implementations to look at in this question.

Some people argue that Singleton is not a great pattern at all, and I'm trying to wean myself off using it - but that's my choice.

避讳 2024-12-04 09:33:38

这就是我通常实现单例方法

+(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 有一个共享应用程序,它执行创建单例的功能,但没有什么真正阻止您创建新实例。

This is how I usually implement a singleton method

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

to make this thread safe you would do

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

also instead of using a singleton, you already have a singleton in the form of the UIApplicationDelegate, you could always add a method to you delegate to get your SampleSingleton from your delegate.

Another point to consider about singletons is it really necessary to enforce singletons, UIApplication has a sharedApplication which performs the function of creating a singleton, but there is nothing really stopping you from creating a new instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文