2017-01-13 11 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. Я не понял, почему он получил ошибку. Ваш код выглядит почти так же. Я думаю, было бы лучше, если бы вы удалили «сообщение» из каждого случая. просто напишите «link» и также получите лучшее имя для протокола, хотя теперь не можете думать о хорошем. 2. В то время как ни один из подклассов классов, они все должны соответствовать, чтобы указать, что у них есть метка? Это неправда. 3. И скажите, что я хочу иметь кнопку, я бы просто добавил ее в протокол? 4. Как насчет того, как их расположить? Можно ли ориентировать протокол компоновки? – Honey

0

У вас есть три основных решения.

  1. Повторите cell.text = ... внутри каждого блока. Но это не то, что вы действительно хотите, как указано в вашем вопросе.
  2. У вас есть три пользовательских класса ячеек, которые расширяют общий базовый класс. Определите этот базовый класс для любых общих свойств.
  3. Определите протокол с общими свойствами и совместите каждый из ваших классов ячеек с протоколом.

Для вариантов 2 и 3 вы должны объявить переменную типа base/protocol перед первым оператором 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

 Смежные вопросы

  • Нет связанных вопросов^_^