iOS开发单例的严谨写法

2017-12-06  本文已影响77人  因为太有钱

OC 的单例写法

创建对象的步骤分为
1:申请内存(alloc)
2:初始化(init) 这两个步骤
我们要确保对象的唯一性,因此在第一步这个阶段我们就要拦截它。
当我们调用alloc方法时,OC内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的。
拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象。

#import "Single.h"
static Single *single = nil;
@implementation Single
+(instancetype) shareInstance{
    static dispatch_once_t onceToken ;
    dispatch_once(&onceToken, ^{
        single = [[super allocWithZone:NULL] init];
    }) ;
    return single ;
}
+(id) allocWithZone:(struct _NSZone *)zone{
    return [Single shareInstance] ;
}
-(id) copyWithZone:(struct _NSZone *)zone{
    return [Single shareInstance] ;
}
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%@%@",[[Single alloc] init],[Single shareInstance]);
   //打印结果:<Single: 0x60400001fdb0><Single: 0x60400001fdb0>
}

可继承单利

可继承单例是指父类中写下单例创建的方法
当其本身类或其子类调用父类中的类创建的方法时, 可以各自类创建各自类的单例. 所以, 在父类中写的一个方法, 同时适用于其本身和其子类, 故称作可继承单例.

#import "Singleton.h"
#import <objc/runtime.h>
@implementation Singleton
+(instancetype)sharedInstance{
    id instance = objc_getAssociatedObject(self, @"instance");
    if (!instance){
        instance = [[super allocWithZone:NULL] init];
        NSLog(@"单例创建=====%@=====",instance);
        objc_setAssociatedObject(self, @"instance", instance, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return instance;
}
+(id) allocWithZone:(struct _NSZone *)zone{
    return [self sharedInstance] ;
}
-(id) copyWithZone:(struct _NSZone *)zone{
    Class selfClass = [self class];
    return [selfClass sharedInstance] ;
}
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    //继承单利
     NSLog(@"%@%@",[[Inheritance alloc] init],[Inheritance sharedInstance]);
      //打印结果 <Inheritance: 0x6040000068a0><Inheritance: 0x6040000068a0>
    //再创建继承自 Inheritance 的文件 也能直接创建单利
}
@end

宏 定义一个 单利 文件

#ifndef SingleTone_h
#define SingleTone_h

#define SingleToneH(MethodName) +(instancetype)shared##MethodName

//如果不是ARC的模式下
#if !__has_feature(objc_arc)
#define SingleToneM(MethodName)\
static id _instance = nil;\
+(id)allocWithZone:(struct _NSZone *)zone\
{\
if (_instance == nil) {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
}\
return _instance;\
}\
-(instancetype)init\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super init];\
});\
return _instance;\
}\
+(instancetype)shared##MethodName\
{\
return [[self alloc] init];\
}\
-(oneway void)release{}\
-(id)retain{return self;}\
-(NSUInteger)retainCount{return 1;}\

#else

#define SingleToneM(MethodName)\
static id _instance = nil;\
+(id)allocWithZone:(struct _NSZone *)zone\
{\
if (_instance == nil) {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
}\
return _instance;\
}\
-(instancetype)init\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super init];\
});\
return _instance;\
}\
+(instancetype)shared##MethodName\
{\
return [[self alloc] init];\
}

#endif

#endif /* SingleTone_h */

使用的时候 直接创建一个.h文件 把上边代码 粘过去
分别在 .h文件 .m文件 调用相应宏就可以

#import <Foundation/Foundation.h>
#import "SingleTone.h"

@interface MalocSingleTone : NSObject
SingleToneH(Maloc);
@end

#import "MalocSingleTone.h"
@implementation MalocSingleTone
SingleToneM(Maloc)
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%@,%@",[MalocSingleTone sharedMaloc],[[MalocSingleTone alloc] init]);
   //打印结果: <MalocSingleTone: 0x604000008820>,<MalocSingleTone: 0x604000008820>
}

老版本中 Swift 仿 OC 的写法

class SharedInstance: NSObject {
    static var instance: SharedInstance?
    static var onceToken: dispatch_once_t = 0
    class func shared() -> SharedInstance {
        dispatch_once(&onceToken) { () -> Void in
            instance = SharedInstance()
        }
        return instance!
    }
}

现在单利的写法

class NetWork: NSObject {
    static let shareNet  =  NetWork.init()
    private override init(){}
}

文章参考: iOS严谨单例写法/可继承单例
代码地址:Github 代码地址

上一篇 下一篇

猜你喜欢

热点阅读