Table of Content
单例模式及其实现
-
步骤
-
提供全局访问方法,公认的格式 shared+类型
-
有一个静态全局变量,保证对象的实例保存在静态区,并且不需要关心释放 的问题
-
重写
allocWithZone
方法,能够保证对象只被实例化一次!- 需要包含
dispatch_once
:保证对象只被分配一次内存空间
- 需要包含
-
实现shared方法
- 需要包含
dispatch_once
:保证对象只被初始化一次
- 需要包含
-
eg.h
#import <Foundation/Foundation.h>
@interface SoundTools : NSObject <NSCopying>
// 全局的访问方法
+ (instancetype)sharedSoundTools;
@end
eg.m
@interface SoundTools()
@property (nonatomic, assign) int count;
@end
@implementation SoundTools
static id instance;
// 所有对象的内存分配,最终都会调用到此方法
// 把这个方法搞定,就能实现单例!
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
// 问题:这种方式不是线程安全的
// 解决方法1:增加互斥锁
// @synchronized (self) {
// if (instance == nil) {
// instance = [super allocWithZone:zone];
// }
// }
// 其他解决办法?dispatch_once,执行一次,线程安全!
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (instance == nil) {
instance = [super allocWithZone:zone];
}
});
return instance;
}
+ (instancetype)sharedSoundTools {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 使用shared方法只能做一次初始化!
instance = [[self alloc] init];
});
⏎ instance;
}
//------------- 以上部分是面试的时候,需要手写单例的代码------
- (id)copyWithZone:(NSZone *)zone {
⏎ instance;
}
- (instancetype)init
{
self = [super init];
if (self) {
_count = 10;
NSLog(@"初始化 %d", _count);
}
⏎ self;
}
@end
MRC中的单例的实现
- 先参考ARC中单例的实现部分
eg.m
#pragma mark - MRC模式中需要增加的代码
- (oneway void)release {
// 原本的程序是做计数-1
}
- (instancetype)retain {
return instance;
}
- (instancetype)autorelease {
return instance;
}
- (NSUInteger)retainCount {
// retainCount返回最大整数,此方法可以不重写
// 出处 limits.h ULONG_MAX 宏可以自行根据运行的CPU架构调整整数的长度
return ULONG_MAX;
}
抽取单例宏
Singleton.h
#define singletonInterface(className) +(instancetype)shared##className;
#if __has_feature(objc_arc)
// 以下是ARC版本
#define singletonImplementation(className) \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
if (instance == nil) { \
instance = [super allocWithZone:zone]; \
} \
}); \
return instance; \
} \
+ (instancetype)shared##className { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
instance = [[self alloc] init]; \
}); \
return instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
return instance; \
}
#else
// 以下是MRC版本
#define singletonImplementation(className) \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
if (instance == nil) { \
instance = [super allocWithZone:zone]; \
} \
}); \
⏎ instance; \
} \
+ (instancetype)shared##className { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
instance = [[self alloc] init]; \
}); \
⏎ instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
⏎ instance; \
} \
- (oneway void)release {} \
- (instancetype)retain {⏎ instance;} \
- (instancetype)autorelease {⏎ instance;} \
- (NSUInteger)retainCount {⏎ ULONG_MAX;}
#endif
// 提示末尾一行不要有 \
eg.h
#import <Foundation/Foundation.h>
#import "Singleton.h"
@interface SoundTools : NSObject <NSCopying>
// 全局的访问方法
//+ (instancetype)sharedSoundTools;
singletonInterface(SoundTools);
@end
eg.m
#import "SoundTools.h"
@interface SoundTools()
/** 声音的数量 */
@property (nonatomic, assign) int count;
@end
@implementation SoundTools
static id instance;
singletonImplementation(SoundTools);
#pragma mark - MRC 部分代码
- (instancetype)init
{
self = [super init];
if (self) {
_count = 10;
NSLog(@"初始化 %d", _count);
}
return self;
}
@end