美好的一天,朋友们。
再一次关于来自新手的Obj-C的愚蠢问题:)
我正在尝试在Obj-C中实现单例设计模式:
@interface SampleSingleton : NSObject {
@private
static SampleSingleton* instance;
}
+(SampleSingleton*) getInstance;
编译器返回错误:“在'静态'之前预期的说明符 - 限定符 - 列表”。
答案 0 :(得分:8)
您不能在类接口声明中使用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 :(得分:8)
请在下面找到我正在使用的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)命名任何静态类。
任何专门用于控制特定进程的类都使用Controller后缀(例如MyParticularTaskConstroller)命名。
从其他控件继承的任何UI控件都需要提供控件后缀(例如,继承自UITableViewCell的MyCustomDetailCell)
希望这有帮助。
答案 2 :(得分:1)
请查看我的问题here以及Nick DeMoore的精彩答案(包含大量注释和代码修复)。拥有一个可以在IB中连接的单例(好吧,无论你在XCode 4中调用它)都非常有用。
很酷的是你可以使用相同的Singleton并在一个NIB中连接它的一些插座,而在另一个NIB中连接它的一些插座......因为它实际上是一个单独的,所以在整个运行时只能有一个实例系统。效果非常好。
注意:每次使用Singleton时,人们会说这是一个坏主意。
答案 3 :(得分:0)
静态SampleSingleton* instance;
行无法进入@interface
部分。大多数人都把它放在上面。
Objective-c并不适用于单例模式以及其他一些语言。但是,在this question中可以看到许多不同的实现。
有些人认为Singleton根本不是一个很好的模式,我试图让自己不再使用它 - 但这是我的选择。
答案 4 :(得分:0)
这就是我通常实现单例方法的方法
+(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有一个执行创建单身人士功能的共享应用程序,但没有什么可以阻止你创建一个新实例。