Как протолкнуть UIViewController программно из "didSelectItemAt" в UICollectionView (используя отдельные файлы)? - PullRequest
1 голос
/ 05 октября 2019

У меня UICollectionView настроен в отдельном файле swift, который отображается на HomeViewController. Я хочу нажать DetailViewController, когда ячейка представления коллекции выбрана. Я хочу сделать это программно, без раскадровок. Я всегда выдвигал ViewControllers с помощью «navigationController.pushViewController (vc, animated: true)», но я не могу получить доступ к navigationController из функции «didSelectItemAt» UICollectionView. Если это имеет значение, у меня есть пользовательский UICollectionViewCell, настроенный и используемый для ячеек.

Как я могу заставить эту работу? CollectionView отображается правильно, и когда я выбираю ячейку, я знаю, что didSelectItemAt запускается, поскольку мое выражение печати «Выбрал элемент в ...» отображается в консоли.

После нескольких часов поисков я не могу этого понять. Я все еще изучаю структуру MVC, поэтому у меня может быть фундаментальный недостаток в том, как все настроено. Я также видел, что мне может понадобиться создать собственный делегат, чтобы справиться с этим, но я чувствую, что мне не хватает чего-то более простого, так как функция didSelectItemAt прямо здесь.

Вот соответствующий код из моего файла Swift UICollectionView:

class HomeDataController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        print("Did select item at...")
        // this is where I am trying to push the DetailViewController

    }
}

Вот мой HomeViewController:

class HomeViewController: UIViewController {

    let collectionView: UICollectionView = {
            let layout = UICollectionViewFlowLayout()
            layout.scrollDirection = .vertical
            layout.minimumLineSpacing = 30
            layout.sectionInset.top = 20
            layout.sectionInset.bottom = 20

            let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
            cv.translatesAutoresizingMaskIntoConstraints = false
            cv.backgroundColor = UIColor(named: "background")
            cv.register(HomeCustomCell.self, forCellWithReuseIdentifier: "homeCell")
            return cv
        }()

    let dataController: HomeDataController = {
        let dataController = HomeDataController()
        return dataController
    }()


    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.dataSource = self.dataController
        collectionView.delegate = self.dataController

        view.addSubview(collectionView)
    }
}

1 Ответ

1 голос
/ 05 октября 2019
class HomeViewController: UIViewController {

let collectionView: UICollectionView = {
            let layout = UICollectionViewFlowLayout()
            layout.scrollDirection = .vertical
            layout.minimumLineSpacing = 30
            layout.sectionInset.top = 20
            layout.sectionInset.bottom = 20

            let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
            cv.translatesAutoresizingMaskIntoConstraints = false
            cv.backgroundColor = UIColor(named: "background")
            cv.register(HomeCustomCell.self, forCellWithReuseIdentifier: "homeCell")
            return cv
        }()

    lazy var dataController: HomeDataController = {
        let dataController = HomeDataController(controller: self)
        dataController.didSelectionCompletion = { indexPath in
            print("Called...")
        }
        dataController.delegate = self
        return dataController
    }()


    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.dataSource = self.dataController
        collectionView.delegate = self.dataController

        view.addSubview(collectionView)
    }
}

//MARK: - HomeDataControllerDelegate 
extension HomeViewController : HomeDataControllerDelegate {
    func homeDataController(_ controller: HomeDataController, didSelectItemAt: IndexPath) {
        print("Called..")
    }
}

HomeDataController.swift

protocol HomeDataControllerDelegate {
    func homeDataController(_ controller : HomeDataController, didSelectItemAt : IndexPath)
}


class HomeDataController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    private var controller : UIViewController? = nil

    var delegate : HomeDataControllerDelegate? = nil

    var didSelectionCompletion : ((IndexPath) -> (Void))? = nil

    override init() {
        super.init()
    }

    init(controller : UIViewController) {
        super.init()
        self.controller = controller
    }


    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        print("Did select item at...")
        // this is where I am trying to push the DetailViewController

        /* Method1 - using property*/
        let detialController = UIViewController()
        controller?.navigationController?.pushViewController(detialController, animated: true)

        /* Method2 - delegate */
        delegate?.homeDataController(self, didSelectItemAt: indexPath)

        /* Method3 - Block */
        self.didSelectionCompletion?(indexPath)
    }
}

При использовании метода 1 (с использованием свойства) существуют ограничения того, что HomeDataController всегда выдвигает только один контроллер детализации. Это стало зависимым классом. Также есть опция передачи контроллера назначения в init метод HomeDataController, снова это становится более сложным. Но если у вас есть исправление detailViewController, вы можете использовать этот метод. Но это не масштабируемый код для любого конкретного запроса на изменение.

Блоки и делегаты являются более стандартными и масштабируемыми параметрами. Используя эти методы, мы имеем полный контроль над UIController и любыми действиями.

Надеюсь, это поможет вам.

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