Objective-Cのシングルモデル(singleton)
11532 ワード
(自動回転:http://blog.csdn.net/arthurchenjs/article/details/6699598)
クラスを書くつもりなら、この特定のインスタンスがサービスを提供するための入口を得ることができると同時に、1つのインスタンスだけが存在することを保証したいなら、シングルデザインモードを使用することができる.
シングルモードはJava、C++でよく使われています.Cocoaでも実現できます.
しかし、
Objective-Cのシングルモデルはあなたが想像しているのとは違って、彼の書き方はあなたが見た言語の書き方とは違います.
政府側の提案
自分でシングルモードを設計するのは一定のリスクがあるので、主にマルチスレッドの場合に発生する可能性がある問題を考慮して、アップルの公式提案は以下の方式を使ってシングルモードを実現することを提案しています.
static MyGizmoClass*sharedGizmonager=nil; + (MyGizmoClass*)sharedManager { @synchronized(self){ if(sharedGizmonager=nil){ [[self alloc]init]//assignment not done here } } return sharedGizmonager; } + (id)allocWithZone:(NSZone*)zone { @synchronized(self){ if(sharedGizmonager=nil){ sharedGizmonager=[super allocWithZone:zone] return sharedGizmonager; //assignment and return on first allocation } } return nil;//on subsequent allocation atempts returnnil } - (id)copyWithZone:(NSZone*)zone { return self } - (id)retain { return self } - (unsigned)retainCount { return UNTUMAX; //denotes an object that cannot be released } - (void)release { //ドノースリング } - (id)autrelease { return self }
オープンソーステンプレート(ダウンロードアドレス付き)
プログラマーは怠け者です.今はマクロ定義を使っていろいろなことを解決するのが流行っています.
一例には以下のインターフェースが含まれています. + (MyClass*)sharedInstance; + (void)purgeShardInstance;
sharedInstanceを呼び出して作成し、単例に戻ります.
purgeSharedInstanceを呼び出して、シングルを破棄します.
手動でallocを呼び出しても、単例であることを保証できます.このように呼び出してもいいです.
[MyClass alloc]init WithParam:first Param secondParam:secondParam]
ただ、株式市場の前に呼び出されることを保証します.一回だけチャンスを作るからです.
マクロを使った書き方は以下の通りです. MyClass.h: ======================================== #import「Synethesize Singleton.h」 @インターフェースMyClass:SomeSuperclass { ... } SYNTHESIZE(USINGLETON); @end ======================================== MyClass.m: ======================================== #import「MyClass.h」 @implemention MyClass SYNTHESIZE(USINGLETON); ... @end ========================================
ダウンロード
http://arthurchen.blog.51cto.com/attachment/201108/2483760_133658868.rar
以上の転載は完了しました.
----------------分割線------------------------
以下は本人が補充したものです.
上記のダウンロードアドレスからダウンロードしたオープンソーステンプレートの内容は以下の通りです.
ファイル名:Synethesize Singleton.h
----------------分割線------------------------
クラスを書くつもりなら、この特定のインスタンスがサービスを提供するための入口を得ることができると同時に、1つのインスタンスだけが存在することを保証したいなら、シングルデザインモードを使用することができる.
シングルモードはJava、C++でよく使われています.Cocoaでも実現できます.
しかし、
Objective-Cのシングルモデルはあなたが想像しているのとは違って、彼の書き方はあなたが見た言語の書き方とは違います.
政府側の提案
自分でシングルモードを設計するのは一定のリスクがあるので、主にマルチスレッドの場合に発生する可能性がある問題を考慮して、アップルの公式提案は以下の方式を使ってシングルモードを実現することを提案しています.
static MyGizmoClass*sharedGizmonager=nil; + (MyGizmoClass*)sharedManager { @synchronized(self){ if(sharedGizmonager=nil){ [[self alloc]init]//assignment not done here } } return sharedGizmonager; } + (id)allocWithZone:(NSZone*)zone { @synchronized(self){ if(sharedGizmonager=nil){ sharedGizmonager=[super allocWithZone:zone] return sharedGizmonager; //assignment and return on first allocation } } return nil;//on subsequent allocation atempts returnnil } - (id)copyWithZone:(NSZone*)zone { return self } - (id)retain { return self } - (unsigned)retainCount { return UNTUMAX; //denotes an object that cannot be released } - (void)release { //ドノースリング } - (id)autrelease { return self }
オープンソーステンプレート(ダウンロードアドレス付き)
プログラマーは怠け者です.今はマクロ定義を使っていろいろなことを解決するのが流行っています.
一例には以下のインターフェースが含まれています. + (MyClass*)sharedInstance; + (void)purgeShardInstance;
sharedInstanceを呼び出して作成し、単例に戻ります.
purgeSharedInstanceを呼び出して、シングルを破棄します.
手動でallocを呼び出しても、単例であることを保証できます.このように呼び出してもいいです.
[MyClass alloc]init WithParam:first Param secondParam:secondParam]
ただ、株式市場の前に呼び出されることを保証します.一回だけチャンスを作るからです.
マクロを使った書き方は以下の通りです. MyClass.h: ======================================== #import「Synethesize Singleton.h」 @インターフェースMyClass:SomeSuperclass { ... } SYNTHESIZE(USINGLETON); @end ======================================== MyClass.m: ======================================== #import「MyClass.h」 @implemention MyClass SYNTHESIZE(USINGLETON); ... @end ========================================
ダウンロード
http://arthurchen.blog.51cto.com/attachment/201108/2483760_133658868.rar
以上の転載は完了しました.
----------------分割線------------------------
以下は本人が補充したものです.
上記のダウンロードアドレスからダウンロードしたオープンソーステンプレートの内容は以下の通りです.
ファイル名:Synethesize Singleton.h
----------------分割線------------------------
#ifndef SYNTHESIZE_SINGLETON_FOR_CLASS
#import <objc/runtime.h>
#pragma mark -
#pragma mark Singleton
/* Synthesize Singleton For Class
*
* Creates a singleton interface for the specified class with the following methods:
*
* + (MyClass*) sharedInstance;
* + (void) purgeSharedInstance;
*
* Calling sharedInstance will instantiate the class and swizzle some methods to ensure
* that only a single instance ever exists.
* Calling purgeSharedInstance will destroy the shared instance and return the swizzled
* methods to their former selves.
*
*
* Usage:
*
* MyClass.h:
* ========================================
* #import "SynthesizeSingleton.h"
*
* @interface MyClass: SomeSuperclass
* {
* ...
* }
* SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(MyClass);
*
* @end
* ========================================
*
*
* MyClass.m:
* ========================================
* #import "MyClass.h"
*
* @implementation MyClass
*
* SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass);
*
* ...
*
* @end
* ========================================
*
*
* Note: Calling alloc manually will also initialize the singleton, so you
* can call a more complex init routine to initialize the singleton like so:
*
* [[MyClass alloc] initWithParam:firstParam secondParam:secondParam];
*
* Just be sure to make such a call BEFORE you call "sharedInstance" in
* your program.
*/
#define SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(__CLASSNAME__) \
\
+ (__CLASSNAME__*) sharedInstance; \
+ (void) purgeSharedInstance;
#define SYNTHESIZE_SINGLETON_FOR_CLASS(__CLASSNAME__) \
\
static __CLASSNAME__* volatile _##__CLASSNAME__##_sharedInstance = nil; \
\
+ (__CLASSNAME__*) sharedInstanceNoSynch \
{ \
return (__CLASSNAME__*) _##__CLASSNAME__##_sharedInstance; \
} \
\
+ (__CLASSNAME__*) sharedInstanceSynch \
{ \
@synchronized(self) \
{ \
if(nil == _##__CLASSNAME__##_sharedInstance) \
{ \
_##__CLASSNAME__##_sharedInstance = [[self alloc] init]; \
} \
else \
{ \
NSAssert2(1==0, @"SynthesizeSingleton: %@ ERROR: +(%@ *)sharedInstance method did not get swizzled.", self, self); \
} \
} \
return (__CLASSNAME__*) _##__CLASSNAME__##_sharedInstance; \
} \
\
+ (__CLASSNAME__*) sharedInstance \
{ \
return [self sharedInstanceSynch]; \
} \
\
+ (id)allocWithZone:(NSZone*) zone \
{ \
@synchronized(self) \
{ \
if (nil == _##__CLASSNAME__##_sharedInstance) \
{ \
_##__CLASSNAME__##_sharedInstance = [super allocWithZone:zone]; \
if(nil != _##__CLASSNAME__##_sharedInstance) \
{ \
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceNoSynch)); \
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
method_setImplementation(class_getInstanceMethod(self, @selector(retainCount)), class_getMethodImplementation(self, @selector(retainCountDoNothing))); \
method_setImplementation(class_getInstanceMethod(self, @selector(release)), class_getMethodImplementation(self, @selector(releaseDoNothing))); \
method_setImplementation(class_getInstanceMethod(self, @selector(autorelease)), class_getMethodImplementation(self, @selector(autoreleaseDoNothing))); \
} \
} \
} \
return _##__CLASSNAME__##_sharedInstance; \
} \
\
+ (void)purgeSharedInstance \
{ \
@synchronized(self) \
{ \
if(nil != _##__CLASSNAME__##_sharedInstance) \
{ \
Method newSharedInstanceMethod = class_getClassMethod(self, @selector(sharedInstanceSynch)); \
method_setImplementation(class_getClassMethod(self, @selector(sharedInstance)), method_getImplementation(newSharedInstanceMethod)); \
method_setImplementation(class_getInstanceMethod(self, @selector(retainCount)), class_getMethodImplementation(self, @selector(retainCountDoSomething))); \
method_setImplementation(class_getInstanceMethod(self, @selector(release)), class_getMethodImplementation(self, @selector(releaseDoSomething))); \
method_setImplementation(class_getInstanceMethod(self, @selector(autorelease)), class_getMethodImplementation(self, @selector(autoreleaseDoSomething))); \
[_##__CLASSNAME__##_sharedInstance release]; \
_##__CLASSNAME__##_sharedInstance = nil; \
} \
} \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
\
- (id)retain \
{ \
return self; \
} \
\
- (NSUInteger)retainCount \
{ \
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(NSUInteger)retainCount method did not get swizzled.", self); \
return NSUIntegerMax; \
} \
\
- (NSUInteger)retainCountDoNothing \
{ \
return NSUIntegerMax; \
} \
- (NSUInteger)retainCountDoSomething \
{ \
return [super retainCount]; \
} \
\
- (oneway void)release \
{ \
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(void)release method did not get swizzled.", self); \
} \
\
- (void)releaseDoNothing{} \
\
- (void)releaseDoSomething \
{ \
@synchronized(self) \
{ \
[super release]; \
} \
} \
\
- (id)autorelease \
{ \
NSAssert1(1==0, @"SynthesizeSingleton: %@ ERROR: -(id)autorelease method did not get swizzled.", self); \
return self; \
} \
\
- (id)autoreleaseDoNothing \
{ \
return self; \
} \
\
- (id)autoreleaseDoSomething \
{ \
return [super autorelease]; \
}
#endif