欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS单例的创建与销毁

程序员文章站 2022-06-17 19:58:44
ios单例的创建与销毁,在ios的日常开发经常要用到单例,单例一经创建就不会销毁,直到app被杀掉的时候单例占用的空间才得以释放.现在比如我有一个自行车类,并且把它写成一个单例(共享自行车,呵呵),...

ios单例的创建与销毁,在ios的日常开发经常要用到单例,单例一经创建就不会销毁,直到app被杀掉的时候单例占用的空间才得以释放.现在比如我有一个自行车类,并且把它写成一个单例(共享自行车,呵呵),代码如下:

#import "bike.h"

@implementation bike

+ (instancetype)sharedbike
{
    static bike *bike;
    static dispatch_once_t oncetoken;
    dispatch_once(&oncetoken, ^{
        bike = [bike new];
    });

    return bike;
}
@end

相信大家一般都是这么写单例的,但是这样写有什么弊端呢?假如我们的bike类需要和其它人的代码有交互,其它人在使用bike类时,没有认真看你的bike.h文件,直接用了[[bike alloc] init];来生成实例,这时候与你当初设计bike为单例的初衷相悖了.那要怎么解决这个问题呢?
在上述sharedbike方法中,生成bike类的实例时,其它调用了alloc方法(new最后也要调用alloc方法),其它人在调用的时候也用了alloc方法,那么我们可不可以在alloc方法上做一下文章呢?答案是可以的.ios中类调用alloc方法时,其它是调用了:

+ (instancetype)allocwithzone:(struct _nszone *)zone;

这个方法,所以我们只需要在这个方法中做一下文章就可以了,代码如下:

#import "bike.h"

@implementation bike

+ (instancetype)sharedbike
{
    return [[self alloc] init];
}

+ (instancetype)allocwithzone:(struct _nszone *)zone
{
    static bike *bike;
    static dispatch_once_t oncetoken;

    dispatch_once(&oncetoken, ^{
        bike = [super allocwithzone:zone];
    });

    return bike;
}

@end

上述代码即能保证通过sharedbike和[[bike alloc] init]方法得到的类都是同一个类.到这一步是不是觉得这种写法就已经ok了?不,不,不,你有没有考虑过copy与mutable时还能保证得到的是仍然是同一个单例,上代码:

#import "bike.h"

@interface bike ()

@end

@implementation bike

static bike *bike;

+ (instancetype)sharedbike
{
    return [[self alloc] init];
}

+ (instancetype)allocwithzone:(struct _nszone *)zone
{
    static dispatch_once_t oncetoken;

    dispatch_once(&oncetoken, ^{
        bike = [super allocwithzone:zone];
    });

    return bike;
}

- (instancetype)copywithzone:(nszone *)zone
{
    return bike;
}

- (instancetype)mutablecopywithzone:(nszone *)zone
{
    return bike;
}
@end

说完单例的创建,我们说说单例的销毁.世间万物,有生必有死.假如我们自己创建的一些单例类,需要内嵌到别人的工程中,而且在别人的工程中只有某种场景下,才会调用我们的单例类,再或者我们的单例类有很多属性,有一个socket保持与后台的常连接等,总之就是比较耗资源,我们希望我们的类在其它工程中如果不用了就销毁掉,这样可以节省资源.
在上述单例的代码中有一个oncetoken变量,在单例生成之前oncetoken = 0,在单例生成之后oncetoken = -1了,之后一直保持-1这个值,知道这个之后我想你应该有思路了,代码如下:

@implementation bike

static bike *bike;
static dispatch_once_t oncetoken;

- (void)destroysingleton
{
    bike = nil;
    oncetoken = 0;
}