2017-03-08 51 views
0

我已經創建了一個通用視圖控制器來從列表中選擇一個項目,並且我想使用通用委託方法來返回已被選中的項目。我的設置如下:通用協議方法swift無法將類型識別爲類型

class ListPickerViewController<T>: UIViewController { 
    var delegate: ListPickerViewControllerDelegate? 
} 

protocol ListPickerViewControllerDelegate { 
    func listPickerViewControllerDelegate<T>(_ listPickerViewController: ListPickerViewController<T>, selectedItem: T) 
} 

我有,我會用它來填充ListPickerViewController

class MyClass { 
    let a = "sometext" 
} 

在課堂上,我想從我實現方法來獲得所選擇的項目對象的列表和爲選定的項目委託給出列表中對象類型的類型參數。

func listPickerViewControllerDelegate<MyClass>(_ listPickerViewController: ListPickerViewController<MyClass>, selectedItem: MyClass) { 
    print(selectedItem.a) 
} 

但是這並不能編譯!我收到一個錯誤'類型MyClass的值沒有成員'。所以我試着將它轉換成類型

func listPickerViewControllerDelegate<MyClass>(_ listPickerViewController: ListPickerViewController<MyClass>, selectedItem: MyClass) { 
    let selected = selectedItem as! MyClass 
} 

這給出了'強制轉換MyClass到相同類型沒有任何效果'。

出於某種原因,我發現這工作:

typealias MyClassAlias = MyClass 

func listPickerViewControllerDelegate<MyClass>(_ listPickerViewController: ListPickerViewController<MyClass>, selectedItem: MyClass) { 
    let selected = selectedItem as MyClassAlias 
    print(selected.a) // works 
} 

肯定有更好的辦法?或者這是一個快速的缺點?

回答

1

在你的協議實現MyClass委託方法的簽名只是一個泛型參數,你也可以使用TK等,並不一定有一個名爲a成員,因此第編譯錯誤。在

let selected = selectedItem as! MyClass 

它只是強制轉換爲它自己的類型,這可能幾乎任何東西。代表方法的主體中使用的MyClass是函數簽名中使用的泛型參數,而不是具有a成員的MyClass類。

如果使用typealias,那麼它可以在方法的主體中使用並編譯,但只要MyClass通用參數的實際類型更改爲MyClass類以外的其他類型,則該轉換將失敗在運行時。

一般而言,對於每種類型的選定對象,您可能都需要單獨的委託協議實現。我假設視圖控制器的通用參數T是選定的對象類型。您還需要確保類型特定的視圖控制器使用正確的委託實現。

在Swift中,您可以使用關聯的類型來完成此操作。見https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html

視圖控制器和委託協議可能是這樣的:

class ListPickerViewController<T, D : ListPickerViewControllerDelegate> 
    : UIViewController 
    where D.T == T 
    { 
     var delegate: D? 
    ...... 
    } 

    protocol ListPickerViewControllerDelegate { 
     associatedtype T 
     func listPickerViewControllerDelegate<D>(_ controller: 
ListPickerViewController<T, D>, selectedItem: T) where D.T == T 
    } 

用於委託執行與MyClass類型的選擇項可能如下:

class MyDelegateImpl : ListPickerViewControllerDelegate { 
     typealias T = MyClass 

     internal func listPickerViewControllerDelegate<D>(_ controller: 
ListPickerViewController<MyClass, D>, selectedItem: MyClass) 
    where D.T == MyClass { 
      print("In the delegate method!") 
      print("MyClass.a = \(selectedItem.a)") 
     } 
    } 
+0

對不起 - 我的意思是刪除WBSCode並用MyClass替換,現在更新 – mbdavis

+0

MyClass爲什麼提到而不是實際類的解釋是合理的。然後,我們如何能夠迅速告訴這種方法應該是什麼類型?或者 - 它只是一個通用類型,它由你來施展它? – mbdavis

相關問題