Swift - Call self.navigationController into custom cell class

半世苍凉 提交于 2019-12-21 05:11:26

问题


Swift:

I have UICollectionViewController with another file/class UICollectionViewCell

The goal is to push UIViewController from my custom cell class.

something like this:

self.navigationController?.pushViewController(vc, animated: true)

I have no problems to implement push from didSelectItemAtIndexPath in UICollectionViewController but i want to do this from custom cell class registered into my UICollectionViewController.

When i try to push view from custom cell class unfortunately i don't have access self.navigationController

Also i want to do this 100% programmatically. I don't use Storyboard or Nib files

Thanks in advance.


回答1:


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




回答2:


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



回答3:


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.



来源:https://stackoverflow.com/questions/31956931/swift-call-self-navigationcontroller-into-custom-cell-class

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