簡體   English   中英

Objective-C:可以測試靜態類類型的未初始化指針嗎?

[英]Objective-C: can you test an uninitialized pointer for static class type?

我正在嘗試采取以下措施:

在某個對象A中:

UITableVIewController *viewController;
[someObjectB setupView: viewController];

在某些對象B中:

-(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:

  • 先前已初始化對象,並在不將其設置為nil的情況下釋放了該對象,從而在其內存地址處產生了垃圾
  • 傳入由編譯器為您創建的未初始化的自動變量
  • 無論出於何種原因,都將其指向內存中的一些荒謬地址。

*編輯*

添加了一個獲得BAD_EXEC的方案,並且,請參見下面的鏈接,以測試類相等性,尤其是使用isKindOfClass方法時,要isKindOfClass

在Objective-C中,Java的“ instanceof”關鍵字等效於什么?

正如其他人指出的那樣,您要的是不可能的。 當您將變量傳遞給方法時,它僅發送值,而不發送類型。 同樣,運行時也不知道方法中的變量類型。 任何變量類型的處理都由編譯器完成。 運行時只能知道變量保存的對象的類。

或者,如果您可以更改方法的簽名,則可以添加一個參數來指示要創建的對象的類型。 調用方法仍然不需要知道對象的確切類型,只需知道它是否是表視圖控制器即可。 這是一個使用枚舉保存不同類型的示例。

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM