iOS ARC與MRC的單例設計模式

單例設計模式(Singleton)

定義

就是保證某個類建立出來的對象從始到終只有一個的一種方案git

做用

  • 節省內存開銷
  • 保證整個程序中使用同一份資源

實現

首先將咱們的環境設置爲非ARC環境,即MRC,如圖 github

MRC環境

在MRC模式下,咱們得本身手動釋放資源,因此得重寫一些與資源建立與釋放相關的方法,以保證單例對象的惟一。設計模式

新建一個繼承於NSObject的類 LXFFileTool,我直接上代碼,並寫上註釋 LXFFileTool.h安全

@interface LXFFileTool : NSObject
+ (instancetype)sharedFileTool;
@end
複製代碼

LXFFileTool.mbash

#import "LXFFileTool.h"
@implementation LXFFileTool
static LXFFileTool *_fileTools = nil;
/** * alloc方法內部會調用allocWithZone: * @param zone 系統分配給app的內存 */
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    if (_fileTools == nil) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{    // 安全(這個代碼只會被調用一次)
            _fileTools = [super allocWithZone:zone];
        });
    }
    return _fileTools;
}
- (oneway void)release {
    // 在allocWithZone中使用了GCD令建立對象的代碼只執行一次,若是_fileTools被釋放則沒法再建立
    // 重寫release方法,防止_fileTools被釋放
}
// 重寫retain方法
- (instancetype)retain {
    return self;
}
// 重寫retainCount鎖定引用計數
- (NSUInteger)retainCount {
    return 1;
}
// 重寫init方法,防止單例所擁有的屬性值被重置
// 讓初始化的方法只能執行一次,天然屬性值就沒有機會被重置
- (instancetype)init {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _fileTools = [super init];  // init會先調用alloc方法
    });
    return _fileTools;
}
// 仿造系統的單例建立方式,提供類方法
+ (instancetype)sharedFileTool {
    // 因爲咱們已經重寫了init方法保證了單例對象的惟一了,因此這裏直接調用init方法便可。
    return [[self alloc] init];
}
@end
複製代碼

MRC下就是這樣,咱們的目的就是隻能建立和初始化一次對象,不給機會釋放,也不給機會從新初始化,從而保證了該對象的惟一。微信

那如今來看看ARC下是如何實現單例的吧。其實ARC下與MRC的區別就是ARC下咱們不用本身再手動去釋放資源了,從而使代碼上大同小異,以下所示。app

#import "LXFFileTool.h"
@implementation LXFFileTool

static LXFFileTool *_fileTools = nil;

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    if (_fileTools == nil) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _fileTools = [super allocWithZone:zone];
        });
    }
    return _fileTools;
}
- (instancetype)init {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _fileTools = [super init];
    });
    return _fileTools;
}
+ (instancetype)sharedFileTool {
    return [[self alloc] init];
}
複製代碼

批量建立單例

如今咱們已經知道了ARC與MRC下分別是如何建立單例的了,可是若是咱們一個項目裏須要多個單例,那咱們只能把代碼複製粘貼再改改就完事嗎?這未免也太麻煩了吧。那咱們能不能作到快速且方便的建立單例對象呢?能夠的,利用宏ui

首先先說下一些關於宏的知識吧spa

  • 使用 #define 關鍵字來定義宏
  • 宏定義只能是單行的,不能換行

那如今來討論下一些疑惑吧,你說宏只能單行,但是建立單例的代碼但是有不少行呀!還有咱們如何作到自定義類方法名(就是 sharedXXX )?好,咱們來介紹下宏下的兩個特殊符號設計

宏的特殊符號

 做用
\ 用來轉譯換行符,即屏蔽換行符
## 將兩個相鄰的標記(token)鏈接爲一個單獨的標記

想了解其它關於宏的預處理命令能夠自行百度參考"C語言的預處理命令"

簡單來講,\用於取消換行,##用來鏈接,而咱們就用##來實現自定義類方法名

建立一個頭文件Singleton.h用來存放宏定義 先來看看定義.h中 sharedXXX 是如何經過宏來定義的

// .h文件的實現
#define SingletonH(methodName) + (instancetype)shared##methodName;
複製代碼

如今回到LXFFileTool.h中,直接一行定義sharedFileTool這個類方法

#import "Singleton.h"
@interface LXFFileTool : NSObject
SingletonH(FileTool)
@end
複製代碼

咱們只須要將方法名FileTool傳入SingletonH()中就能夠拼接爲sharedFileTool

那如今再來看看定義.m中建立單例的方式,以ARC爲例

#define SingletonM(methodName) \
static id _instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zAone { \
    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]; \
}
複製代碼

在每個行後面加上(反斜槓)取消換行,使用##來拼接傳入的方法名,但還有一點須要注意:最後一行不能加反斜槓

回到LXFFileTool.m中,一行實現建立單例

#import "LXFFileTool.h"
@implementation LXFFileTool
SingletonM(FileTool)
@end
複製代碼

好,如今還有一個問題,就是若是個人項目中有個別文件是須要MRC環境的,那我該怎麼辦才能讓建立單例也是如此簡單呢?很簡單,加個判斷就行了,大體判斷以下,詳情看文章最後附上的Demo

#if __has_feature(objc_arc) // ARC
// 寫上ARC下的定義代碼
#else // 非ARC
// 寫上MRC下的定義代碼
#endif
複製代碼

好了,如今用起來是否是方便多了?咱們只要建立一個類,而後在.h文件中寫SingletonH(XXX),再在.m文件中寫SingletonM(XXX)就能夠實現單例了~

指定環境

順便提下如何在MRC下指定某個類文件使用的環境爲ARC

指定環境
如圖,能夠在 Build Phases -> Compile Sources 中雙擊某個須要ARC環境的類文件,而後寫上

-fobjc-arc
複製代碼

若是是指定MRC,則寫上

-fno-objc-arc
複製代碼

Demo

最後,附上Demo: LXFSingleton

微信公衆號
相關文章
相關標籤/搜索