国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

【iOS】Objective-C簡約而不簡單的單例模式

2019-11-14 20:04:30
字體:
供稿:網(wǎng)友

前些日子在項(xiàng)目中因?yàn)檎`用了單例而導(dǎo)致了一系列問題。原來在objective-c中的單例并沒有java或者C#那么簡單的實(shí)現(xiàn),這里記錄下;

 

問題是這樣被發(fā)現(xiàn)的,在對于一個(gè)UIViewController進(jìn)行pop時(shí)并沒有被dealloc,導(dǎo)致了內(nèi)存泄露。問題代碼類似于下面的:

 

C代碼  收藏代碼
  1. //LWChatViewController.h  
  2. @interface LWChatViewController : LWTableViewController <LWObjSelectViewDelegate>{  
  3.     UINavigationController *root;  
  4. }  
  5. @PRoperty (nonatomic, retain) UINavigationController *root;  
  6. @end  
  7.   
  8. //LWChatViewController.m  
  9. - (void)viewDidLoad  
  10. {  
  11.     [super viewDidLoad];  
  12.     // Do any additional setup after loading the view from its nib.  
  13.     self.root = LWNavigationController;  
  14. }  

 

  這里的LWNavigationController是一個(gè)頂級的單例。

問題就出在@property (nonatomic, retain) 這里root居然是一個(gè)retain的對象指針,在這里retain一個(gè)static的單例將導(dǎo)致內(nèi)存泄露,MD,這個(gè)bug找的我好久。。。

 

 

解決這個(gè)問題其實(shí)很簡單,把retain改為assign就行了,但這樣如果在協(xié)作編程的時(shí)候如果別人不在意這個(gè)是單例直接進(jìn)行常規(guī)操作的話會帶來很大的問題。

 

 

繼續(xù),我們來從根本上解決這個(gè)問題。

我們需要重寫一些方法:

 

C代碼  收藏代碼
  1. - (id)retain  
  2. {  
  3.     return self;  
  4. }  
  5.   
  6. - (NSUInteger) retainCount  
  7. {  
  8.     return NSUIntegerMax;  
  9. }  
  10.   
  11. - (void) release  
  12. {  
  13.     // do nothing  
  14. }  
  15.   
  16. - (id)autorelease  
  17. {  
  18.     return self;  
  19. }  

在retain和autorelease什么都不做只是返回自己,release的時(shí)候啥都不做,將retainCount設(shè)為UInt的極大值。

 

其次是關(guān)于線程安全的實(shí)現(xiàn),這些java都有明確的代碼模式:

關(guān)于線程安全的單例,這篇外文 http://www.numbergrinder.com/2008/12/patterns-in-objective-c-singleton-pattern/ 有比較詳細(xì)的解釋。

 

 

Java代碼  收藏代碼
  1. @implementation Singleton  
  2. static Singleton *instance = nil;  
  3. + (Singleton *)sharedInstance  {  
  4.    @synchronized(self)   
  5.    {  
  6.         if(!instance) {  
  7.            instance = [[Singleton alloc] init];  
  8.         }  
  9.     }  
  10.    
  11.     return instance;  
  12. }  
  13.    
  14. @end  

 

嗯,這樣就可以實(shí)現(xiàn)線程安全的單例了,當(dāng)然這里也可以用NSLock實(shí)例去實(shí)現(xiàn)。

 

最后趁機(jī)深入了下單例模式,發(fā)現(xiàn)instance = [[Singleton alloc] init];這樣的語句是有問題的,它不能以其他方式發(fā)起分配內(nèi)存去實(shí)例化對象,可能會造成多個(gè)實(shí)例被創(chuàng)建。(見《pro objective-c design patterns for ios》 )

該書推薦用

 

C代碼  收藏代碼
  1. instance = [[super allocWithZone:NULL] init];  

 

傳NULL到allocWithZone其實(shí)等同與alloc默認(rèn)方法,但注意這里是調(diào)用super的alloc;

 

本類的allocWithZone被改寫為:

 

C代碼  收藏代碼
  1. + (id)allocWithZone:(NSZone *)zone  
  2. {  
  3.       return [self sharedInstance];  
  4. }  
  5.   
  6. - (id)copyWithZone:(NSZone *)zone  
  7. {  
  8.       return self;  
  9. }  

 同時(shí)深拷貝也直接重載阻止掉多個(gè)實(shí)例的出現(xiàn)。上面的allocWithZone的重載使得這個(gè)單例也能夠直接用alloc或是allocWithZone進(jìn)行初始化,但返回的一如既往是那個(gè)static的實(shí)例。

 

這樣一個(gè)objective-c的單例模式才算是完整了。。。啦啦啦,每月末一博寫完,睡覺去了。。。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 花垣县| 汉源县| 广灵县| 舞钢市| 连州市| 铜川市| 双流县| 上高县| 灵石县| 平罗县| 宝山区| 西华县| 监利县| 黔南| 会昌县| 当雄县| 永昌县| 安宁市| 石景山区| 黄浦区| 昌吉市| 乌兰察布市| 海口市| 武陟县| 凌海市| 东乡族自治县| 金塔县| 文昌市| 小金县| 外汇| 绵阳市| 高清| 娱乐| 海原县| 安顺市| 芒康县| 仪征市| 江达县| 宣化县| 衡阳县| 象山县|