2017-01-13 36 views
1

我有三種不同類型的自定義UITableCells。我有一個if語句來設置它們:如何使用if語句將變量的類型設置爲特定類型的自定義tableCell?

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {     
    if somePosts[indexPath.row].typeOfPost == .linkPost { 
     let cell: LinkTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell 

    } else if somePosts[indexPath.row].typeOfPost == .picturePost { 
     let cell: PictureTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell 

    } else if somePosts[indexPath.row].typeOfPost == .textPost { 
     let cell: TextTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell 


    } else { 
     print("Type of post is not link, picture, or text") 
    } 
} 

每個自定義單元格都有類似的標籤,例如標題和時間。我想設置使用相同的代碼行這些標籤,如:

cell.titleLabel.text = "Some title here" 

然而,在這個例子中,我得到一個錯誤,說我使用的是未解決的標識符「細胞」,顯然是因爲我的變量被宣佈爲非全球性的。有沒有辦法解決這個問題,因爲swift是強類型的?謝謝!

+2

不相關,但從數據源數組中檢索三次類型是不必要的昂貴。你應該使用switch語句'switch somePosts [indexPath.row] .typeOfPost {case .linkPost ...' – vadian

+0

謝謝,這很有幫助。我對此很新,所以任何建議總是讚賞 – SomeGuy

+0

這裏有很多重複的代碼。停止瘋狂。 – Alexander

回答

2

制定一個協議,您的TableViewCell類擴展,並將cell作爲該類型的變量存儲。

protocol MyTableViewCell { 
    var titleLabel: UILabel { get } 
    // ... 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let identifier: String 

    switch somePosts[indexPath.row].typeOfPost { 
     case .linkPost: identifier = "linkTableViewCell" 
     case .picturePost: identifier = "pictureTableViewCell" 
     case .textPost: identifier = "textTableViewCell" 
     default: fatalError("Type of post is not link, picture, or text") 
    } 

    guard let cell = self.tableView.dequeueReusableCell(withIdentifier: identifier) as? MyTableViewCell else { 
     fatalError("Cell isn't castable to MyTableViewCell") 
    } 

    cell.titleLabel.text = "Some title here" 
    // ... 
} 
+0

好吧,我真的很吮吸這個,我提前道歉。它在第二個fatalError行上不斷崩潰。不知道爲什麼......所有的標籤都必須是一樣的嗎?有些是不同的,有些在每個自定義單元中都是相同的。我試圖這樣做,所以相同的那些不需要多次輸入。 – SomeGuy

+0

@SomeGuy你忘了讓現有的類符合這個新協議嗎? – Alexander

+0

0.我不明白他爲什麼得到錯誤。你的代碼看起來幾乎相同1.我認爲如果你從每個案例中刪除'post'會更好。只是寫'鏈接',也有一個更好的名稱爲協議,但現在不能想到一個好的。 2.雖然沒有一個類是子類,它們都應該符合表示它們有標籤嗎?這不是POP的問題。 3.說我想要一個按鈕,我只是將它添加到協議中? 4.如何定位它們?有沒有辦法讓佈局協議導向? – Honey

0

您有三個基本解決方案。

  1. 在每個塊內重複cell.text = ...。但這不是你真正想要的,正如你的問題所述。
  2. 您的三個自定義單元類都擴展了一個公共基類。讓這個基類定義任何公共屬性。
  3. 定義一個具有公共屬性的協議,並讓您的每個自定義單元類符合該協議。

對於選項2和3,您將聲明第一個if語句之前的基本/協議類型的變量。然後在整個if/else塊之後,可以分配任何常用屬性。

如果您需要更新任何單元格類型特定的屬性,那麼也可以在相應的塊內執行此操作。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    var cell: BaseTableViewCell? 
    if somePosts[indexPath.row].typeOfPost == .linkPost { 
     cell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell 
    } else if somePosts[indexPath.row].typeOfPost == .picturePost { 
     cell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell 
    } else if somePosts[indexPath.row].typeOfPost == .textPost { 
     cell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell 
    } else { 
     print("Type of post is not link, picture, or text") 
    } 

    if let cell = cell { 
     cell.commonProperty = ... 

     return cell 
    } else { 
     return nil // this shouldn't happen but if it does, you have a bug to fix 
    } 
} 
0

如果每個子類都有自己的titleLabel屬性,則需要使它們全都符合協議。我們稱之爲ConfigurableCell

protocol ConfigurableCell { 
    var titleLabel: UILabel { get set } 
} 

然後,您可以初始化你的細胞都以同樣的方式,而是把他們定義爲一個ConfigurableCell

var cell: ConfigurableCell? = nil // not set yet 
if somePosts[indexPath.row].typeOfPost == .linkPost { 
    cell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell 
} else if somePosts[indexPath.row].typeOfPost == .picturePost { 
    cell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell 
} else if somePosts[indexPath.row].typeOfPost == .textPost { 
    cell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell 
} 

guard let cell = cell else { 
    // how to handle this error case is up to you 
    print("Type of post is not link, picture, or text") 
    return UITableViewCell()  
} 

// now, cell is a ConfigurableCell with a titleLabel property, regardless of class 
cell.titleLabel.text = "Some title" 

當然,UITableViewCell確實有一個內置的textLabel屬性,你可以嘗試在您的單元類中使用,然後協議將不是必需的,因爲該屬性在UITableViewCell

+0

嘿,我是新手,所以如果這是一個愚蠢的問題,不要殺了我,但是當我聲明協議時,我得到一個錯誤:「協議中的屬性必須顯式{ get}或{get set}說明符。 – SomeGuy

+0

啊對了。請參閱編輯。 – Connor

+0

好了,修正了那個錯誤,但現在我得到了「無法指定類型」LinkTableViewCell「的值(以及所有其他類型的單元格)以鍵入ConfigurableCell?」 – SomeGuy

相關問題