2010-04-21 49 views
17

A有一個視圖控制器,它創建一個「下載器」對象,它具有對視圖控制器的引用(作爲委託)。如果下載器成功下載該項目,則回調視圖控制器。只要你停留在視圖上,這工作正常,但如果你在下載完成之前離開,我會得到EXC_BAD_ACCESS。我明白爲什麼會發生這種情況,但有什麼方法可以檢查一個對象是否仍然被分配? 我試圖用delegate != nil[delegate respondsToSelector:]進行測試,但它嗆了。使用委託模式時避免EXC_BAD_ACCESS

if (!self.delegate || ![self.delegate respondsToSelector:@selector(downloadComplete:)]) { 
    // delegate is gone, go away quietly 
     [self autorelease]; 
     return; 
    } 
else { 
    // delegate is still around 
    [self.delegate downloadComplete:result]; 
} 

我知道我可以,

一個)已下載器對象保留視圖控制器

b)中保持在視圖控制器下載程序的陣列,並且設置它們的代表值,以零時我取消分配視圖控制器。

但我不知道是否有一個更簡單的方法,我只是測試委託地址是否包含有效的對象?

+0

如果你可以測試一個地址是否包含一個有效的對象,根據定義,它會,因爲它是有效的訪問它來測試? – 2010-04-21 03:46:46

+1

objective-c有很多抽象...我可以想象一個世界,運行時能夠分辨出一個地址與一個有效對象之間的區別,以及一個被釋放的地址。 – 2010-04-21 04:22:28

回答

10

不,您不能(有用地)「測試地址是否包含有效的對象」。即使你能夠在內存分配系統的內部進行修改,並確定你的地址指向了一個有效的對象,這並不一定意味着它是你之前所指的對象:對象可能已經被釋放,另一個對象在相同的內存地址創建。

保留代表是解決此問題的常用方法。您的選項(b)打破了對象封裝,並且可能存在線程安全問題。

+0

我可以看到蘋果的大部分實現不會保留代表... '@property(nonatomic,assign)id delegate;'我錯誤地應用了設計模式? – 2010-04-21 04:15:08

+0

對於需要在主線程中發生所有交互的UI對象,這可能是正確的,但我認爲您會發現在後臺線程(如NSURLConnection)中執行異步操作的實現將保留其委託。 – 2010-04-21 04:32:58

+6

A **代表**從未保留!只保留**目標**。 – 2010-04-22 11:37:43

1

我只想寫

SEL slc = @selector(theSlc); 
if ([delegate respondsToSelector:slc]) { 
    [delegate performSelector:slc]; 
} 

如果對象是有效的方法將被調用,否則不是。你不必檢查

self.delegate != nil 
+4

你可能是對的,我的'!self.delegate'是多餘的。但是,我確實知道'[delegate respondsToSelector:]'不能保護您免受'EXC_BAD_ACCESS'的攻擊。 試試這個: \t NSObject * obj = [[NSObject alloc] init]; \t [obj release];對於(int i = 0; i <2; i ++){ \t if([objrespondsToSelector:@selector(retainCount)]))NSLog(@「retain count:%i」,[obj retainCount]); \t} – 2010-04-23 22:46:48

1

我遇到了這個問題,因爲我的「下載器」對象給我EXC_BAD_ACCESS。我的解決方案是在我釋放之前取消下載器對象。假設你的下載器對象中使用了NSURLConnection,請調用它的cancel方法。

重要的是要注意,如果NSURLConnection當前沒有下載任何內容,那麼調用cancel將導致崩潰。您需要一些邏輯來檢查下載是否正在進行。

1

我也有代表弱引用的問題,目前我只有一個解決方案,這個問題:使用強參考委託,並手動設置self.delegate =零;我的代碼完成後。這種解決方案適用於異步圖像加載,在這裏你有一些生命週期可見的結局。

27

我剛碰到這個問題就解決了。對於ARC,解決方案是使用weak屬性而不是assign

崩潰而來,是因委託

  1. 有一個assign屬性,
  2. 已釋放。

的解決方案是使用weak屬性,因爲當對象解除分配時,指針WILL設置的nil。因此,當您的代碼在nil上調用respondsToSelector時,Objective C將忽略該調用,而不會崩潰。

在您的代碼中,當您嘗試調用delegate上的respondsToSelector方法時,會得到一個EXC_BAD_ACCESS。這是因爲使用assign屬性的對象在釋放時不會被設置爲nil。 (因此,爲什麼做一個!self.delegaterespondsToSelector之前不會阻止responseToSelector被稱爲解分配的對象,並且仍然崩潰代碼)

如前所述,使用一個代表一個strongassign屬性(如許多人提到)在ARC將導致一個保留週期。所以不要這樣做,你不需要。

+0

除了使用弱點,還有其他的東西需要嗎?例如,在主類中設置'delegate = nil'或設置'id _strong delegate'?我假設我遇到同樣的問題http://stackoverflow.com/questions/24466244/delegate-dont-exist-exc-bad-access/24970685#24970685 – Hexark 2014-07-26 12:51:41

+2

你不應該做任何事情。我讀了你的問題,並注意到你提供了一個響應,指出使用'weak'而不是'assign'來修復崩潰。你還在遇到問題嗎? – 2014-07-29 04:59:05

+0

似乎已經解決了問題:) – Hexark 2014-07-31 05:15:21