標籤:style blog io color 使用 sp on 檔案 div
用GCD寫Objective-c的單例模式和C#有比較大的區別
聲明h檔案
#import <Foundation/Foundation.h>@interface me : NSObject<NSObject>@property (nonatomic) NSInteger age;+(instancetype)makeme;@end
instancetype和id的區別
instancetype返回的是該執行個體類型,而id返回的是未知類型
①instancetype可以返回和方法所在類相同類型的對象,id只能返回未知類型的對象,便於編寫調試
②instancetype只能作為傳回值,不能像id那樣作為參數
具體原理是利用dispatch_once 來建立一個單一實例,因為該函數在程式生命週期內只運行一次
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
第一個參數是檢查後面第二個參數所代表的代碼塊是否被調用的謂詞,第二個參數是在整個應用程式中只會被調用一次的代碼塊。
不過眾多的dispath_once版本中我認為這個下面這個還不錯
#import "me.h"static me *myself;@implementation me+(id)allocWithZone:(struct _NSZone *)zone{ static dispatch_once_t onetaken; dispatch_once(&onetaken,^{ myself=[super allocWithZone:zone]; }); return myself;}+(instancetype)makeme{ static dispatch_once_t onetaken; dispatch_once(&onetaken, ^{ myself=[[self alloc]init]; }); return myself;}-(id)copy{ return myself;}
這裡我們需要弄清楚allocWithZone方法。oc對象的初始化是alloc和init配合。alloc劃分記憶體,init為執行個體配置參數變數,如對比下面代碼,我刪除了allocWithZone方法
#import "me.h"static me *myself;@implementation me+(instancetype)makeme{ static dispatch_once_t onetaken; dispatch_once(&onetaken, ^{ myself=[[self alloc]init]; }); return myself;}
下面的例子是如果你如果用了
me *myself=[[me alloc]init];
me *myself1=[me makeme];
你會發現你獲得了一個新的執行個體,。。。myself和myself1是不同的,這貨不是單一實例。。。當然因為我們用的alloc+init方法已經繞過了dispath_once的方法,單一實例也就失效了
這意味著我們需要從執行個體初始化的地方開始
查看allocWithZone方法的介紹是
使用alloc方法初始化一個類的執行個體的時候,預設是調用了 allocWithZone 的方法。於是我們可以把這個也堵上就即使使用者使用alloc +init 也不會產生新的執行個體。
Objective-c 單例模式