在iOS的开发中,单例设计模式(Singleton Pattern)是用得最多的设计模式之一了。在iOS的SDK中,很多地方都可以看到它的踪影。例如UIApplication, 我们可以在任何地方调用sharedApplication方法来获取当前运行的UIApplication实例。对于这个设计模式的优缺点我们这里就不讨论了,我们着重放在如何实现。
文章用到的Demo源码在这里.
Objective-C
在ARC模式下,我们创建一个单例类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模式下,在实现文件要重写其他的方法
//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
如果要给某个类关闭ARC,如图在TARGETS -> Build Phases -> Compile Sources 里给相应的class加 -fno-objc-arc
WX20180904-143419@2x.png
如何在Swift下创建一个单例
// LocationManager.swift
import UIKit
class LocationManager: NSObject {
static let shared = LocationManager()
var hasLocation: Bool?
private override init() {
}
func requestForLocation(){
hasLocation = true
print("Location granted")
}
}
我们创建这个单例实例的话代码如下
LocationManager.shared.requestForLocation()
如果尝试使用init的方法就会报错
WX20180904-144831@2x.png