Swift 4 - Push a ViewController from a UICollectionView Cell

本秂侑毒 提交于 2020-04-30 16:37:41

问题


I'm stuck in my project and is in need for some help. I want to push/present a UICollectionViewController from a UICollectionViewCell including my UINavigationBar. I have understand that you can not actually present a ViewController from a Cell? How do I supposed to do in this case? My problem is that my NavigationBar won´t show up.

Here is my Cell:

import UIKit
import Firebase

class UserProfileHeader: UICollectionViewCell, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

lazy var followersLabelButton: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("followers", for: .normal)
    button.setTitleColor(UIColor.lightGray, for: .normal)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
    button.addTarget(self, action: #selector(followers), for: .touchUpInside)
    return button
}()

@objc fileprivate func followers() {

    let newController = NewController(collectionViewLayout: UICollectionViewFlowLayout())

    self.window?.rootViewController?.present(newController, animated: true, completion: nil)


    }

   }

And the CollectionViewController:

import UIKit
import MapKit
import Firebase

class UserProfileController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate {

    var userId: String?

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView?.backgroundColor = UIColor.white


        collectionView?.register(UserProfileHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerId")

    }


    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! UserProfileHeader

        header.user = self.user

        return header
    }


    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {


        return CGSize(width: view.frame.width, height: 200)


    }


}

回答1:


1- Inside the cell

weak var delegate:UserProfileController?

2- Inside cellForItemAt

cell.delegate = self

3- Use this inside the cell

delegate?.present(newController, animated: true, completion: nil)

BTW i think you mean

delegate?.navigationController?.pushViewController(newController, animated: true)  



回答2:


it`s not right way do this in view. Use MVC way: Move

button.addTarget(self, action: #selector(followers), for: .touchUpInside)

to UserProfileController in method

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! UserProfileHeader as! UserProfileHeader
        header.followersLabelButton.addTarget(self, action: #selector(followers), for: .touchUpInside)
        header.user = self.user

        return header
    }

and rewrite

@objc func followers() {

    let newController = self.navigationController

    newController?.present(newController, animated: true, completion: nil)


}



回答3:


If you want to present a new ViewController you should create a new delegate in your Cell like this:

import UIKit
import Firebase

protocol CellDelegate {
    func presentViewController()
}    

class UserProfileHeader: UICollectionViewCell, 
UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    var delegate: CellDelegate?

    lazy var followersLabelButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("followers", for: .normal)
        button.setTitleColor(UIColor.lightGray, for: .normal)
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
        button.addTarget(self, action: #selector(followers), for: .touchUpInside)
        return button
    }()

    @objc func followers() {
        delegate.presentViewController
    }

}

While in your ViewController you should make the delegate function works like this

import UIKit
import MapKit
import Firebase

class UserProfileController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate
 , CellDelegate {

    var userId: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView?.backgroundColor = UIColor.white
        collectionView?.register(UserProfileHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerId")
    }


    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! UserProfileHeader

        header.user = self.user

        // Remember to set the delegate for the cell
        header.delegate = self

        return header
    }


    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: view.frame.width, height: 200)
    }

    func presentViewController() {
        let newController = NewController(collectionViewLayout: UICollectionViewFlowLayout())

        self.window?.rootViewController?.present(newController, animated: true, completion: nil)
    }

}



回答4:


I really think you shouldn't be presenting from the cell at all, even if you have a reference to the viewController. I'd rather call a function on the delegate, and leave it to decide what to do -

import UIKit
import Firebase

protocol UserProfileHeaderDelegate: class {
    func followersTapped()
}


class UserProfileHeader: UICollectionViewCell, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    weak var headerDelegate: UserProfileHeaderDelegate?

    lazy var followersLabelButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("followers", for: .normal)
        button.setTitleColor(UIColor.lightGray, for: .normal)
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
        button.addTarget(self, action: #selector(followers), for: .touchUpInside)
        return button
    }()

    @objc fileprivate func followers() {
        self.headerDelegate?.followersTapped()
    }
}

In the viewController -

class UserProfileController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UserProfileHeaderDelegate {

    // etc, etc......

    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! UserProfileHeader

        header.user = self.user

        // Remember to set the delegate for the cell
        header.headerDelegate = self

        return header
    }


    // Implement the UserProfileHeaderDelegate protocol - this is called from within the cell
    // so all the cell knows is that its delegate implements this protocol, which has the followersTapped() function

    func followersTapped() {
        let newController = NewController(collectionViewLayout: UICollectionViewFlowLayout())
        self.present(newController, animated: true, completion: nil)
    }
}

This way your viewController is not concerned with the inner workings of your cell, and vice-versa.



来源:https://stackoverflow.com/questions/53433399/swift-4-push-a-viewcontroller-from-a-uicollectionview-cell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!