how to call presentViewController from within a UICollectionViewCell
UITableViewCell should never handle any business logic. It should be implemented in a view controller. You should use a delegate:
UICollectionViewCell subclass:
protocol CustomCellDelegate: class {
func sharePressed(cell: MyCell)
}
class CustomCell: UITableViewCell {
var delegate: CustomCellDelegate?
func didTapShare(sender: UIButton) {
delegate?.sharePressed(cell: self)
}
}
ViewController:
class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
//...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! CustomCell
cell.delegate = self
return cell
}
}
extension TableViewController: CustomCellDelegate {
func sharePressed(cell: CustomCell) {
guard let index = tableView.indexPath(for: cell)?.row else { return }
//fetch the dataSource object using index
}
}
Presenting a ViewController from within a CollectionViewCell that is nested in a TableViewCell
Use protocol and delegate like this
In tableViewCell
protocol CellDelegate {
func colCategorySelected(_ indexPath : IndexPath)
}
var delegate : CellDelegate?
In didSelect
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.colCategorySelected(indexPath)
}
In your ProfileViewController
class HomeVC: UIViewController , UITableViewDelegate, UITableViewDataSource, CellDelegate{
:
:
func colCategorySelected(_ indexPath : IndexPath){
// Push here
}
:
:
}
And dont forget
cellForRow
let Cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! tableCell
Cell.delegate = self // dont forget this line.
return Cell
How to present view controller from UICollectiveViewCell Class - SWIFT
You have to implement custom delegate for this. When user select item from collection view, you have to call parent view method using delegate.
Here is reference for this : Access a UICollectionView's parent UIViewController
How to present a ViewController after pressing a button inside of a CollectionViewCell
You can present your ProfileEditViewController
, which is styled in your Main.storyboard
the following way:
1) Give your ProfileEditViewController
a StoryBoard ID
. E.g. "ProfileEditViewController" - Some question regarding this is here: What is a StoryBoard ID and how can i use this?
2) Register the UIViewController
for the action on the UIButton
or offer an appropriate callback functionality.
As your HomeViewController
is also your Collection View's datasource, you can easily extend your DataSource method
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell`
Implementation could look like:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 3 {
let profileCell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
if let _cell = cell as? ProfileCell,
let button = _cell.optionsButton as? UIButton {
button.addTarget(self, action: #selector(handleOptionsButton), forControlEvents: UIControlEvents.TouchUpInside)
}
return profileCell;
}
return cell
}
Make sure that your buttons Action is now also being implemented by your HomeViewController
@objc func handleOptionsButton() {
print("Button pressed")
}
3) Now in HomeViewController.handleOptionsButton
you need to provide a functionality to support the transition to that specific Controller with the desired StoryboardID:
let storyboard = UIStoryboard(name: "Main", bundle:Bundle.main)
let controller = storyboard.instantiateViewController(withIdentifier: "ProfileEditViewController")
self.present(controller, animated: true, completion: nil)
How to present a UIViewController on top of UICollectionView?
Create a protocol in your CollectionViewFolderCell.swift
protocol CollectionViewFolderCellDelegate {
func collectionViewFolderCellDidPressButton()
}
And inside CollectionViewFolderCell
declare a delegate like:
var delegate: CollectionViewFolderCellDelegate?
Inside your button action add:
@IBAction func moreInfoBtn(_ sender: Any) {
delegate?.collectionViewFolderCellDidPressButton()
}
In your cellForItemAtIndexPath Method add cell.delegate = self
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewFolderCell
cell.delegate = self
return cell
}
Also in your View Controller you need to conform your CollectionViewFolderCellDelegate
extension CollectionViewFolder: CollectionViewFolderCellDelegate {
// here you can present your desired view controller
}
Swift 4 - Push a ViewController from a UICollectionView Cell
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)
How to transition a UICollectionViewCell via a button to another ViewController?
The problem is that your button's target is the cell, and so the buttonPressed
action function is located in the cell. That's a pretty silly thing to do, because (as you rightly say) you cannot call present
without a view controller to send it to.
What I would have done is set the button's target/selector in cellForItemAt:
. That way, self
is the view controller and we can set the target to self
. But you didn't do that!
Thus, you need to get from the cell to the view controller that controls it.
However, there is a way. It's called walking the responder chain. Set a UIResponder variable to the button:
var responder : UIResponder = self
Now loop, calling next
on responder
to walk one step up the chain:
responder = responder.next
Each time, look to see if this responder is a UIViewController. When it is, stop looping and send it present
! Thus:
var responder : UIResponder = self
repeat { responder = responder .next } while !(responder is UIViewController)
let vc = responder as! UIViewController
vc.present( // ...
(Still, even though the problem can be solved in this way, I think it was silly to get yourself into this mess in the first place. Making the view controller the target in the first place would have been a much better idea, in my opinion.)
presentViewController from TableViewCell
You should use protocol
to pass the action back to tableViewController
1) Create a protocol
in your cell class
2) Make the button
action call your protocol
func
3) Link your cell's protocol
in tableViewController
by cell.delegate = self
4) Implement the cell's protocol
and add your code there
let vc = ViewController()
self.presentViewController(vc, animated: true, completion: nil)
Present view controller on last item of UICollectionView
viewWillAppear will be called after viewDidLoad. If you need to call this method once your viewcontroller is launched, then you can add the code in the viewDidload method.
But if you still need to use viewWillAppear, I suggest to wrap this call on the main thread or mainqueue. You can use GCD or NSOperationQueue for this.
I think this might help in the delay issue
Related Topics
Swiftui Hide Tabview Bar Inside Navigationlink Views
Restricting App Installations from Appstore Only to Users with iPhone 5/5S/5C
How to Download a File and Save It to the Documents Directory with Afnetworking
Mkmapview Mkpointannotation Tap Event
iOS Touch Event Notifications (Private API)
How to Change the Background Color of the Uialertcontroller
How to Add Image in Uitableviewrowaction
How to Change App Icon Programmatically
How to Change Uidatepicker to a Specific Time (In Code)
Make Segue Programmatically in Swift
How to Render a Uiview with Transparent Background on an Scnplane in Arkit
Move a Node to Finger Using Swift + Spritekit
Swift Get String Between 2 Strings in a String
Combine Framework Serialize Async Operations