// Tools.h
#import <Foundation/Foundation.h>
@interface Tools : NSObject<NSCopying, NSMutableCopying>
// 一般情况下创建一个单例对象都有一个与之对应的类方法,一般情况下用于创建单例对象的方法名称都以share开头, 或者以default开头
+ (instancetype)shareInstance;
@end
//
// Tools.m
#import "Tools.h"
@implementation Tools
+ (instancetype)shareInstance
{
Tools *instance = [[self alloc] init];//调用allocWithZone
return instance;
}
static Tools *_instance = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone //alloc内部会调用allocWithZone
{
// 由于所有的创建方法都会调用该方法, 所以只需要在该方法中控制当前对象只创建一次即可
/*
// 当前代码在多线程中可能会出现问题
NSLog(@"%s", __func__);
if (_instance == nil) {
NSLog(@"创建了一个对象");
_instance = [[super allocWithZone:zone] init]; //去父类创建,不能用self否则会死循环,
}
return _instance;
*/
// 以下代码在多线程中也能保证只执行一次
static dispatch_once_t onceToken;//long类型
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:zone] init];
});
return _instance;
}
// copyWithZone方法用什么调用? 对象,对象已经有了,就用原来的对象。
- (id)copyWithZone:(NSZone *)zone{
// Tools *t = [[[self class] allocWithZone:zone] init]; //调用allocWithZone,所以这里也是单利,
// return t;
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
// Tools *t = [[[self class] allocWithZone:zone] init];
// return t;
return _instance;
}
//MRC:MRC才可以写release,retain,retainCount
- (oneway void)release
{
// 为保证整个程序过程中只有一份实例, 在这个方法中什么都不做,单利释放了就没有了。
}
- (instancetype)retain
{
return _instance;
}
- (NSUInteger)retainCount
{
// return 1;
// 注意: 为了方便程序员之前沟通, 一般情况下不会在单例中返回retainCount = 1
// 而是返回一个比较大得值
return MAXFLOAT;
}
@end
//
// main.m
// 单例:只有一个实例,只有程序挂掉实例才释放。
//
#import <Foundation/Foundation.h>
#import "Tools.h"
int main(int argc, const char * argv[]) {
//ARC
// 单例就是无论怎么创建都只能有一个实例对象
// 如果地址相同就代表着是同一个实例对象
Tools *t11 = [[Tools alloc] init]; //alloc内部会调用allocWithZone,这里调用allocWithZone,
Tools *t21 = [Tools new];// [[alloc] init], allocWithZone,,这里调用allocWithZone,
Tools *t31 = [Tools shareInstance];//先调用shareInstance再调用allocWithZone,
Tools *t41 = [t31 copy];
Tools *t51 = [t31 mutableCopy];
NSLog(@"%p, %p, %p, %p, %p", t11, t21, t31, t41, t51);//0x1005035e0, 0x1005035e0, 0x1005035e0, 0x1005035e0, 0x1005035e0
//MRC
Tools *t2 = [[Tools alloc] init];
[t2 retain];
[t2 retain];
[t2 retain];
[t2 retain];
[t2 retain];
NSLog(@"retainCount = %lu", [t2 retainCount]);//4299163232
NSLog(@"t2 = %p", t2);//t2 = 0x1005035e0
[t2 release];
Tools *t1 = [Tools shareInstance];
NSLog(@"retainCount = %lu", [t1 retainCount]);//4299163232
NSLog(@"t1 = %p", t1);//0x1005035e0
[t1 release];
return 0;
}