OC中的单例模式

单例简介

单例之所以叫单例就是整个类有且仅有一个对象,从而方便对实例个数的控制并节约系统资源,平时项目开发中用到最多的就是页面之间的传值,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
    
    
    
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值