Objective-C – 优化这个单例模式?

我发现网上的单身模式。 在我看来,它有很多可以优化的东西。

sharedMySingleton方法中,不需要调用retain? 我不确定…
– 如果不是,为什么在allocWithZone有一个保留?
– 什么是@synchronized的使用。 NSAssert认为块可以被调用多次,所以如果是的话,应该有更多的代码释放以前的内存,或者没有NSAsserting清除退出块,如果没有,为什么有这个NSAssert?
– 链接sharedMySingletonsharedMySingleton似乎很奇怪。 我写了自己的东西:

 +(MySingleton*)sharedMySingleton { @synchronized([MySingleton class]) { if (_sharedMySingleton == nil) _sharedMySingleton = [[self alloc] init]; return _sharedMySingleton; } return nil; } +(id)alloc { @synchronized([MySingleton class]) { return [super alloc]; } return nil; } 

单身模式

 #import "MySingleton.h" @implementation MySingleton // ########################################################################################################## // ######################################## SINGLETON PART ################################################## // ########################################################################################################## static MySingleton* _sharedMySingleton = nil; // ================================================================================================= +(MySingleton*)sharedMySingleton // ================================================================================================= { @synchronized([MySingleton class]) { if (_sharedMySingleton == nil) [[self alloc] init]; return _sharedMySingleton; } return nil; } // ================================================================================================= +(id)alloc // ================================================================================================= { @synchronized([MySingleton class]) { NSAssert(_sharedMySingleton == nil, @"Attempted to allocate a second instance of a singleton."); _sharedMySingleton = [super alloc]; return _sharedMySingleton; } return nil; } + (id)allocWithZone:(NSZone *)zone { return [[self sharedMySingleton] retain]; } - (id)copyWithZone:(NSZone *)zone { return self; } - (id)retain { return self; } - (NSUInteger)retainCount { return NSUIntegerMax; /* denotes an object that cannot be released */} - (oneway void)release { /* do nothing */ } - (id)autorelease { return self; } // ########################################################################################################## // ########################################################################################################## // ########################################################################################################## // ================================================================================================= -(id)init // ================================================================================================= { if (!(self = [super init])) return nil; return self; } // ================================================================================================= -(void) dealloc // ================================================================================================= { [super dealloc]; } // ================================================================================================= -(void)test // ================================================================================================= { NSLog(@"Hello World!"); } @end 

你根本不应该使用这个模式(这对于Singleton的一个非常特殊的情况几乎是不需要的,甚至在这种情况下你通常不应该使用它)。

有很多很好的模式讨论在什么我的Objective-C单身人士看起来像? ,但是自从GCD发布以来,其中大部分已经过时了。 在Mac和iOS的现代版本中,您应该使用Colin Barrett在链接问题中给出的以下模式:

 + (MyFoo *)sharedFoo { static dispatch_once_t once; static MyFoo *sharedFoo; dispatch_once(&once, ^{ sharedFoo = [[self alloc] init]; }); return sharedFoo; } 

我只在这里复制它,而不是标记问题的重复,因为旧问题的答案最高的答案已经过时。

不需要retain因为有一个alloc 。 调用retain在上面会导致内存泄漏。 allocWithZone上有保留,因为它是一个单例,所以我们不想创build两个不同的类的实例。 而是分配一个新的实例,我们增加了单例实例的保留数。 这是为什么? 可能是为了防止有人不知道类的单身types。 如果他调用allocWithZone然后释放实例,一切仍然正常,他实际上访问共享的单例实例。

@synchronized用于防止来自两个不同线程的两个调用同时input到if语句中。 所以代码是线程安全的。

如果创build了两个单例的话,NSSAssert可能会使应用程序“崩溃”。 这是“即将确定”的代码,也被称为防御性编程。

关于sharedMySingletonalloc的链,我认为这很好。

在sharedMySingleton方法中,不需要调用retain?

alloc返回一个引用计数为1的新实例,所以不需要保留。

如果没有,为什么在allocWithZone中有保留?

根据规则,当你调用allocWithZone ,你拥有这个引用,所以allocWithZone大大增加了你的引用计数。 但是这个allocWithZone的实现是返回已经创build并由其他人拥有的单例实例( sharedMySingleton方法)。 所以sharedMySingleton方法创build带有alloc的对象,因此它成为一个所有者。 然后你通过allocWithZone得到同样的实例,所以你成为同一个实例的第二个所有者。 所以保留数量必须增加,因为现在有两个所有者。 这就是为什么allocWithZone需要保留。

什么是@synchronized的使用?

@synchronized允许代码被多个线程同时调用。 如果你永远不会从多个线程调用sharedMySingleton ,那么这是没有必要的,你可以省略它。

NSAssert认为块可以被调用多次,所以如果是的话,应该有更多的代码释放以前的内存,或者没有NSAsserting清除退出块,如果没有,为什么有这个NSAssert?

因为这个类是一个singleton,所以alloc只能被调用一次。 如果alloc被多次调用, NSAssert()终止程序。 由于NSAssert()终止程序,当第二次调用alloc时,不需要内存pipe理。