單例是設計模式中常見的一種。
//
// 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