實現
先貼出程式碼
也可以直接訪問我的github:RWSingleton
#import <objc/runtime.h>
#define RW_DECLARE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, accessorMethodName)
+ (classname *)accessorMethodName;
#if __has_feature(objc_arc)
#define RW_SYNTHESIZE_SINGLETON_RETAIN_METHODS
#else
#define RW_SYNTHESIZE_SINGLETON_RETAIN_METHODS
- (id)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax;
}
- (oneway void)release
{
}
- (id)autorelease
{
return self;
}
#endif
#define RW_SYNTHESIZE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, accessorMethodName)
static classname *accessorMethodName##Instance = nil;
+ (classname *)accessorMethodName
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
accessorMethodName##Instance = [super allocWithZone:NULL];
accessorMethodName##Instance = [accessorMethodName##Instance init];
method_exchangeImplementations(
class_getInstanceMethod([accessorMethodName##Instance class], @selector(init)),
class_getInstanceMethod([accessorMethodName##Instance class], @selector(init_once)));
});
return accessorMethodName##Instance;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self accessorMethodName];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)init_once
{
return self;
}
RW_SYNTHESIZE_SINGLETON_RETAIN_METHODS
#define RW_DECLARE_SINGLETON_FOR_CLASS(classname) RW_DECLARE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, shared##classname)
#define RW_SYNTHESIZE_SINGLETON_FOR_CLASS(classname) RW_SYNTHESIZE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, shared##classname)
使用
例如你需要一個名為MyOjbect
的單例. 在MyOjbect.h
中,程式碼如下:
#import "RWSingletonMacro.h"
@interface MyObject : NSObject
RW_DECLARE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(MyObject, sharedObject)
@end
在MyObject.m
中:
#import "MyObject.h"
@implementation MyObject
RW_SYNTHESIZE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(MyObject, sharedObject)
@end
注意
很多時候,單例都會擁有自己的instance varible
,所以這裡做了method siwwizling
, 你可以過載-(id)init
,在其中實現你的初始化邏輯.MyObject.m
看起來如下:
#import "MyObject.h"
@implementation MyObject
RW_SYNTHESIZE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(MyObject, sharedObject)
- (id) init
{
self = [super init];
//do your things
return self
}
@end
此外,從實現中可得知,即便是如下程式碼也可以保證obj
是單例。
MyObject* obj = [[MyObject alloc] init];
原作寫於segmentfault 連結