Swift - Call self.navigationController into custom cell class

我是研究僧i 提交于 2019-12-03 16:06:24

This is a bad idea. Views should not have/do that kind of logic. You should leave it with the Controller (that's what the MVC-Pattern is about).

Anyway:

class MyCollectionViewCell: UITableViewCell {
    var myViewController: MyViewController!
}

and when the cell is dequeued you could set it like this:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
    let cell: MyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(myCellIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
    let nvc: UINavigationController = UIStoryboard(name: "myStoryboard", bundle: nil).instantiateViewControllerWithIdentifier("myNavigationController") as! UINavigationController
    cell.myViewController = nvc.childViewControllers.first as! MyViewController

    return cell
}

and on selection:

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
    let cell: MyCollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCollectionViewCell

    // I don't know where vc comes from
    cell.myViewController.navigationController?.pushViewController(vc, animated: true)
}

Still, there is no case I can think of, where this would make any sense. So rethink your architecture again.

Visualize the communication of your entities, by drawing it on a paper. You'll have to draw Models, Views and Controllers and only Controllers are allowed to "talk" to other Controllers.

Look at this and this

I've recently came up with this question as well, and I have a way to demonstrate Akhilrajtr comment, as it might help others as well.

First in your cell class you need a protocol in top of the file:

protocol YourCellDelegate: NSObjectProtocol{
    func didPressCell(sender: Any)
}

Then in you cell class variables add this:

var delegate:YourCellDelegate!

When you are performing some action within your cell, trigger the function of your protocol:

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
    delegate.didPressCell(sender: indexPath)
}

On your super main controller, you should conform to the delegate you've created:

class MyViewController: UIViewController, YourCellDelegate{...}

And, implement the function of the protocol, which will be triggered when the cell is pressed, just like you defined it before:

func didPressCell(sender: Any){
    let vc = SomeViewController()
    self.navigationController?.pushViewController(vc, animated: true)
}

Of course not to forget to give the reference for your delegate in the cell instantiation part in cellForItem function:

cell.delegate = self

I want to extend on ezcoding answer. So instead of this code

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
    let cell: MyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(myCellIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
    let nvc: UINavigationController = UIStoryboard(name: "myStoryboard", bundle: nil).instantiateViewControllerWithIdentifier("myNavigationController") as! UINavigationController
    cell.myViewController = nvc.childViewControllers.first as! MyViewController

    return cell
}

You can simply use self to get the current instance of the view controller, hence the code can be simplified to

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
    let cell: MyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(myCellIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
    cell.myViewController = self

    return cell
}

This worked for me at-least in my case.

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