重點(diǎn) (一) : 單例模式

單例模式的作用

可以保證在程序運(yùn)行過(guò)程,一個(gè)類(lèi)只有一個(gè)實(shí)例,而且該實(shí)例易于供外界訪問(wèn)

從而方便地控制了實(shí)例個(gè)數(shù),并節(jié)約系統(tǒng)資源

單例模式的使用場(chǎng)合

在整個(gè)應(yīng)用程序中,共享一份資源(這份資源只需要?jiǎng)?chuàng)建初始化1次)

單例模式在ARC\MRC環(huán)境下的寫(xiě)法有所不同,需要編寫(xiě)2套不同的代碼

可以用宏判斷是否為ARC環(huán)境

if __has_feature(objc_arc)

// ARC

else

// MRC

endif

單例模式 - ARC

ARC中,單例模式的實(shí)現(xiàn)

在.m中保留一個(gè)全局的static的實(shí)例

static id _instance;

重寫(xiě)allocWithZone:方法,在這里創(chuàng)建唯一的實(shí)例(注意線程安全)

(id)allocWithZone:(struct
_NSZone *)zone {

if (_instance == nil) { //

防止頻繁加鎖

    @synchronized(self) {

        if

(_instance== nil) { //
防止創(chuàng)建多次

_instance = [super allocWithZone:zone];

      }


  }

}

return _instance;

}

提供1個(gè)類(lèi)方法讓外界訪問(wèn)唯一的實(shí)例

(instancetype)sharedMusicTool {

if (_instance == nil) { //

防止頻繁加鎖

    @synchronized(self) {

        if

(_instance== nil) { //
防止創(chuàng)建多次

        _instance

= [[self alloc]
init];

      }


  }

}

return _instance;

}

實(shí)現(xiàn)copyWithZone:方法

(id)copyWithZone:(struct
_NSZone *)zone {

return _instance;

}

單例模式 – 非ARC

非ARC中(MRC),單例模式的實(shí)現(xiàn)(比ARC多了幾個(gè)步驟)

實(shí)現(xiàn)內(nèi)存管理方法

(id)retain { return
self; }

(NSUInteger)retainCount {return 1; }

(oneway void)release {}

  • (id)autorelease { return
    self; }

************************筆記****************************


1.單例模式

  • 1.1 概念相關(guān)

(1)單例模式

在程序運(yùn)行過(guò)程,一個(gè)類(lèi)只有一個(gè)實(shí)例

(2)使用場(chǎng)合

在整個(gè)應(yīng)用程序中,共享一份資源(這份資源只需要?jiǎng)?chuàng)建初始化1次)

  • 1.2
    ARC實(shí)現(xiàn)單例

(1)步驟

01 在類(lèi)的內(nèi)部提供一個(gè)static修飾的全局變量

02 提供一個(gè)類(lèi)方法,方便外界訪問(wèn)

03 重寫(xiě)+allocWithZone方法,保證永遠(yuǎn)都只為單例對(duì)象分配一次內(nèi)存空間

04 嚴(yán)謹(jǐn)起見(jiàn),重寫(xiě)-copyWithZone方法和-MutableCopyWithZone方法

(2)相關(guān)代碼

提供一個(gè)static修飾的全局變量,強(qiáng)引用著已經(jīng)實(shí)例化的單例對(duì)象實(shí)例

static XMGTools *_instance;

類(lèi)方法,返回一個(gè)單例對(duì)象

+(instancetype)shareTools

{

注意:這里建議使用self,而不是直接使用類(lèi)名Tools(考慮繼承)

return [[self
alloc]init];

}

保證永遠(yuǎn)只分配一次存儲(chǔ)空間

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

{

使用GCD中的一次性代碼

static

dispatch_once_t onceToken;

dispatch_once(&onceToken,

^{

_instance

= [super allocWithZone:zone];

});

使用加鎖的方式,保證只分配一次存儲(chǔ)空間

@synchronized(self) {

if (_instance ==nil) {

  _instance = [super

allocWithZone:zone];

}

}

return _instance;

}

  1. mutableCopy 創(chuàng)建一個(gè)新的可變對(duì)象,并初始化為原對(duì)象的值,新對(duì)象的引用計(jì)數(shù)為1;

  2. copy 返回一個(gè)不可變對(duì)象。分兩種情況:(1)若原對(duì)象是不可變對(duì)象,那么返回原對(duì)象,并將其引用計(jì)數(shù)加1;(2)若原對(duì)象是可變對(duì)象,那么創(chuàng)建一個(gè)新的不可變對(duì)象,并初始化為原對(duì)象的值,新對(duì)象的引用計(jì)數(shù)為1。

讓代碼更加的嚴(yán)謹(jǐn)

-(nonnull id)copyWithZone:(nullable
NSZone *)zone

{

return [[self class] allocWithZone:zone];

return _instance;

}

-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone

{

return _instance;

}

  • 1.3
    MRC實(shí)現(xiàn)單例

(1)實(shí)現(xiàn)步驟

01 在類(lèi)的內(nèi)部提供一個(gè)static修飾的全局變量

02 提供一個(gè)類(lèi)方法,方便外界訪問(wèn)

03 重寫(xiě)+allocWithZone方法,保證永遠(yuǎn)都只為單例對(duì)象分配一次內(nèi)存空間

04 嚴(yán)謹(jǐn)起見(jiàn),重寫(xiě)-copyWithZone方法和-MutableCopyWithZone方法

05 重寫(xiě)release方法

06 重寫(xiě)retain方法

07 建議在retainCount方法中返回一個(gè)最大值

(2)配置MRC環(huán)境知識(shí)

01 注意ARC不是垃圾回收機(jī)制,是編譯器特性

02 配置MRC環(huán)境:build
setting ->搜索automatic ref->修改為NO

(3)相關(guān)代碼

提供一個(gè)static修飾的全局變量,強(qiáng)引用著已經(jīng)實(shí)例化的單例對(duì)象實(shí)例

static XMGTools *_instance;

類(lèi)方法,返回一個(gè)單例對(duì)象

+(instancetype)shareTools

{

注意:這里建議使用self,而不是直接使用類(lèi)名Tools(考慮繼承)

return [[self
alloc]init];

}

保證永遠(yuǎn)只分配一次存儲(chǔ)空間

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

{

使用GCD中的一次性代碼

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instance = [super allocWithZone:zone];

});

使用加鎖的方式,保證只分配一次存儲(chǔ)空間

@synchronized(self) {

if (_instance ==nil) {

  _instance = [super

allocWithZone:zone];

}

}

return _instance;

}

讓代碼更加的嚴(yán)謹(jǐn)

-(nonnull id)copyWithZone:(nullable
NSZone *)zone

{

return

[[self class] allocWithZone:zone];

return _instance;

}

-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone

{

return _instance;

}

在MRC環(huán)境下,如果用戶retain了一次,那么直接返回instance變量,不對(duì)引用計(jì)數(shù)器+1

如果用戶release了一次,那么什么都不做,因?yàn)閱卫J皆谡麄€(gè)程序運(yùn)行過(guò)程中都擁有且只有一份,程序退出之后被釋放,所以不需要對(duì)引用計(jì)數(shù)器操作

-(oneway void)release

{

}

-(instancetype)retain

{

return _instance;

}

慣用法,有經(jīng)驗(yàn)的程序員通過(guò)打印retainCount這個(gè)值可以猜到這是一個(gè)單例

-(NSUInteger)retainCount

{

return MAXFLOAT;

}

  • 1.4 通用版本

(1)有意思的對(duì)話

01 問(wèn):寫(xiě)一份單例代碼在ARC和MRC環(huán)境下都適用?

答:可以使用條件編譯來(lái)判斷當(dāng)前項(xiàng)目環(huán)境是ARC還是MRC

02 問(wèn):條件編譯的代碼呢,么么噠?

答:條件編譯

if

__has_feature(objc_arc)

如果是ARC,那么就執(zhí)行這里的代碼1

else

如果不是ARC,那么就執(zhí)行代理的代碼2

endif

03 問(wèn):在項(xiàng)目里面往往需要實(shí)現(xiàn)很多的單例,比如下載、網(wǎng)絡(luò)請(qǐng)求、音樂(lè)播放等等,弱弱的問(wèn)一句單例可以用繼承嗎?

答:?jiǎn)卫遣豢梢杂美^承的,如果想寫(xiě)一次四處使用,那么推薦親使用帶參數(shù)的宏定義啦!

04 問(wèn):宏定義怎么弄?

答:這個(gè)嘛~~回頭看一眼我的代碼咯,親。

(2)使用帶參數(shù)的宏完成通用版單例模式代碼

01 注意條件編譯的代碼不能包含在宏定義里面

02 宏定義的代碼只需要寫(xiě)一次就好,之后直接拖到項(xiàng)目中用就OK

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一. ARC環(huán)境下的單例模式 單例模式的基本概念單例, 顧名思義, 即在整個(gè)程序中, 某一個(gè)類(lèi)只有唯一一個(gè)實(shí)例, ...
    面糊閱讀 807評(píng)論 0 50
  • (1)單例模式 在程序運(yùn)行過(guò)程,一個(gè)類(lèi)只有一個(gè)實(shí)例 (2)使用場(chǎng)合 在整個(gè)應(yīng)用程序中,共享一份資源(這份資源只需要...
    奧斯卡先生閱讀 367評(píng)論 1 0
  • 導(dǎo)游犬小Q是在北京時(shí)的同事回武漢后搗鼓的一個(gè)項(xiàng)目,4月份的時(shí)候同事發(fā)來(lái)鏈接說(shuō)讓我點(diǎn)評(píng)一下,當(dāng)時(shí)體驗(yàn)了幾天,原定在勞...
    liyishan閱讀 939評(píng)論 0 0
  • 有一種父子之情叫父愛(ài)如山,有一種兄弟情深叫手足情深。 家人常常教導(dǎo)他:是家人你們盡自己的能力幫襯...
    樂(lè)雅霖閱讀 871評(píng)論 0 2
  • 1)把URL分割成幾個(gè)部分:協(xié)議、網(wǎng)絡(luò)地址、資源路徑。其中網(wǎng)絡(luò)地址指示該連接網(wǎng)絡(luò)上哪一臺(tái)計(jì)算機(jī),可以是域名或者IP...
    勃王閱讀 240評(píng)論 0 0

友情鏈接更多精彩內(nèi)容