Быстрое правильное использование расширения протокола - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь извлечь часть кода для повторного использования.Мой подход использует Protocol и Protocol Extension вместо общего BaseClass.

Я создал ниже protocol и protocol extension

protocol MovieDisplay {

    var collectionView: UICollectionView! { get set }
    var refreshControl: UIRefreshControl! { get set }

}

extension MovieDisplay where Self: UIViewController {

    var refreshControl: UIRefreshControl {
        let rc = UIRefreshControl()
        rc.backgroundColor = .clear
        rc.tintColor = .lightGray
        if #available(iOS 10.0, *) {
            collectionView.refreshControl = rc
        } else {
            // Fallback on earlier versions
            collectionView.addSubview(rc)
        }
        return rc
    }

}

В моем основном классе, который принимает протокол, я объявляю так (используя реализацию по умолчанию refreshcontrol)

class PopularMovieVC: UIViewController, MovieDisplay {

    @IBOutlet weak var collectionView: UICollectionView!

}

Проблема в том, что функция refreshcontrol не работает.Это работает только тогда, когда я явно объявляю переменную refreshcontrol внутри основного класса, преобразовываю расширение в функцию и вызываю его внутри основного класса, как показано ниже:

func setupRefreshControl() {
            refreshControl.backgroundColor = .clear
            refreshControl.tintColor = .lightGray
            if #available(iOS 10.0, *) {
                collectionView.refreshControl = refreshControl
            } else {
                // Fallback on earlier versions
                collectionView.addSubview(refreshControl)
            }
}

Как правильно настроить protocol и protocol extension дляреализация по умолчанию?

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Для вашего протокола требуется gettable и settable refreshControl (который возвращает UIRefreshControl!), но ваша реализация по умолчанию предоставляет только getter (и этот getter возвращает другой тип, UIRefreshControl).Ваша реализация по умолчанию также возвращает различный UIRefreshControl каждый раз, когда к нему обращаются, и изменяет collectionView каждый раз, когда к нему обращаются.Думаю, это не то, что вы имеете в виду.

Как следует из заметок Вадиана, я думаю, что базовый класс - это то, что вам действительно нужно, если вы хотите автоматически изменить collectionView.refreshControl.Соответствие протоколу никогда не должно вызывать неявных изменений в других свойствах, и в большинстве случаев это не может.Представьте, если PopularMovieVC соответствует MovieDisplay в расширении в другом модуле.В лучшем случае это приведет к путанице.

Соответствие протокола расширяет возможности использования типа, такие как добавление новых методов.Это ничего не меняет в самом типе.Если вы хотите что-то изменить в самом типе, вам нужно что-то вроде наследования или компоновки, а не соответствия протокола.


Если вы делаете это немного, я бы не стал делать это с протоколамисюда.Я бы просто создал такие расширения:

extension UIRefreshControl {
    static func makeStandard(attachedTo collectionView: UICollectionView) -> UIRefreshControl {
        let rc = UIRefreshControl()
        rc.backgroundColor = .clear
        rc.tintColor = .lightGray
        if #available(iOS 10.0, *) {
            collectionView.refreshControl = rc
        } else {
            // Fallback on earlier versions
            collectionView.addSubview(rc)
        }
        return rc
    }
}

extension UIActivityIndicatorView {
    static func makeStandard() -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: .gray)
    }
}

Тогда ваш контроллер представления может выглядеть следующим образом:

class MyViewController: UIViewController {
    private var refreshController: UIRefreshControl!
    @IBOutlet var collectionView: UICollectionView!
    let activityIndicator = UIActivityIndicatorView.makeStandard()

    override func viewDidLoad() {
        refreshController = .makeStandard(attachedTo: collectionView)
    }
}

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

0 голосов
/ 28 ноября 2018

Это не работает, потому что вычисляемое свойство не вызывается неявно.

Добавление этой строки в viewDidLoad должно инициализировать элемент управления обновлением

_ = refreshControl

В этом случае я 'я действительно предпочел бы базовый класс

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