zoukankan      html  css  js  c++  java
  • iOS单例模式(面试必考)

    ​# 单例模式(面试必考)

    1. 单例模式的作用

    • 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
    • 从而方便地控制了实例个数,并节约系统资源

    2. 单例模式的使用场合

    • 在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)

    3. ARC中,单例模式的实现

    • 1.在.m中保留一个全局的static的实例
    static id _instance;
    
    • 2.重写allocWithZone:方法,在这里创建唯一的实例(注意线程安全)
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
        return _instance;
    }
    
    • 3.提供1个类方法让外界访问唯一的实例
    + (instancetype)sharedInstance
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
        });
        return _instance;
    }
    
    • 4.实现copyWithZone:方法
    - (id)copyWithZone:(struct _NSZone *)zone
    {
        return _instance;
    }
    

    4.ARC中完整版(GCD)

    static id _instance;
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[super allocWithZone:zone] init]; // 记住这儿是super,不能用self
        });
    
        return _instance;
    }
    
    + (instancetype)sharedPerson
    {
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
        });
        return _instance;
    }
    
    // copyWithZone方法的前提是必须先有一个对象
    - (id)copyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    
    
    • 在实际开发中,一个应用程序可能有多个对象是单例对象,此时我们应该把单例抽成一个宏放在一个单独的.h文件中,千万不能用继承
      • 其中表示此行跟下面一行是一起的
      • ## 表示后面是参数
      • 此时,注释只能在上面,在右边注释会报错的
    // .h文件中的声明
    #define SLInstanceH(name)  + (instancetype)shared##name;
    // .m文件的实现
    #define SLInstanceM(name) static id _instance; 
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[super allocWithZone:zone] init];
        });
        return _instance;
    }
    
    + (instancetype)shared##name
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [[self alloc] init];
        });
        return _instance;
    }
    
    - (id)copyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    
    • 使用宏的时候
    • 在.m文件中
    #import <Foundation/Foundation.h>
    #import "SLSharedInstance.h"  // 导入,定义了宏的.h文件
    
    @interface SLPerson : NSObject<NSCopying>
    SLInstanceH(Person)  // 传入单例的对象
    @end
    
    • 在.h文件中
    #import "SLPerson.h"
    
    @implementation SLPerson
    SLInstanceM(Person)
    @end
    

    5. 单例模式(常规做法,非GCD)

    • 一定要加互斥锁,不然会有线程安全问题
    #import "SLPerson.h"
    
    @implementation SLPerson
    static id _instance;
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        @synchronized(self){ // 一定要加互斥锁,不然会有线程安全问题
            if (_instance == nil) {
                _instance = [[super allocWithZone:zone] init];
            }
        }
        return _instance;
    }
    + (instancetype)sharedPerson
    {
        @synchronized(self){
            if (_instance == nil) {
                _instance = [[self alloc] init];
            }
        }
        return _instance;
    }
    
    // 要有对象才能进行copy
    - (id)copyWithZone:(NSZone *)zone
    {
        return _instance;
    }
    @end
    
  • 相关阅读:
    【掉下巴】枪的制造现场
    不引入第三个变量交换两个变量的方法
    [转]科学计算经典算法
    [小练eVC]常用控件之微调按钮
    【收购】LSI 40亿美元并购Agere
    VB6.0不支持鼠标滚轮的解决办法
    一个简单的BP网络C语言程序
    [转]想成为嵌入式程序员应知道的0x10个基本问题
    [zt]关于左值"lvalue"和右值"rvalue"的一点理解
    [掉下巴]细数非洲大山的肘下亡魂
  • 原文地址:https://www.cnblogs.com/coderAlin/p/4752248.html
Copyright © 2011-2022 走看看