Reputation: 2514
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.
Upvotes: 6
Views: 8414
Reputation: 25745
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.
Upvotes: 0
Reputation: 652
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
Upvotes: 5
Reputation: 2994
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.
Upvotes: 7