iOS中单例模式的基本应用

ARC(自动内存管理)下实现单例模式

前言

开发过程中,遇到一种情况:需要多次用到某个类,每次创建都会分配新的内存地址。但是,在某些场合这是没有必要的。

如播放音乐,一般不会说,开一个播放器同时播放多首歌。

而且,系统的资源是有限的,特别是移动设备。所以 ‘ 单例模式 ’ 应运而生。

简介

单例模式:在程序运行过程中,一个类只有一个实例。而且该实例易于供外界使用。换句话说,一个类无论创建多少次,都只分配一次存储空间。

目的

为了在程序运行过程中,共享一份资源,且这份资源只会初始化一次,只分配一次存储空间,从而节约系统资源。

好处

节约系统资源。

实现步骤

以PDuser类为例

1、定义静态变量,存储唯一实例

static PDuser *_instance;

这样,外面就不能获取到这个实例变量,只能在本文件中访问。

2、重写allocWithZone方法,在里面用一次性代码函数dispatch_once,并调用super allocWithZone方法

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

这一步,也可以用懒加载的方式来做:

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{    
    //  考虑到使用时可能在多条线程同时执行此方法任务,那么就可能引发线程安全问题,所以需要对线程进行加锁操作
    @synchronized(self) {
        if (_instance == nil) { 
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

3、实现类方法

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

new方法:分配内存并且初始化
alloc:为对象分配内存,init:初始化对象中的属性等

4、外界调用方法
提供一个类方法,获取单例对象,方便创建。
+ (instancetype)shareUser;

至此,基本的单例已经实现。下面可以再继续完善。


5、处理copy的情况(可选)
为了让单例严谨一点,如果要支持copy,则重写copy和mutableCopy。直接返回变量即可,因为只有创建了对象,才能使用copy方法。

先遵守协议<NSCopying, NSMutableCopying>

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

- (id)mutableCopyWithZone:(NSZone *)zone
{
    return _instance;
}

6、销毁单例
dispatch_once_t参数的初始值就是0l,只需要重置dispatch_once_t参数及实例参数_instance即可。

给外界提供类方法

+(void)releaseInstance{ 
    _instance = nil;
    onceToken = 0l;
    //将静态存储区的静态变量指针 置为nil,
//这样单例对象在没有任何指针指向的情况下 被系统回收了。 
}
  • 注意 : 使用单例模式设计的类,不可继承!

单例命名格式

牵扯到命名的问题,怎样命名才规范?单例常见的命名形式有这几种:share 、share + 类名 、default、default + 类名

适用场景

在整个程序中,都可以共享同一份资源——这份资源只需创建初始化一次,只分配一次存储空间即可。
例如:用户实例、文件管理者等。

测试

创建3个对象

    PDuser *user1 = [PDuser shareUser];
    PDuser *user2 = [PDuser shareUser];
    PDuser *user3 = [PDuser shareUser];
    NSLog(@"user1:%@\nuser2:%@\nuser3:%@",user1,user2,user3);

结果


QQ.png

成功

宏定义

若要实现单例代码复用,不能用继承。用宏,把单例模式抽取出来。

新建一个.h文件Single.h,其中包含两个部分,即.h和.m部分

把具体的类类型,改成id 类型,并设置参数(name)类名,用##连接,使用时,外界的类可以灵活变换。另外,.m中的代码用多个""号连接起来。

QQ.png

外界使用:

在新建的某个类的.h中,注意带上参数 类名

QQ.png

.m中

QQ.png

即可

相关资料

https://www.jianshu.com/p/5226bc8ed784

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。