单例

 1. 定义一个静态的实例成员=>保证对象在内存中只有一个副本,而且是保存在静态区的
 
 static id instance;
 
 2. 提供一个全局的访问方法,都以 shared + 类名 格式定义
 
 + (instancetype)sharedSoundTools;
 
 3. 重写 allocWithZone 方法,=> 保证对象只被实例化一次,只分配一次内存空间
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
    instance = [super allocWithZone:zone];
 });
 return instance;
 
 4. 实现 shared 方法 => 保证对象只被 init(初始化) 一次
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
    instance = [[self alloc] init];
 });
 return instance;
 
 面试中,只需要写以上四个步骤就行!关于 gcd 部分,只需要写 dispatch_once 就可以

static id instance;

// alloc方法会调用 allocWithZone 方法
// 既然所有的内存分配最终都是 allocWithZone 来实现的
// 如果能够保证只实例化一个对象的副本
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    
    // 问题:如果是多线程运行!
    // 目标:要保证 super allocWithZone 方法只执行一次!
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}

+ (instancetype)sharedSoundTools {
    // 问题:如果直接返回 instance 会怎样?
    // 如果第一次就调用类方法,因为没有实例化,会直接返回 nil
    
//    return instance;
    // 要保证单例对象只被 init(初始化) 一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

// 对象方法,说明拷贝的源已经存在 => instance 就一定已经被实例化过!
- (id)copyWithZone:(NSZone *)zone {
//    id s = [[self.class allocWithZone:zone] init];
//    
//    return s;
    return instance;
}

原文地址:https://www.cnblogs.com/it-k-50/p/6093841.html