iOS 单例模式使用

注:只介绍怎么使用,至于其他的方面,google去吧。

  1. 实现步骤:

    1. 为单例对象声明一个静态实例,并初始化,然后设置成nil。
    2. 声明并实现一个类方法,检查上面声明的静态实例是否为nil;如果是,则将静态变量初始化为本类的实例。
    3. 重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不会产生一个新实例。
    4. 非ARC(MRC)模式下,实现copyWithZone,release和autorelease等方面。
  2. 具体代码
    具体的实现方法有2种。假设有个类UserInfo需要使用单例模式。
    首先,在UserInfo.h文件中,需要提供一个标准的实例访问接口。

//该类方法的名称一般以 share,default,main为前缀
+(UserInfo *)shareUserInfo;

第1种方法:

#import "UserInfo.h"

//定义一个静态变量,用于接收实例对象并初始化为nil
static UserInfo *singleInstance = nil;

@implementation UserInfo

//在多线程的情况下,多个任务会同时执行,它们的执行方式是抢占式的,所以为保证线程安全,增加互斥锁
+ (UserInfo *)shareUserInfo {
    @synchronized (self) {
        if (singleInstance == nil) {
            singleInstance = [[UserInfo alloc] init];
        }
    }
    return singleInstance;
}

//使用单例时,不想再实例化出其它的对象,可以重写 allocWithZone: 
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    @synchronized (self) {
        if (singleInstance == nil) {
            singleInstance = [super allocWithZone:zone];
        }
    }
    return singleInstance;
}

@end

第2种方法:

#import "UserInfo.h"

static UserInfo *singleInstance = nil;

@implementation UserInfo

//1.dispatch_once可以在创建单例或者某些初始化动作时使用,以保证其唯一性。
//2.该方法是线程安全的,所以请放心大胆地在子线程中使用。前提是你的dispatch_once_t *predicate对象必须是全局或者静态对象。这一点很重要,如果不能保证这一点,也就不能保证该方法只会被执行一次。
+ (UserInfo *)shareUserInfo {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleInstance = [[UserInfo alloc] init];
    });
    return singleInstance;
}

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

@end

另外,在非ARC(MRC)模式下,需要重写以下方法

//禁止copy
+(id)copyWithZone:(struct _NSZone *)zone{
    return self;
}
//retain后引用计数+1
-(instancetype)retain{
    return self;
}
//release后引用计数-1
-(oneway void)release{
    //什么都不做
}
//自动释放池
-(instancetype)autorelease{
    return self;
}
//查看引用计数器
-(NSUInteger)retainCount{
    //返回无穷大的数,表示不能release
    return NSIntegerMax;
}

你可能感兴趣的:(iOS 单例模式使用)