2017-06-12 100 views
0

我一直在嘗試做一些代碼,允許用戶「附加」到特定單元格的特定模型。我打算通過協議和associatedType方法來做到這一點。如何在Swift中測試與associatedType協議的一致性?

這裏的計劃:

細胞符合MTZSectionRowConfigurable時,他們可以顯示數據,但他們不一定需要:

public protocol MTZSectionRowConfigurable { 
    associatedtype T: MTZSectionRowModel 
    func configure(with model: T?) 
} 

通過使用typealias,它們允許用戶定義哪種模式他們「再要代表:

class SignOutCell: UITableViewCell, MTZSectionRowConfigurable { 
    typealias T = SignOutModel 
    var redLabel: UILabel! 
    // ... 
    func configure(with model: SignOutCellModel?) { 
     self.redLabel.text = model?.text 
    } 
} 

模型只是順應MTZSectionRowModel明確聲明補償atibility。

但是,由於表示模型是可選的,我需要在調用configure方法之前檢查單元以支持它們。這是對cellForRowAtIndexPath:

if let cell = cell as? MTZSectionRowConfigurable { 
    cell.configure(with: sectionRow.model) 
} 

完成。在上述例子中,是sectionRow.modelMTZSectionRowModel?類型。

以上代碼不能編譯。它產生臭名昭著:

「協議‘MTZSectionRowConfigurable’只能作爲一種通用的約束,因爲它具有自我或相關類型的要求」

我試圖檢查電池也迴應#selector,但不幸的是,同樣的錯誤適用。

有什麼辦法可以使這段代碼有效嗎?我錯過了什麼嗎?我可以放棄associatedType,在每個單元格上實施廣泛的方法MTZSectionRowModel,但是然後我需要在每個實現內部施放,但在我看來這不是最佳解決方案。

回答

0

我明白你正在嘗試做什麼,我自己也做過。然而,這比現在所做的要多一點。你在Andy Matuschak的gist中找到答案。

爲了與SO答案的最佳實踐保持一致,我將解釋其原因。讓我們從最後開始。 cellForRow...這是objc func,它需要返回UITableViewCell?。所以我們已經知道,在某些時候我們會丟失類型信息(例如,你的SignOutCell類不是返回的,它是它的超類,UITableViewCell)。鑑於我們最終得到了UITableViewCell,我們如何才能做到您想做的事情並生成SignOutCell並對其進行配置?答案在於定義安迪在他的要點(在此鏈接)中描述的CellFactory中的完成處理程序。然後他使用bridgedDataSource將一種細胞類型轉換爲另一種細胞類型。我定製了他的代碼,以允許根據輸入參數返回4種不同類型的單元格。例如,我的UITableViewController可能包含4個UITableViewCell項目,每個項目的佈局和數據模型都可能非常不同。我會參數CellFactory接受enum CellType,我預先定義了4種類型。然後,在細胞工廠內,我使用switch cellType來設置細胞(此時我有細胞和模型數據的所有類型信息)。最後,bridgedDataSource返回良性UITableViewCell這使UIKit非常高興,它具有我需要的所有品質。 Andy所依賴的基本概念之一是分解。我相信他在某處有一個YouTube視頻,或者在他的網站上有一段視頻,他可以在這裏看到。我會看看如果我能找到它並更新答案。