单例

1、什么是单例模式

    简单的来说,一个单例类,在整个程序中只有一个实例,并且提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序(APP)退出时由系统自动释放这部分内存。

2.系统为我们提供的单例类有哪些?

    UIApplication(应用程序实例类)

    NSNotificationCenter(消息中心类)

    NSFileManager(文件管理类)

    NSUserDefaults(应用程序设置)

    NSURLCache(请求缓存类)

    NSHTTPCookieStorage(应用程序cookies池)

3.在哪些地方会用到单例模式

    一般来说 经常调用的类,如工具类、公共跳转类等,采用单例模式

4.重复初始化单例类会怎样?

    程序直接崩溃  因为一个单例类只能初始化一次

5.单例模式的优缺点

  优:

    1)、在整个程序中只会实例化一次,所以在程序如果出了问题,可以快速的定位问题所在;

    2)、由于在整个程序中只存在一个对象,节省了系统内存资源,提高了程序的运行效率;

  缺:

    1)、不能被继承,不能有子类;

    2)、不易被重写或扩展;

    3)、同时,由于单例对象只要程序在运行中就会一直占用系统内存,该对象在闲置时并不能销毁,在闲置时也消耗了系统内存资源;

6.单例类的生命周期

    下面的表格展示了程序中中不同的变量在手机存储器中的存储位置

    一个单例类在程序中只能初始化一次,为了保证在使用中始终都是存在的,所以单例是在存储器的全局区域,在编译时分配内存,只要程序还在运行就会一直占用内存,在APP结束后由系统释放这部分内存内存。

7.1如何单例类ARC (分MRC ARC)

    ARC实现单例过程:

    1.在类的内部提供一个static修饰的全局变量static SingletonVC * _singletonVC;;

    2 提供一个类方法,方便外界访问

    3 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间

    4.严谨起见,重写-copyWithZone方法和-MutableCopyWithZone方法

 

    单例三种写法

        第一种:GCD的一次函数(dispatch_once_t)

        第二种:线程锁

        第三种:懒加载模式   (不推荐使用这种方法,线程不安全)

 

第一种:GCD的一次函数(dispatch_once_t)

 

#import "SingletonVC.h"

// 创建静态对象 防止外部访问

static SingletonVC * _singletonVC;

@implementation SingletonVC

+ (instancetype)allocWithZone:(struct _NSZone *)zone{

    

    static dispatch_once_t onceToken;

    // 一次函数

    dispatch_once(&onceToken, ^{

        if (_singletonVC == nil) {

            _singletonVC = [super allocWithZone:zone];

        }

    });

    

    return _singletonVC;

}

+ (instancetype)share{

    

    return  [[self alloc] init];

}

@end

 

第二种:线程锁

 

#import "SingletonVC.h"

// 创建静态对象 防止外部访问

static SingletonVC * _singletonVC;

@implementation SingletonVC

+ (instancetype)allocWithZone:(struct _NSZone *)zone{

    

    //线程锁

    @synchronized (self) {

        if (_singletonVC == nil) {

            

            _singletonVC = [super allocWithZone:zone];

        }

    }

    

    return _singletonVC;

}

+ (instancetype)share{

    

    return  [[self alloc] init];

}

@end

 

第三种:懒加载模式   (不推荐使用这种方法,线程不安全)

 

#import "SingletonVC.h"

static SingletonVC * _singletonVC;

@implementation SingletonVC

+ (instancetype)allocWithZone:(struct _NSZone *)zone{

    

    if (_singletonVC == nil) {

        _singletonVC = [super allocWithZone:zone];

    }

    return _singletonVC;

}

+ (instancetype)share{

    

    return  [[self alloc] init];

}

@end

 

7.2如何单例类MRC

    MRC单例实现步骤

        1 在类的内部提供一个static修饰的全局变量

        2 提供一个类方法,方便外界访问

        3 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间

        4 严谨起见,重写-copyWithZone方法和-MutableCopyWithZone方法

        5 重写release方法

        6 重写retain方法

        7 建议在retainCount方法中返回一个最大值

    配置MRC环境

        1 注意ARC不是垃圾回收机制,是编译器特性

        2 配置MRC环境:build setting ->搜索automatic ref->修改为N0

    MRC中单例代码实现

        配置好MRC环境之后,在ARC代码基础上重写下面的三个方法即可

-(oneway void)release

{

    

}

-(instancetype)retain

{

    return _instance;

}

-(NSUInteger)retainCount

{

    return MAXFLOAT;

}

 

8.一劳永逸,单例模式的优化

    1:如何写一份单例代码在ARC和MRC环境下都适用?

    2:如何使一份单例代码可以多个类共同使用

        为了解决这两个问题,我们可以在PCH文件使用代参数的宏和条件编译

        利用条件编译来判断是ARC还是MRC环境

 

#if __has_feature(objc_arc)

//如果是ARC,那么就执行这里的代码1

#else

//如果不是ARC,那么就执行代理的代码2

#endif

 

#define singleH(name) +(instancetype)share##name;

 

#if __has_feature(objc_arc)

 

#define singleM(name) static id _instance;\

+(instancetype)allocWithZone:(struct _NSZone *)zone\

{\

static dispatch_once_t onceToken;\

dispatch_once(&onceToken, ^{\

_instance = [super allocWithZone:zone];\

});\

return _instance;\

}\

\

+(instancetype)share##name\

{\

return [[self alloc]init];\

}\

-(id)copyWithZone:(NSZone *)zone\

{\

return _instance;\

}\

\

-(id)mutableCopyWithZone:(NSZone *)zone\

{\

return _instance;\

}

#else

#define singleM static id _instance;\

+(instancetype)allocWithZone:(struct _NSZone *)zone\

{\

static dispatch_once_t onceToken;\

dispatch_once(&onceToken, ^{\

_instance = [super allocWithZone:zone];\

});\

return _instance;\

}\

\

+(instancetype)shareTools\

{\

return [[self alloc]init];\

}\

-(id)copyWithZone:(NSZone *)zone\

{\

return _instance;\

}\

-(id)mutableCopyWithZone:(NSZone *)zone\

{\

return _instance;\

}\

-(oneway void)release\

{\

}\

\

-(instancetype)retain\

{\

return _instance;\

}\

\

-(NSUInteger)retainCount\

{\

return MAXFLOAT;\

}

#endif

 

任何项目中,当我们要使用单例类的时候只要在项目中导入PCH文件然后在.h文件中调用singleH(类名),在.m文件中调用singleM(类名),创建类时直接调用share类名方法即可。

 

posted on 2018-08-21 10:36  张麻子  阅读(171)  评论(0)    收藏  举报

导航