在iOS的開(kāi)發(fā)中,單例設(shè)計(jì)模式(Singleton Pattern)是用得最多的設(shè)計(jì)模式之一了。在iOS的SDK中,很多地方都可以看到它的蹤影。例如UIApplication, 我們可以在任何地方調(diào)用sharedApplication方法來(lái)獲取當(dāng)前運(yùn)行的UIApplication實(shí)例签舞。對(duì)于這個(gè)設(shè)計(jì)模式的優(yōu)缺點(diǎn)我們這里就不討論了,我們著重放在如何實(shí)現(xiàn)柒瓣。
文章用到的Demo源碼在這里.
Objective-C
在ARC模式下儒搭,我們創(chuàng)建一個(gè)單例類InfoManager
//InfoManager.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface InfoManager : NSObject
+(instancetype)shareInstance;
@end
NS_ASSUME_NONNULL_END
//InfoManager.m
#import "InfoManager.h"
static InfoManager *_infoManager = nil;
@implementation InfoManager
+(instancetype)shareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_infoManager = [[self alloc] init];
});
return _infoManager;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
@synchronized (_infoManager) {
if (_infoManager == nil) {
_infoManager = [super allocWithZone:zone];
}
}
return _infoManager;
}
-(instancetype)init{
@synchronized (self) {
self = [super init];
}
return self;
}
@end
在NON-ARC模式下,在實(shí)現(xiàn)文件要重寫(xiě)其他的方法
//InfoManager.m
#import "InfoManager-NonARC.h"
static InfoManager_NonARC *_infoManager = nil;
@implementation InfoManager_NonARC
+(instancetype)shareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_infoManager = [[self alloc] init];
});
return _infoManager;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
@synchronized (_infoManager) {
if (_infoManager == nil) {
_infoManager = [super allocWithZone:zone];
}
}
return _infoManager;
}
-(instancetype)init{
@synchronized (self) {
self = [super init];
}
return self;
}
-(instancetype)retain{
return self;
}
-(NSUInteger)retainCount{
return UINT_MAX;
}
-(oneway void)release{
}
-(instancetype)autorelease{
return self;
}
@end
如果要給某個(gè)類關(guān)閉ARC芙贫,如圖在TARGETS -> Build Phases -> Compile Sources 里給相應(yīng)的class加 -fno-objc-arc
如何在Swift下創(chuàng)建一個(gè)單例
// LocationManager.swift
import UIKit
class LocationManager: NSObject {
static let shared = LocationManager()
var hasLocation: Bool?
private override init() {
}
func requestForLocation(){
hasLocation = true
print("Location granted")
}
}
我們創(chuàng)建這個(gè)單例實(shí)例的話代碼如下
LocationManager.shared.requestForLocation()
如果嘗試使用init的方法就會(huì)報(bào)錯(cuò)