单例是设计模式中常见的一种。
//
// Singleton.h
// 单例
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
+ (instancetype)shareInstance;
@end
//
// Singleton.m
// 单例
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import "Singleton.h"
@implementation Singleton
+ (instancetype)shareInstance {
static Singleton * singletion = nil;
if (!singletion) {
singletion = [[Singleton alloc]init];
}
return singletion;
}
@end
调用
//
// main.m
// 单例
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Singleton.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Singleton *s1 = [Singleton shareInstance];
Singleton *s2 = [Singleton shareInstance];
Singleton *s3 = [Singleton shareInstance];
NSLog(@"%p, %p, %p", s1, s2, s3);
}
return 0;
}
打印的结果:
0x102040f60, 0x102040f60, 0x102040f60
对于多线程情况,增加互斥锁,以及copy对象优化等。
//
// Singletion.h
// 优化后的.h文件没有变
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Singletion : NSObject
+ (instancetype)shareInstance;
@end
//
// Singletion.m
// 优化后的.m文件增加互斥锁等。
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import "Singletion.h"
@interface Singletion()<NSCopying,NSMutableCopying>
@end
@implementation Singletion
static id _instance;
+ (instancetype)shareInstance { // 提供类方法,用于外界访问
@synchronized (self) {
if (!_instance) {
_instance = [[self alloc]init];
}
}
return _instance;
}
+ (instancetype) allocWithZone:(struct _NSZone *)zone { // 在这里创建唯一的实例
@synchronized(self) {
if (!_instance) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
- (instancetype)copyWithZone:(struct _NSZone*)zone { // 保证复制时不生成新对象
return _instance;
}
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
return _instance;
}
@end
在ios中,关于多线程安全的使用,我们通常会使用dispatch_once。所以,单例的线程安全改法更贴近ios开发习惯的写法是:
//
// Singletion.m
//
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import "Singletion.h"
@interface Singletion()<NSCopying,NSMutableCopying>
@end
@implementation Singletion
static id _instance;
+ (instancetype)shareInstance { // 提供类方法,用于外界访问
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc]init];
});
return _instance;
}
+ (instancetype) allocWithZone:(struct _NSZone *)zone { // 在这里创建唯一的实例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
- (instancetype)copyWithZone:(struct _NSZone*)zone { // 保证复制时不生成新对象
return _instance;
}
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
return _instance;
}
@end
使用 NS_UNAVAILABLE 修饰单例
//
// Singletion.h
//
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Singletion : NSObject
+ (nonnull instancetype)shareInstance;
- (nonnull instancetype)init NS_UNAVAILABLE;
- (nonnull instancetype)new NS_UNAVAILABLE;
@end
//
// Singletion.m
//
//
// Created by hhg on 15-6-11.
// Copyright (c) 2015年 hhg. All rights reserved.
//
#import "Singletion.h"
@implementation Singletion
-(instancetype)init {
if (self = [super init]) {
__weak typeof(self) weakSelf = self;
static dispatch_once_t onceToken;
dispatch_once(&onceToken ,^{
__strong typeof(self) strongSelf = weakSelf;
// other coder
});
}
return self;
}
+ (instancetype)shareInstance { // 提供类方法,用于外界访问
static Singletion * _instance;
static dispatch_once_t onceToken;
distapch_once(&onceToken ,^{
_instance = [[self alloc]init];
});
return _instance ;
}
@end
注:以上代码在文档编辑器直接盲敲的,可能会有疏漏,如复制黏贴到xcode跑起来有问题的自行修改一下,也欢迎留言修改。
相关参考:
《IQKeyboardManager》源码
相关讨论/指导:
成都_Peter