您的位置:首页 > 移动开发 > IOS开发

浅析iOS中单例模式的写法(懒汉式&饿汉式&ARC&非ARC&宏)

2017-01-22 23:16 513 查看

懒汉式:

第一次用单例对象时,进行创建,推荐使用

ManagerTool.h
+(instancetype)sharedManagerTool;

ManagerTool.m
//用来保存唯一的单例对象,不写`static`,其他类可通过extern 访问修改
static id _instace;
+ (id)allocWithZone:(struct _NSZone *)zone // alloc调用此方法
{
//防止多线程的写法
//    if (_instace == nil) {
//        @synchronized (self) {
//            if (_instace == nil) {
//                _instace = [[self alloc] init];
//            }
//        }
//    }
//GCD的写法
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instace = [super allocWithZone:zone];
});
return _instace;
}
+ (instancetype)sharedManagerTool  //实现.h中sharedManagerTool
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instace = [[self alloc] init];
});
return _instace;
}
- (id)copyWithZone:(NSZone *)zone  //copy会调用次方法
{
return _instace;
}


饿汉式:

一进入程序就创建该对象,不推荐使用

ManagerTool.h
+(instancetype)sharedManagerTool;

ManagerTool.m
+ (void)load //装载内存时就实例化,仅此一次
{
_instance = [[self alloc] init];
}
+ (id)allocWithZone:(struct _NSZone *)zone
{
if (_instance == nil) { // 防止创建多次
_instance = [super allocWithZone:zone];
}
return _instance;
}
+ (instancetype)sharedManagerTool
{
return _instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}


上面两种写法均是在ARC环境下,在非ARC环境中需在.m中加入以下代码:

//禁止进行retain和release操作,一旦创建一直存在,引用计数不变
- (oneway void)release {
}
- (id)retain {
return self;
}
- (NSUInteger)retainCount {
return 1;
}
- (id)autorelease {
return self;
}


宏的写法(已判断当前环境,可直接用)

#if __has_feature(objc_arc)

#define SINGLETON_FOR_CLASS_HEADER(classname) \
\
+ (classname *)shared##classname;

#define SINGLETON_FOR_CLASS(classname) \
\
static classname *shared##classname = nil; \
\
+ (classname *)shared##classname \
{ \
static dispatch_once_t pred; \
dispatch_once(&pred, ^{ shared##classname = [[classname alloc] init]; }); \
return shared##classname; \
} \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
shared##classname = [super allocWithZone:zone]; \
}); \
return shared##classname; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \

#else

#define SINGLETON_FOR_CLASS_HEADER(classname) \
\
+ (classname *)shared##classname;

#define SINGLETON_FOR_CLASS(classname) \
\
static classname *shared##classname = nil; \
\
+ (classname *)shared##classname \
{ \
static dispatch_once_t pred; \
dispatch_once(&pred, ^{ shared##classname = [[classname alloc] init]; }); \
return shared##classname; \
} \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
shared##classname = [super allocWithZone:zone]; \
}); \
return shared##classname; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
\
- (id)retain \
{ \
return self; \
} \
\
- (NSUInteger)retainCount \
{ \
return NSUIntegerMax; \
} \
\
- (oneway void)release \
{ \
} \
\
- (id)autorelease \
{ \
return self; \
}

#endif

//调用:
ManagerTool.h
SINGLETON_FOR_CLASS_HEADER(ManagerTool)

ManagerTool.m
SINGLETON_FOR_CLASS(ManagerTool)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息