Как правильно удалить подзаголовок UITableViewCell в коде?

Я пытаюсь создать UITableView с обычными, нестандартными ячейками .subtitle в чистом коде. Однако следующий код никогда не дает мне ячейку с правильным detailTextLabel, вместо этого выбирая ячейку .default.

public var cellIdentifier: String { return "wordsCell" }
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell
    if let newCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) {
        // Always succeeds, so it never goes to the alternative.
        cell = newCell
    }
    else {
        // This is never reached.
        cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellIdentifier)
    }

    let word = wordAtIndexPath(indexPath: indexPath)
    cell.textLabel?.text = word.text
    cell.detailTextLabel?.text = word.subText

    return cell
}

Очевидно, это связано с тем, что dequeueReusableCell(withIdentifier:) на самом деле не возвращает nil, даже если в данный момент нет доступных ячеек. Вместо этого он всегда возвращает .default, если не было создано ни одной ячейки.

Другой вариант, dequeueReusableCell(withIdentifier:for:), также всегда успешен, так что это тоже не сработает.

До сих пор кажется невозможным создать ячейку в стиле, отличном от .default, в чистом коде без Interface Builder, определяющего стиль ячейки-прототипа. Самое близкое, что я могу придумать, это ответ, который замечает ту же проблему. Все остальные вопросы, которые я нашел, также касаются либо проблем с IB, либо пользовательских ячеек.

Кто-нибудь знает, как убрать из очереди ячейку .subtitle для табличного представления без использования Interface Builder?


person SpacyRicochet    schedule 11.01.2017    source источник
comment
Можете ли вы поменять порядок условных выражений?   -  person NRitH    schedule 12.01.2017
comment
@NRitH Вероятно, нет, поскольку мы хотим инициализировать новую ячейку только при необходимости. Если я поменяю местами условные выражения, это всегда инициализирует новую ячейку.   -  person SpacyRicochet    schedule 12.01.2017
comment
Можете ли вы объяснить, чего вы пытаетесь достичь? если в каком случае вам нужны субтитры?   -  person Mat    schedule 12.01.2017
comment
@mat Я всегда хочу субтитры. Но без использования Interface Builder.   -  person SpacyRicochet    schedule 12.01.2017
comment
вы зарегистрировали ячейку в первую очередь в viewDidLoad, используя func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String)   -  person Mat    schedule 12.01.2017
comment
@mat Да, все готово. Ячейка также создается правильно (иначе она вылетит), только без detailTextLabel.   -  person SpacyRicochet    schedule 12.01.2017
comment
Да, это сработает. Меня просто очень смутило, что это вообще не работает. Тем временем @silicon_valley дал ответ в комментарии ниже. Я не должен регистрировать класс (думал, что это необходимо для любого вновь инициализированного UITableViewController).   -  person SpacyRicochet    schedule 12.01.2017
comment
Возможный дубликат dequeueReusableCellWithIdentifier никогда не возвращает nil Комбинированные ответы GayleDDS и Matthias Bauch - это ответ, который вы искали .   -  person Larme    schedule 12.01.2017
comment
Пожалуйста, не регистрируйте какую-либо ячейку, если вы хотите удалить подзаголовок UITableviewCell, потому что он сначала попытается создать ячейку по умолчанию, а затем deque всегда будет возвращать ячейку.   -  person Sourabh Shekhar    schedule 02.12.2020


Ответы (3)


Я думаю, что ваша проблема может заключаться в том, что вы зарегистрировали ячейку в построителе интерфейса (или в viewDidLoad) с тем же именем, что и «cellIdentifier». Вы не должны регистрировать какую-либо ячейку, если хотите использовать ячейку типа субтитров. Зарегистрировав ячейку, он сначала попытается создать эту ячейку (которая не будет ячейкой типа субтитров).

person silicon_valley    schedule 11.01.2017
comment
За исключением оригинальной раскадровки, которую я не трогал, здесь нет файла Interface Builder. Таким образом, нет никаких шансов, что какая-либо ячейка будет иметь этот идентификатор. Я добавил идентификатор ячейки для ясности. - person SpacyRicochet; 12.01.2017
comment
Вы не должны регистрировать какую-либо ячейку, если вы удалите этот код, он должен работать. Зарегистрировав ячейку, он сначала попытается создать эту ячейку (которая не будет ячейкой типа субтитров). - person silicon_valley; 12.01.2017
comment
Это сработало! Можете ли вы создать ответ, чтобы я мог его принять? - person SpacyRicochet; 12.01.2017
comment
Большой! Я обновил ответ, поэтому в нем также упоминается регистрация ячейки в viewDidLoad. - person silicon_valley; 12.01.2017

Я протестировал его, и он работает. Я думал, вы хотите создать подкласс UItableViewCell, но в этом случае вам не нужно регистрировать ячейку.

class TableViewController: UITableViewController {

    let wordAtIndexPath = ["one", "two", "three"]
    let cellId = "cellId"
    override func viewDidLoad() {
        super.viewDidLoad()

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return wordAtIndexPath.count
    }


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

        let word = wordAtIndexPath[indexPath.row]
        let cell: UITableViewCell = {
            guard let cell = tableView.dequeueReusableCell(withIdentifier: cellId) else {
                return UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: cellId)
            }    
            return cell
        }()

        cell.textLabel?.text = "My cell number"
        cell.detailTextLabel?.text = word
        return cell
    }

}

введите здесь описание изображения

person Mat    schedule 11.01.2017
comment
блестящий. Ясно, когда вы видите это, но не очевидно раньше - person brainray; 18.12.2017

Я столкнулся с подобной проблемой и обнаружил, что наиболее элегантным способом было бы создать подкласс UITableViewCell, если вы не используете раскадровки. И удалите ячейку из очереди с этим пользовательским классом.

Два шага:

  1. Создайте ячейку подзаголовка:

     class DetailCell: UITableViewCell {
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
     super.init(style: .subtitle, reuseIdentifier: "reuseIdentifier")
    
    }
    
     required init?(coder: NSCoder) {
     super.init(coder: coder)
     }
    
    }
    
  2. Удалите ячейку из очереди, при желании приведя ее к этому классу как таковому:

     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     guard let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as? DetailCell else {
         return UITableViewCell.init(style: .subtitle, reuseIdentifier: "reuseIdentifier")
     }
    
     // Configure the cell...
     cell.textLabel?.text =  "Title"
     cell.detailTextLabel?.text = "Subtitle"
     return cell
    
     }
    
person Srinath Shah    schedule 14.08.2020