OC中的单例模式

    科技2022-07-11  82

    单例简介

    单例之所以叫单例就是整个类有且仅有一个对象,从而方便对实例个数的控制并节约系统资源,平时项目开发中用到最多的就是页面之间的传值,A页面将对应属性赋值后,全世界都可以访问,直到程序退出内存才会释放。

    常见的单例创建

    创建一个单例类 .h文件提供一个快速创建对象的方法, 一般情况下用于创建单例对象的方法名称都以share开头, 或者以default开头

    #import <Foundation/Foundation.h> @interface Tools : NSObject<NSCopying, NSMutableCopying> // 一般情况下创建一个单例对象都有一个与之对应的类方法 // 一般情况下用于创建单例对象的方法名称都以share开头, 或者以default 开头 + (instancetype)shareInstance; @end

    .m文件中处理创建对象的唯一性,当我们在初始化对象的时候,调用alloc方法时,系统会帮我们调用+ (instancetype)allocWithZone:(struct _NSZone *)zone,所以我们需要重写这个方法,保证唯一性,还有在创建对象的时候,可能会用copy方法创建,所以我们需要重写- (id)copyWithZone:(NSZone *)zone和- (id)mutableCopyWithZone:(NSZone *)zone两个方法

    #import "Tools.h" @implementation Tools static Tools *_instance = nil; + (instancetype)shareInstance { Tools *instance = [[self alloc] init]; return instance; } + (instancetype)allocWithZone:(struct _NSZone *)zone { // 以下代码在多线程中也能保证只执行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[super allocWithZone:zone] init]; }); return _instance; } // copyWithZone方法用什么调用? 对象 - (id)copyWithZone:(NSZone *)zone{ return _instance; } - (id)mutableCopyWithZone:(NSZone *)zone { return _instance; }

    一般在开发中这样处理单例就没什么问题了,现在开发环境都是ARC的模式下。当然为了严谨起见,也要做一下MRC的适配,下面的代码只适合在MRC的环境下写,ARC中会报错的

    - (oneway void)release { // 为保证整个程序过程中只有一份实例,在这个方法中什么都不做 } - (instancetype)retain { return _instance; } - (NSUInteger)retainCount { // 而是返回一个比较大得值 return MAXFLOAT; }

    为了开发快捷,我们可以将单例抽成一个宏

    我们可以将上面的代码写在一个文件中定义成单例宏,项目中多个单例可以调用同一份代码,减少项目中出现许多重复的代码。

    直接建立一个SingleInstance.h文件,代码如下// 以后就可以使用interfaceSingleton来替代后面的方法声明 #define interfaceSingleton(name) +(instancetype)share##name #if __has_feature(objc_arc) // ARC #define implementationSingleton(name) \ + (instancetype)share##name \ { \ name *instance = [[self 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 = [[self 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 抽成宏之后,下次再创建单例类的时候,直接写2行代码就可以啦,例如我们创建一个Person类,让他成为单例Person.h和.m文件代码如下#import <Foundation/Foundation.h> #import "Singleton.h" @interface Person : NSObject interfaceSingleton(Person);//直接将类名传给宏,告诉他创建哪个对象 @end #import "Person.h" @implementation Person implementationSingleton(Person)//实现单例方法 @end
    Processed: 0.058, SQL: 8