[英]Objective-C: can you test an uninitialized pointer for static class type?
我正在嘗試采取以下措施:
UITableVIewController *viewController;
[someObjectB setupView: viewController];
-(void) setupView:(UIViewController*)view
{
if the pointer passed in is of type UITableViewController then ...
say, for instance with: [[view class] isKindOfClass [UITableViewController class]]
or: [view isKindOfClass [UITableViewController class]]
}
但是,我有兩個問題:首先,參數作為UIViewController的超類進入了B中的方法,它是UITableView的超類(我正在這樣做,因為該方法還將配置其他類型的視圖控制器)。 所以我想知道,如果我將UITableViewController傳遞給類型為UIViewController的方法參數,isKindOfClass仍然可以進行動態綁定嗎? 也就是說,運行時檢查內容的類型,而不管指針的靜態類型如何?
其次,請注意,在將對象A傳遞給B之前,我沒有初始化它。我實際上希望B對其進行初始化。 但是,然后購買的問題變成了,如何在未初始化的指針上測試靜態指針類型? 也就是說,在B內部:[view isKindOfClass [UITableViewController class]]給我一個BAD_EXEC。 我的猜測,因為我顯然正在嘗試訪問jul指針。 那么有沒有一種方法仍然可以基於指針靜態類型聲明進行測試?
讓我用更具體的措辭來重新說明問題的這一部分:我希望obj B創建一個UITableViewController類型的變量,將其傳遞給A並讓A意識到已經為它提供了一個指向UITableViewController的指針,以便它實際上可以將該指針初始化為UITableViewController的特定子類,然后obj B將現在已初始化的對象傳遞給其他對象。
我想這樣做的原因是以下情形:我有一個基於navigationController的應用程序。 它具有一個帶有按鈕的根控制器,並根據所按下的按鈕,該根控制器實例化並推送數據庫中不同表的表控制器,然后,當單擊這些表的一行時,這些表實例化並推送詳細視圖控制器。
到目前為止,一切都很好,但是由於項目的性質,我想讓整個Navigationcontroller實例化-推鏈與一個數據庫無關,並且表和詳細視圖控制器實際上是UITableViewController和UIViewController的特定子類, 分別。
這意味着流程將是:
1-單擊時,根控制器將通用UIViewController傳遞給我的自定義主控制器。
2-該主控制器意識到已將其傳遞給通用表,將其初始化為我定義的特定子類,並做了一些事情為它提供來自sql數據庫的數據。
3-根控制器不關心通用UIViewController是表還是UIViewController的子類,而只是將其推送到navigationController。
同樣的想法是,那么我不需要在根控制器中包含表子類的標頭。 只有定制的主控制器才知道這些。
因此,歸根結底,我看到的方法是能夠確定要傳遞的指針的類型,而不管該指針是nil,指向垃圾還是指向實際對象。 含義:
UIVIewController *一個->靜態類型聲明,在編譯時確定。
a = [UIVIewController alloc的某些子類] init]; ->指針內容的動態類型,在運行時確定,可能是通過跟蹤激活記錄中的鏈接來確定的。類似於C ++中的“虛擬”
與C一樣,Objective-C是一種按值傳遞的語言。您無法使用其中的代碼在對象A中初始化viewController
。 對其進行初始化,並將其地址傳遞給setupView:
然后根據需要對其進行初始化:
UITableVIewController *viewController = nil;
[someObjectB setupView:&viewController];
和:
-(void)setupView:(UIViewController**)view
{
if (*view == nil)
// initialize it - *view = [[blah alloc] init] or whatever
else
...
}
回答第一個問題,是的-目標C將在運行時(動態)確定對象的類類型。 在回答第二個問題時,分派給nil對象的任何方法調用都將被忽略,因此您的所有類檢查都將無法正常進行。 但是,除非您執行以下操作,否則不應獲得BAD_EXEC:
*編輯*
添加了一個獲得BAD_EXEC的方案,並且,請參見下面的鏈接,以測試類相等性,尤其是使用isKindOfClass
方法時,要isKindOfClass
。
正如其他人指出的那樣,您要的是不可能的。 當您將變量傳遞給方法時,它僅發送值,而不發送類型。 同樣,運行時也不知道方法中的變量類型。 任何變量類型的處理都由編譯器完成。 運行時只能知道變量保存的對象的類。
或者,如果您可以更改方法的簽名,則可以添加一個參數來指示要創建的對象的類型。 調用方法仍然不需要知道對象的確切類型,只需知道它是否是表視圖控制器即可。 這是一個使用枚舉保存不同類型的示例。
// header
enum ViewControllerType {
ViewControllerNormal = 0,
ViewControllerTableView
};
- (void)setupView:(UIViewController **)view ofType:(enum ViewControllerType)type;
// implementation
- (void)setupView:(UIViewController **)view ofType:(enum ViewControllerType)type {
if(!view) {
NSLog(@"setupView:ofType: received nil pointer");
return;
}
switch(type) {
case ViewControllerNormal:
// create normal UIViewController type
break;
case ViewControllerTableView:
// create UITableViewController type
break;
default:
NSLog(@"setupView:ofType: received unknown type: %i",type);
return;
}
}
像這樣使用:
UIViewController *view;
[creatorObject setupView:&view ofType:ViewControllerNormal];
// or
UITableViewController *tableView;
[creatorObject setupView:&tableView ofType:ViewControllerTableView];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.