iOS单例一行实现(抽取单例宏)

作者: 王技术 | 来源:发表于2017-07-10 15:54 被阅读339次

本文首先实现单例模式,然后对单例代码进行抽取宏,使其他类可以一句代码实现单例(只介绍ARC环境)
本文代码

- 单例介绍
  • 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
  • 从而方便地控制了实例个数,并节约系统资源
  • 在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)
- 单例实现

以代码中的Book类为例
首先要在.h文件中提供外部访问方法

+ (instancetype)sharedBook;

然后是.m文件中实现这个方法

static HXBook *_book;

+ (instancetype)sharedBook
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _book = [[self alloc] init];
    });
    return _book;
}

我们知道,新建对象的时候调用alloc和init方法
在alloc中,系统为我们的对象分配了内存
在系统内部,alloc默认调用了allocWithZone
所以,实现单例要重写这两个方法

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _book = [super allocWithZone:zone];
    });
    return _book;
}

- (id)copyWithZone:(NSZone *)zone{
    return _book;
}

单例已经完成了,测试一下效果:

    HXBook *book1 = [[HXBook alloc]init];
    HXBook *book2 = [HXBook sharedBook];
    HXBook *book3 = [[HXBook alloc]init];
    NSLog(@"\n%p\n%p\n%p",book1,book2,book3);

打印结果:

2017-07-10 15:39:35.297 HXSingleton[1529:400378] 
0x608000005bf0
0x608000005bf0
0x608000005bf0

内存地址是一样的,完成.

- 对单例抽取宏

新建文件HXSingleton.h
首先对需要做单例类的.h文件抽取宏
name是需要传入的名字

// .h文件
#define HXSingletonH(name) + (instancetype)shared##name;

然后是.m文件的抽取

// .m文件
#define HXSingletonM(name) \
static id _instance; \
 \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [super allocWithZone:zone]; \
    }); \
    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; \
}

#######宏的使用
新建HXPen类
.h中这么写:

#import <Foundation/Foundation.h>
#import "HXSingleton.h"

@interface HXPen : NSObject
HXSingletonH(Pen)
@end

.m中这么写

@implementation HXPen
HXSingletonM(Pen)
@end

完成!
测试一下:

    HXPen *pen1 = [[HXPen alloc]init];
    HXPen *pen2 = [HXPen sharedPen];
    HXPen *pen3 = [[HXPen alloc]init];
    NSLog(@"\n%p\n%p\n%p",pen1,pen2,pen3);

打印结果:

2017-07-10 15:44:54.380 HXSingleton[1564:431889] 
0x608000008ed0
0x608000008ed0
0x608000008ed0

内存是一样的,完成!

谢谢阅读
有不合适的地方请指教
喜欢请点个赞
抱拳了!

相关文章

  • iOS单例一行实现(抽取单例宏)

    本文首先实现单例模式,然后对单例代码进行抽取宏,使其他类可以一句代码实现单例(只介绍ARC环境)本文代码 - 单例...

  • iOS 单例

    单例模式实现不能使用继承 定义单例实现 简写 定义单例实现宏

  • 单例模式和GCD单例实现

    1、传统单例模式2、GCD单例模式3、用宏实现GCD单例模式4、用宏实现GCD单例模式,名称随类名变化而变化 单例...

  • 单例

    单例 单例宏

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • iOS单例模式的实现

    转自于宏创学院:单例singleton模式–单例类的实现 – 宏创学院 以前写的单例类只是提供了一个 类方法让外界...

  • iOS开发之单例宏抽取

    在需要实现单例的类的.h和.m文件下分别写下这两个宏的实现,会自动实现shareInstance方法,返回该类的单...

  • iOS 单例模式

    关于单例模式的详解,看完这几篇,就完全了然了。iOS 单例模式iOS中的单例模式iOS单例的写法

  • iOS 单例

    Objective-C 单例宏 Swift 单例声明

  • OC语言day08-22宏定义抽取单例

    pragma mark 宏定义抽取单例 pragma mark 概念 pragma mark 代码 Tools.h...

网友评论

  • 随行的羊:希望关注 “iOS开发知识小集” 专题,学习更精炼的iOS技术 😄 https://www.jianshu.com/c/7c8c0fe15550
  • a5a2b92ecd85:总觉得宏在预加载的时候占用太多资源
    能少用就少用一些吧
    类似的处理思路出现很久了
    allocWithZone&&copyWithZone那段代码不错
    王技术:@王家伟 嗯嗯,确实预加载会占用很多资源,而且在项目中用到宏的地方并不多,用宏会有些浪费,我也是突发奇想做实现这么一个东西。

本文标题:iOS单例一行实现(抽取单例宏)

本文链接:https://www.haomeiwen.com/subject/zfzyhxtx.html