2011-08-17 47 views
7

我有時喜歡將IB元素組織爲NSArray,主要是爲了幫助我組織元素。大多數情況下,不同類別的對象會將它們放在同一個陣列中。雖然這組織的一種方便的方式,我似乎無法環繞爲什麼,如果我有一個這樣的數組我的頭:for loops - 忽略對象類型?

NSArray *array = [NSArray arrayWithObjects:((UITextField *)textField), ((UISegmentedController *)segmentedController), nil]; 

爲什麼我收到的時候我的消息「不給選擇迴應」把for循環是這樣的:

for (UITextField *text in array) { 
    [text setText:@""]; 
} 

for循環似乎要傳遞是UITextField類的不是對象。

如果指定數組中的所有對象都通過循環傳遞,那麼聲明對象的類是什麼?

編輯僅供參考,這是我如何處理它的現在:

for (id *object in array) { 
    if ([object isMemberOfClass:[UITextField class]]) { 
     foo(); 
    } else if ([object isMemberOfClass:[UISegmentedController class]) { 
     bar(); 
    } 
} 
+0

'id'已經是一個指針類型。 99.9%的時間,你想使用普通的'id'類型,而不是指向'id *'的指針。 –

回答

10

當你

for (UITextField *text in... 

從數組對象的指針被強制轉換爲*的UITextField型 - 因此,如果對象實際上不是的UITextField,如果你嘗試調用的怪異的東西種種可能發生UITextField方法。

因此,而不是使用id型(無*需要,順便說一句):

for (id obj in array) 

你做然後檢查類型和調用適當的方法。或者,過濾陣列以獲得某種類型的對象,然後再去雖然只有類型:

for (UITextField* text in [array filteredArrayUsingPredicate:...]) 

編輯:這裏是如何打造一流的過濾謂詞:

Is it possible to filter an NSArray by class?

+0

對象不會轉換爲新類型 - 指針是。在分派消息時,指針的類型並不重要。如果你願意,你可以使用'NSWindow *'類型的指針將'-appendString:'發送給一個對象,只要指針指向一個NSMutableString實例就可以工作。 (你可能會得到一個編譯器警告,但它會起作用。)但是,如果指針指向一個窗口,那麼當然在運行時會出現一個錯誤,除非你採取措施來阻止它。 – Caleb

+0

你當然是對的,我相應地修改了我的答案。 – SVD

+0

需要編輯的部分是「如果對象實際上不是UITextField,可能會發生各種奇怪的事情......」。如果該對象實際上不是UITextField,則會得到未實現的選擇器異常。 – Caleb

5

什麼是聲明對象類的點,如果指定數組中的所有對象傳遞通過循環?

類名稱就在那裏讓編譯器知道它應該找到什麼。這允許它試圖找出它應該期望你調用什麼方法,以及如何處理對象。這與將int傳遞給需要float的方法的想法是一樣的。該方法不會忽略整數 - 它假設您傳遞的是正確的類型。你只是給這個構造更多的信用比它的到期:

for (UITextField *text in array) 

它只是沒有這種功能。您現在如何處理它是正確的方法。

0

確定當你運行那個代碼你沒有收到錯誤? 「不響應選擇器」消息是運行時錯誤,而不是編譯時錯誤。編譯器不知道數組中的對象是否實現了-setText:,但是當您實際將該消息發送到UISegmentedControl的實例時,您肯定會收到錯誤。

另一種可能性是,你有一個名爲UISegmentedController的課程,它有一個-setText:方法。實現多部分條形圖用戶界面小部件的類的名稱是UISegmentedControl。所以要麼你顯示的代碼不是真正的,經過測試的代碼,或者你有一個我們不知道的類。