一. singleton(单粒)
作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点
下面用Tools类举例单粒类的创建
----------Tools.h文件
#import <Foundation/Foundation.h>
@interface Tools : NSObject<NSCopying, NSMutableCopying>
// 一般情况下创建一个单粒对象都有一个与之对应的类方法
// 一般情况下用于创建单粒对象的方法名称都以share开头, 或者以default开头,后加上类名用,驼峰命名法。
+ (instancetype)shareTools;
@end
----------Tools.m文件
#import "Tools.h"
@implementation Tools
+ (instancetype)shareTools
{
Tools *instance = [[self alloc] init];
return instance;
}
/*
此处还要重写一些方法!
*/
@end
二. 重写+ (instancetype)allocWithZone:(struct _NSZone *)zone
重写目的:保证类只有一个对象
1. 单线程下
在单线程下,用下面的代码重写,是没有问题的,但是在多线程下,会生成多个对象。
//用于存储唯一生成的Tools对象
static Tools *_instance = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
//1.单线程模式下
if (_instance == nil) {
_instance = [[super allocWithZone:zone] init];
}
return _instance;
}
2. 多线程下
在多线程下,用下面的代码重写,可以保证任何时候都只有一个对象,当然在单线程下也可以用以下代码。
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
//2.多线程模式下
//2.1 dispatch_once_t实质是long的宏定义,定义的变量用于检查该代码块是否已经被调度,用于dispatch_once()函数
static dispatch_once_t onceToken;
//2.2 声明一个Block变量,用于存储创建对象的代码块
void (^block)() = ^{
_instance = [[super allocWithZone:zone] init];
};
//2.3dispatch_once()函数接收一个检查代码块是否已执行的变量和一个希望在应用的生命周期内仅被调度一次的代码块;
//dispatch_once不仅意味着代码仅会被运行一次,而且还是线程安全的,如果被多个线程调用,该函数会同步等待直至代码块完成。
dispatch_once(&onceToken,block);
return _instance;
}
----------下面为优化后的重写代码
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
_instance = [[super allocWithZone:zone] init];
});
return _instance;
}
三. 重写copyWithZone:方法和mutableCopyWithZone:方法
重写目的:保证复制时不生成新对象
//_instance是该类的单粒变量
- (id)copyWithZone:(NSZone *)zone {
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
四. ARC模式下和MRC模式下
在ARC模式下只要重写以下3个方法
(1). + (instancetype)allocWithZone:(struct _NSZone *)zone
(2). - (id)copyWithZone:(NSZone *)zone
(3). - (id)mutableCopyWithZone:(NSZone *)zone在MRC模式下,要重写ARC要重写的方法外,还要重写以下3个方法
(1). - (oneway void)release
(2). - (instancetype)retain
(3). - (NSUInteger)retainCount在MRC模式下,还要重写的代码如下
- (oneway void)release
{
//为保证整个程序过程中只有一份实例,在这个方法中什么都不做
}
- (instancetype)retain
{
//为保证整个程序过程中只有一份实例,直接返回静态实例变量
return _instance;
}
- (NSUInteger)retainCount
{
//可以用return 1;,但是为了方便程序员之前沟通, 一般情况下不会在单粒中返回retainCount = 1
//而是返回一个比较大得值,说明此对象一直存在,是个单粒
return MAXFLOAT;
}
五. 单粒模式的抽取
1. 判断当前系统是ARC或者MRC
#if __has_feature(objc_arc)
NSLog(@"ARC");
#else
NSLog(@"MRC");
#endif
2. ## 和 \
(1).在宏定义或者在注释中: 斜杠\ 代表换行;
(2).在宏定义中:双井号## 代表连接。
3.自定义单粒
在单粒模式中除了类名不一样,其他的代码基本一样,可以用宏定义抽取,当以后写单粒类,可以直接#import单粒文件即可调用宏来创建单粒类。
代码如下:
----------Singleton.h文件,代码抽取所放的文件
//声明部分的抽取
#define interfaceSingleton(name) +(instancetype)share##name;
//实现部分的抽取
#if __has_feature(objc_arc)
//ARC下执行以下代码
#define implementationSingleton(name) \
+ (instancetype)share##name { \
name *instance = [[name alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken,^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone { \
return _instance; \
}
#else
//MRC下执行以下代码
#define implementationSingleton(name) \
+ (instancetype)share##name { \
name *instance = [[name alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken,^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone { \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone { \
return _instance; \
} \
- (oneway void)release { \
} \
- (instancetype)retain { \
return _instance; \
} \
- (NSUInteger)retainCount { \
return MAXFLOAT; \
}
#endif
----------Tools.h文件
#import <Foundation/Foundation.h>
#import "Singleton.h"
@interface Tools : NSObject <NSCopying,NSMutableCopying>
//调用宏定义
interfaceSingleton(Tools)
@end
----------Tools.m文件
#import "Tools.h"
#import "Singleton.h"
@implementation Tools
//调用宏定义
implementationSingleton(Tools)
@end
----------main.m文件,用于测试所写的单例类
#import <Foundation/Foundation.h>
#import "Tools.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Tools *tools = [Tools new];
Tools *tools1 = [[Tools alloc] init];
Tools *tools2 = [Tools shareTools];
Tools *tools3 = [tools copy];
Tools *tools4 = [tools mutableCopy];
NSLog(@"%p %p %p %p %p",tools,tools1,tools2,tools3,tools4);
NSLog(@"%lu",[tools retainCount]);
#if __has_feature(objc_arc)
NSLog(@"ARC");
#else
NSLog(@"MRC");
#endif
}
return 0;
}