在iOS中有很多单例对象,比如UIApplication
,UIScreen
等等,那我们自己可以实现单例吗?答案是肯定的,请往下看
ARC中的单例实现
//.h文件
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
//单例方法
+(instancetype)sharedSingleton;
@end
//.m文件
#import "Singleton.h"
@implementation Singleton
//全局变量
static id _instance = nil;
//单例方法
+(instancetype)sharedSingleton{
return [[self alloc] init];
}
////alloc会调用allocWithZone:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//初始化方法
- (instancetype)init{
// 只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super init];
});
return _instance;
}
//copy在底层 会调用copyWithZone:
- (id)copyWithZone:(NSZone *)zone{
return _instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone{
return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
@end
- 测试代码及运行结果
#import <Foundation/Foundation.h>
#import "Singleton.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Singleton *s1 = [[Singleton alloc]init];
Singleton *s2 = [Singleton sharedSingleton];
Singleton *s3 = [[Singleton alloc]init];
Singleton *s4 = [Singleton sharedSingleton];
Singleton *s5 = [s4 copy];
NSLog(@"%p %p %p %p %p",s1,s2,s3,s4, s5);
}
return 0;
}
运行结果
2015-08-29 21:07:01.869 Singleton-ARC[42202:784939] 0x100114760 0x100114760 0x100114760 0x100114760 0x100114760
非ARC中的单例实现
- 因为在非ARC中,需要我们自己管理内存,所以实现稍微负责一点
//.m文件
#import <Foundation/Foundation.h>
//单例方法
@interface Singleton : NSObject
+ (instancetype)sharedSingleton;
@end
//.m文件
#import "Singleton.h"
@implementation Singleton
//全局变量
static id _instance = nil;
//单例方法
+(instancetype)sharedSingleton{
//系统的大多数类方法都有做autorelease,所以我们也需要做一下
return [[[self alloc] init] autorelease];
}
//alloc会调用allocWithZone:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//初始化方法
-(instancetype)init{
// 只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super init];
});
return _instance;
}
- (oneway void)release{
//什么都不做 保证单例对象不被销毁
}
//返回本身 保证只有一个单例对象
- (instancetype)retain{
return _instance;
}
//计数器为1 保证只有一个单例对象
- (NSUInteger)retainCount{
return 1;
}
//copy在底层 会调用copyWithZone:
+ (id)copyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)copyWithZone:(NSZone *)zone{
return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
@end
- 因为要保证单例对象在程序运行期间一直存在,所以不需要实现release方法和dealloc方法
- 测试代码及运行结果
#import <Foundation/Foundation.h>
#import "Singleton.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Singleton *s1 = [[Singleton alloc]init];
Singleton *s2 = [Singleton sharedSingleton];
Singleton *s3 = [[Singleton alloc]init];
Singleton *s4 = [Singleton sharedSingleton];
Singleton *s5 = [s4 copy];
NSLog(@"%p %p %p %p %p",s1,s2,s3,s4, s5);
[s1 release];
[s3 release];
[s5 release];
}
return 0;
}
运行结果
2015-08-29 21:01:43.770 Singleton-非ARC[42192:782473] 0x100206880 0x100206880 0x100206880 0x100206880 0x100206880
- 也可以把上面的代码抽出一个宏,以ARC为例
//.h文件 ##表示拼接字符
#define SingletonH(methodName) +(instancetype)shared##methodName;
//.m文件
#define SingletonM(methodName)\
\
static id _instance = nil;\
+(instancetype)sharedSingleton{\
return [[self alloc] init];\
}\
+(instancetype)allocWithZone:(struct _NSZone *)zone{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
- (instancetype)init{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super init];\
});\
return _instance;\
}\
- (id)copyWithZone:(NSZone *)zone{\
return _instance;\
}\
+ (id)copyWithZone:(struct _NSZone *)zone{\
return _instance;\
}
- 以上代码如果有上面不对的地方,敬请纠正,谢谢!
网友评论
This method exists for historical reasons; memory zones are no longer used by Objective-C.
—— 苹果官方文档
static id _instance = nil;\
+(instancetype)sharedSingleton{\
return [[self alloc] init];\
}\
应该改为 shared##methodName
+ (id)copyWithZone:(struct _NSZone *)zone这个类方法,也需要重写?