iOS中的单例模式

在程序运行中,一个类只有一个实例,就叫单例。当我们想要在整个应用程序中,指定一份资源只能被初始化一次,并且实现共享的时候我们就可以使用单例模式,也就是创建一个单例类,用它来管理指定资源。

一、如何在创建一份ARCMRC通用的单例?
  1. 在类的内部提供一个static修饰的全局变量
  2. 提供一个类方法,方便外界访问
  3. 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间
  4. 严谨起见,重写-copyWithZone方法和-MutableCopyWithZone方法

如果是MRC则还需要以下步骤:

  1. 重写release方法
  2. 重写retain方法
  3. 建议在retainCount方法中返回一个最大值

我们来看一下代码:

//
//  STSingleton.m
//  单例模式
//
//  Created by Swift Gao on 16/6/24.
//  Copyright © 2016年 Swift Gao. All rights reserved.
//

#import "STSingleton.h"

@implementation STSingleton

static STSingleton *_instance;

//保证只分配一次存储空间

+(instancetype)allocWithZone:(struct _NSZone *)zone{


//    @synchronized(self) {
//        if (_instance == nil) {
//            _instance = [super allocWithZone:zone];
//        }
//    }
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
        _instance = [super allocWithZone:zone];
    });

    return _instance;
}

+(instancetype)shareSTSingleton{
    return [[self alloc]init];
}

- (id)copyWithZone:(NSZone *)zone{
    return _instance;
}

-(id)mutableCopyWithZone:(NSZone *)zone{
    return _instance;
}

#if __has_feature(objc_arc)
//ARC
//什么都不做
#else
//MRC
//如果用户release了一次,那么什么都不做,因为单例模式在整个程序运行过程中都拥有且
//只有一份,程序退出之后被释放,所以不需要对引用计数器操作
-(oneway void)release
{
}
//在MRC环境下,如果用户retain了一次,那么直接返回instance变量,不对引用计数器+1

-(instancetype)retain
{
    return _instance;
}

//惯用法,有经验的程序员通过打印retainCount这个值可以猜到这是一个单例
-(NSUInteger)retainCount
{
    return MAXFLOAT;
}

#endif
@end
二、单例类能使用继承吗?

答案是不行的,为什么?

单例类中使用了static修饰的全局变量,继承的时候也会将其继承过来,而这个变量只能创建一次。如果你真的去尝试继承,你会发现,你用父类和子类创建的对象是同一个,继承失去了意义,这并不是我们想要的。

我们使用继承的目的是减少代码量,提高代码的复用以提高开发效率并使得项目结构更加整洁。如果我们也想要使得单例类可以复用,而我们已经知道无法通过继承的方式去实现,那么有没有其他方法?

当然是有的,我们这边使用带参数的宏定义来解决问题。当然,如果有幸让身为大神的你看到这篇文章并且你刚好也有其他更好的解决方案,烦请告知,不胜感激。

创建一个宏定义头文件,直接看代码吧:

//
//  Singleton.h
//  单例模式
//
//  Created by Swift Gao on 16/6/25.
//  Copyright © 2016年 Swift Gao. All rights reserved.
//

#define singleH(name) +(instancetype)share##name;
//反斜杠用于拼接跨行
//if
#if __has_feature(objc_arc)
//ARC
//define
#define singleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken,^{\
        _instance = [super allocWithZone:zone];\
    });\
    return _instance;\
}\
\
+(instancetype)share##name{\
    return [[self alloc]init];\
}\
\
- (id)copyWithZone:(NSZone *)zone{\
    return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone{\
    return _instance;\
}

//else
#else 

//define
#define singleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken,^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+(instancetype)share##name{\
return [[self alloc]init];\
}\
\
- (id)copyWithZone:(NSZone *)zone{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone{\
return _instance;\
}\
\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
    return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
    return MAXFLOAT;\
}
//endif
#endif

如何使用?
如果你要创建一个单例类:Bluetooth

//
//  Bluetooth.h
//  单例模式
//
//  Created by Swift Gao on 16/6/24.
//  Copyright © 2016年 Swift Gao. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "Singleton.h"
@interface Bluetooth : NSObject
//这里使用了宏定义
singleH(Bluetooth)
@end
//
//  Bluetooth.m
//  单例模式
//
//  Created by Swift Gao on 16/6/24.
//  Copyright © 2016年 Swift Gao. All rights reserved.
//

#import "Bluetooth.h"

@implementation Bluetooth
singleM(Bluetooth)
@end

是的,就这么简单,一次编写,可以到处使用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值