Как заставить класс соответствовать протоколу в Swift?

121

в Objective-C:

@interface CustomDataSource : NSObject <UITableViewDataSource>

@end

в Swift:

class CustomDataSource : UITableViewDataSource {

}

Однако появится сообщение об ошибке:

  1. Тип CellDatasDataSource не соответствует протоколу NSObjectProtocol.
  2. Тип CellDatasDataSource не соответствует протоколу UITableViewDataSource

Каким должен быть правильный путь?

Юйсюань Фу
источник
1
Имя класса в сообщениях об ошибках не соответствует указанному вами коду?
Мэтт Гибсон
2
Классы Swift по умолчанию не наследуются от NSObject. Они являются собственными базовыми классами, если не указано иное.
Тим

Ответы:

251

Тип CellDatasDataSource не соответствует протоколу NSObjectProtocol.

Вы должны сделать свой класс унаследованным от, NSObjectчтобы соответствовать NSObjectProtocol. Классы Vanilla Swift - нет. Но многие части UIKitожидают NSObjectгодовщины.

class CustomDataSource : NSObject, UITableViewDataSource {

}

Но это:

Тип CellDatasDataSource не соответствует протоколу UITableViewDataSource

Ожидается. Вы будете получать сообщение об ошибке, пока ваш класс не реализует все необходимые методы протокола.

Так что кодируйте :)

Алекс Уэйн
источник
Спасибо @Alex; вы спасли мне день, так как я довольно долго боролся за то, чтобы мой класс Swift соответствовал протоколу UICollectionViewDataSource. Добавление наследования NSObject в мой класс решило эту проблему!
iOS-Coder
1
Я единственный, кто считает, что предупреждения компиляции было достаточно?
Magoo
@Magoo Вы, конечно, имели в виду недостаточное. «Не соответствует протоколу» для меня не означает «унаследовать от NSObject».
Рой Фальк,
@RoyFalk Я имею в виду, что предупреждения компиляции было достаточно из-за ошибки ... Возможно, вам не нужно реализовывать весь протокол во всех случаях, и, возможно, вы захотите построить до этого ... это не имеет большого значения, но кажется немного ненужным ,
Magoo
0

Класс должен унаследовать от родительского класса, прежде чем соответствовать протоколу. В основном это можно сделать двумя способами.

Один из способов - сделать так, чтобы ваш класс унаследовал от них NSObjectи соответствовал им UITableViewDataSource. Теперь, если вы хотите изменить функции в протоколе, вам нужно добавить ключевое слово overrideперед вызовом функции, например

class CustomDataSource : NSObject, UITableViewDataSource {

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        // Configure the cell...

        return cell
    }
}

Однако это иногда делает ваш код беспорядочным, потому что у вас может быть много протоколов, которым нужно соответствовать, и каждый протокол может иметь несколько функций делегирования. В этой ситуации вы можете отделить код, соответствующий протоколу, от основного класса, используя extension, и вам не нужно добавлять overrideключевое слово в расширение. Таким образом, эквивалент приведенного выше кода будет

class CustomDataSource : NSObject{
    // Configure the object...
}

extension CustomDataSource: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        // Configure the cell...

        return cell
    }
}
Fangming
источник
0

Xcode 9 помогает реализовать все обязательные методы Swift Datasource & Delegates.

Вот пример UITableViewDataSource:

Показывает предупреждение / подсказку для реализации обязательных методов:

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

Нажмите кнопку «Исправить», все обязательные методы будут добавлены в код:

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

Krunal
источник