关闭

IOS-单例模式

标签: ios单例对象GCD
339人阅读 评论(0) 收藏 举报
分类:

单例模式可以保证在程序运行的过程中,一个类只有一个实例方法,而且该实例易于供外界访问。例如,oc中的 UIApplication 可以通过 [UIApplication sharedApplication] 方法开速实例化一个UIApplication对象,而且在整个项目中仅实例化一份,即只有一个内存地址。

单例模式可以分为两类:(1)懒汉式,第一次用到这个单例对象的时候,再创建;(2)饿汉式,一进入程序就创建一个单例对象。在实际上一般都是“懒汉式”的单例模式,因为当项目中的单例对象较多时,如果使用“饿汉式”​单例模式,会导致程序在一启动就加载单例对象,或许项目中的很多单例一开始更不用不到,这样就消耗了不必要的内存。所以,一般选取“懒汉式”的单例模式,这样在需要的时候,再创建单例对象。

实现单例对象步骤可以归纳为:

(1)提供全局变量;

(2)重写allocWithZone方法,(这是alloc底层调用的方法)

(3)提供类方法sharedClassName​(其中ClassName为对象的名称),方便其他开发人员快速调用。

(4)重写copyWithZone方法。

如果是非ARC环境,基于上述步骤还要重写retain、retainCount、autorelease和release方法。​

实现单例对象可以采用两种方式:一种是互斥锁访问,一种是GCD实现。

互斥锁实现单例模式:

static id _instance;
//这里的static修饰全局变量,使得全局变量的作用域仅限于当前文件内,保证安全​
//重写allocWithZone方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{

    if (_instance == nil) {//保证只加一次锁,方式重复加锁

        @synchronized(self) {//加锁,多线程安全

            if (_instance == nil) {//防止创建多次

                _instance = [super allocWithZone:zone];
            }
        }
    }
    return _instance;
}
//实现外部调用的shared方法
+ (instancetype)sharedMusicTool{
    if (_instance == nil) {
        @synchronized(self) {
            if (_instance == nil) {
                _instance = [[self alloc] init];
            }
        }
    }
    return _instance;
}
//实现copyWithZone方法
- (id)copyWithZone:(NSZone *)zone{
    return _instance;
}
//非ARC要实现
- (oneway void)release{
}

- (instancetype)retain{
    return self;
}
- (NSUInteger)retainCount{
    return 1;
}
- (instancetype)autorelease{
    return self;
}

GCD实现单例模式:

static id _instance;
//这里的static修饰全局变量,使得全局变量的作用域仅限于当前文件内,保证安全​
//重写allocWithZone方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
	static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{//代码仅被执行一次
        _instance = [super allocWithZone:zone];
    });          
    return _instance;
}
//实现外部调用的shared方法
+ (instancetype)sharedMusicTool{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{//代码仅被执行一次
        _instance = [[self alloc] init];
    });   
    return _instance;
}
//实现copyWithZone方法
- (id)copyWithZone:(NSZone *)zone{
    return _instance;
}
//非ARC要实现
- (oneway void)release{
}

- (instancetype)retain{
    return self;
}
- (NSUInteger)retainCount{
    return 1;
}
- (instancetype)autorelease{
    return self;
}

每次实现都用这段代码实现单例对象时,代码重复率高,因此定义一个专门实现单例对象的宏,其他单例对象直接调用单例的宏定义即可,简化了代码。宏定义为:

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

//.m文件
//ARC环境
#if __has_feature(objc_arc)
//ARC环境
#define XCSingleModelM(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; \
}
#else

//MRC环境,非ARC环境
#define XCSingleModelM(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; \
} \
 \
- (oneway void)release{ \
     \
} \
 \
- (instancetype)retain{ \
    return self; \
} \
 \
- (NSUInteger)retainCount{ \
    return 1; \
} \
 \
- (instancetype)autorelease{ \
    return self; \
}
#endif

当定义一个单例对象的时候,可以引入宏定义:

.h文件:

#import <Foundation/Foundation.h>
#import "<span style="font-family: Arial, Helvetica, sans-serif;">SingleHod</span>.h"

@interface ClassName : NSObject

SingleHod(ClassName);

@end
.m文件:
<pre name="code" class="objc">#import "ClassName.h"
#import "SingleHod.h"

@implementation ClassName

SingleHod(ClassName);

@end







2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:49368次
    • 积分:1167
    • 等级:
    • 排名:千里之外
    • 原创:67篇
    • 转载:1篇
    • 译文:0篇
    • 评论:4条
    博客专栏
    最新评论