проблемы, чтобы получить правильный reuseIdentifier - PullRequest
0 голосов
/ 01 июня 2019

Я создал расширение для UITableView и хочу получить правильный reuseIdentifier во время выполнения, но я не могу:

extension UITableView {

func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T {

    let s = T.reuseIdentifier

Переменная «s» всегда содержит «UITableViewCell», а не имя, которое я указывал в раскадровке.

Ответы [ 3 ]

1 голос
/ 01 июня 2019

Неважно, весь метод

extension UITableView {

    func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T {
        return self.dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as! T 
    }
}

должен работать правильно.


Альтернативой является расширение протокола и методы static, просто примите протокол в подклассах UITableViewCell.

protocol Reusable {
    associatedtype CellType : UITableViewCell = Self

    static var cellIdentifier : String { get }
    static func dequeueReusableCell(in tableView : UITableView, for indexPath: IndexPath) -> CellType
}

extension Reusable where Self : UITableViewCell {

    static var cellIdentifier : String {
        return String(describing: Self.self)
    }

    static func dequeueReusableCell(in tableView : UITableView, for indexPath: IndexPath) -> CellType {
        return tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! CellType
    }
}

И назовите это

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = MyTableViewCell.dequeueReusableCell(in: tableView, for: indexPath)
...
0 голосов
/ 01 июня 2019

Ваше расширение никогда не будет работать, потому что

  • Свойство reuseIdentifier не устанавливается до тех пор, пока оно не будет удалено ( Source ).
  • Дженерики не работают так, как вы этого хотите. Чтобы понять, что T - это ваш тип ячейки, вам нужно привести его к этому типу вручную. Лучшим решением было бы преобразовать это расширение в UITableView. https://gist.github.com/OscarApeland/80d1b1dd9f7534ffa0dc8c7173989ef6
0 голосов
/ 01 июня 2019

Мой способ справиться с этим заключается в следующем.

Я создаю протокол, который объявляет тип загружаемым из пера:

//  MARK: Nib Loadable
public protocol NibLoadable {
    /// The name of the .xib file in which this view is defined.
    static var nibName: String { get }
}
//  MARK: Nib Loadable Convenience
public extension NibLoadable where Self: UIView {
    static var nibName: String { return NSStringFromClass(self).components(separatedBy: ".").last! }
}

Я создаю другой тип, который объявляет тип как повторно используемый и автоматически согласовывает ячейки представления таблицы и коллекции:

//  MARK: Reusable View
/**
Indicates that a view can be reused provided it matches a provided identifier.
*/
public protocol ReusableView: class {
    /// The identifier for this type of reusable view.
    static var defaultReuseIdentifier: String { get }
}
//  MARK: Reusable View Convenience
public extension ReusableView where Self: UIView {
    static var defaultReuseIdentifier: String { return NSStringFromClass(self).components(separatedBy: ".").last! }
}
extension UICollectionViewCell: ReusableView { }
extension UITableViewCell: ReusableView { }

Затем я создаю простой способ регистрации такой ячейки:

//  MARK: Registration
public extension UICollectionView {
    func register<T: UICollectionViewCell>(_: T.Type) {
        register(T.self, forCellWithReuseIdentifier: T.defaultReuseIdentifier)
    }
    func register<T: UICollectionViewCell>(_: T.Type) where T: NibLoadable {
        let bundle = Bundle(for: T.self)
        let nib = UINib(nibName: T.nibName, bundle: bundle)
        register(nib, forCellWithReuseIdentifier: T.defaultReuseIdentifier)
    }
}
public extension UITableView {
    func register<T: UITableViewCell>(_: T.Type) {
        register(T.self, forCellReuseIdentifier: T.defaultReuseIdentifier)
    }
    func register<T: UITableViewCell>(_: T.Type) where T: NibLoadable {
        let bundle = Bundle(for: T.self)
        let nib = UINib(nibName: T.nibName, bundle: bundle)
        register(nib, forCellReuseIdentifier: T.defaultReuseIdentifier)
    }
}

Наконец-то у меня есть удобный способ удаления этих ячеек:

//  MARK: Dequeuing
public extension UICollectionView {
    func dequeue<T: UICollectionViewCell>(for indexPath: IndexPath) -> T {
        guard let cell = dequeueReusableCell(withReuseIdentifier: T.defaultReuseIdentifier, for: indexPath) as? T else {
            fatalError("Could not dequeue cell with identifier: \(T.defaultReuseIdentifier)")
        }
        return cell
    }
}
public extension UITableView {
    func dequeue<T: UITableViewCell>(for indexPath: IndexPath) -> T {
        guard let cell = dequeueReusableCell(withIdentifier: T.defaultReuseIdentifier, for: indexPath) as? T else {
            fatalError("Could not dequeue cell with identifier: \(T.defaultReuseIdentifier)")
        }
        return cell
    }
}

При использовании приложения я делаю идентификатор повторного использования для любой ячейки с именем класса. Затем я изменяю ячейку следующим образом:

extension PersonalDetailTableViewCell: NibLoadable { }

Владелец табличного представления зарегистрирует ячейку в viewDidLoad():

tableView.register(PersonalDetailTableViewCell.self)

Внутри функции cellForRow я удалю должным образом:

let cell: PersonalDetailTableViewCell = tableView.dequeue(for: indexPath)

Я сделал это доступным в гисте здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...