Push TableViewController from a UICollectionView with UITableViewCell's - swift

So I am trying to push a UITableViewController from a UITableViewCell that is embedded in a collection view cell.
So the structure is UICollectionView > UICollectionViewCell > UITableView > UITableViewCell.
Do I want to call a segue when the TableViewCell is clicked?
How can I do this as you cannot access the function perform segue for identifier?

You can create one protocol for that and implement it with your ViewController where you are having collectionView, after that make instance property of that protocol in your collectionViewCell and set that property in cellForItemAt method. Now inside the didSelectRowAt method of tableView call the delegate method with the detail that you want to pass for segue.
protocol PassData {
func performSegue(with data: String) //Set argument type to Type that you want pass instead of String
}
Now implement this PassData protocol with your ViewController and inside the cellForItemAt set the delegate of UICollectionViewCell.
class ViewController: UIViewController, PassData, UICollectionViewDelegate, UICollectionViewDataSource {
//Other methods
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
cell.passDelegate = self
return cell
}
//Add the `performSegue(with:)` delegate method of PassData
func performSegue(with data: String) {
//Perform segue here
self.performSegue(withIdentifier: "SegueIdentifier", sender: data)
}
}
Now in your CustomCollectionViewCell make one instance property named passDelegate of type PassData? after that in didSelectRowAt method of tableView call its delegate method.
class CustomCollectionViewCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource {
var passDelegate: PassData?
//Your other methods
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Pass whatever data that you want to pass
self.passDelegate?.performSegue(with: array[indexPath.row])
}
}

You can push the tableViewController to navigation stack by calling self.navigationController?.pushViewController(tableviewVC, animate: true) from table view delegate method didSelectRowAtIndexPath

Related

How to performSegue or go to another view from a cell when the superclass of the main class is UICollectionViewCell

I have a class which is a type of UICollectionViewCell.
In this class, I have another CollectionView which when I select a cell of this inner collection view, I go to another view or perform a segue. I really need some help with it as The class is CollectionViewCell and performSegue() is not working.
class MyGamesController: UICollectionViewCell,UICollectionViewDelegateFlowLayout,UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// performSegue is not working here
}
}
You can do what you looking for by using swift protocols read more HERE
First you need to know that performSegue() works on UIViewController
You need to create a protocol for your collectionViewCell , I guess here is MyGamesController like this:
protocol MyGamesControllerDelegate {
func insidCellDidSelect()
}
And add an instance of it to your class:
var delegate : MyGamesControllerDelegate?
Now when you call delegate?.insidCellDidSelect in your MyGamesController 's didSelectItemAt you can trigger it inside your parent VC by doing steps below:
When you are creating an instance of MyGamesController i.e incellForItemAt attach the cells delegate to the parent ViewController which is creating it like this:
class TheVCYouWantToPerformSegue : MyGamesControllerDelegate {
...
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = ... as! MyGamesController
cell.delegate = self
Then you can implement the protocols method inside your VC body and get notified :
func insidCellDidSelect() {
//Perform Segue goes here
}

Is there an alternative for function Present in a UItableViewCell? [duplicate]

This question already has answers here:
UIButton action in table view cell
(11 answers)
Closed 3 years ago.
I want to navigate from UITableViewCell(Xib) to UIViewController but when I try to use present Value of type 'TableViewCell' has no member 'present
So if anyone is familiar with a function that can help me navigate please help me :) .
Thank you for your time
UITableViewCell can’t present viewcontroller. Please store viewController to variable in your tableview cell. And use it to present.
Or use didSelectRowAt delegate function and using self to present ( Or write your custom cell delegate if your event fire by button in cell)
Conform your ViewController to UITableViewDelegate protocol and then in your ViewController code use the delegate method: func tableView(UITableView, didSelectRowAt: IndexPath) and inside this method perform/present a segue or any other type of navigation you have.
import UIKit
class ViewController: UIViewController, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(UITableView, didSelectRowAt: IndexPath) {
// navigation logic here
}
}
Use closure inside your custom UITableViewCell to handle this scenario.
In your custom UITableViewCell create a handler and call it when the button is tapped inside the cell, i.e.
class CustomCell: UITableViewCell {
var handler: (()->())?
#IBAction func onTapButton(_ sender: UIButton) {
handler?()
}
}
Now, set the handler in cellForRowAt when creating the cell, i.e.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.handler = {
//present your controller here...
}
return cell
}

Can I do transition in CollectionCell Class?

I want to transition another ViewController Class when tablViewCell tapped. (TableView in CollectionView Cell)
so,I want to write to transition Code in tableViewCell Class.
How should I do?
You need to assign collectionview delegate to the view controller class inside the tableview cellforrow method. And assign tableview cell indexpath.row to its collectionview tag.
In collectionview didselect method write the transition Code.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ...
cell.collectionView.tag = indexPath.row
cell.collectionView.delegate = self
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("selected collectionview cell indexpath \(indexPath) in table view cell row \(collectionView.tag)")
//push to next view controller from here
}
}

Using variable from one class in another class

I have two classes: CollectionCell and ViewController.
The first class is used for Collection View Cell (in which I have placed a button). In CollectionCell class I need to connect outlet for this button: #IBOutlet weak var firstPercent: UIButton!.
In ViewController class I need to use var of this button: firstPercent.
How can I do that? Thanks for any help.
In collectionViewDelegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
Now declare your Custom Cell instance and then
you can use CollectionCell.firstPercent addTarget in ViewController and set this or
do whatever you want.
You can get it something like below.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ZonesCell", for: indexPath as IndexPath) as! ZonesCell
let keyValue = self.dataList[indexPath.row] as! [String:Any]
cell.lblZoneName.text = keyValue[Keys.name] as? String
if(keyValue[Keys.status] as? Bool)! {
cell.lblZoneName.textColor = UIColor.white
} else {
cell.lblZoneName.textColor = UIColor.red
}
return cell
}
There lets suppose ZonesCell is the collectionCell contains lblZoneName as label.
You can use button same as label.
You can use delegate for this.
Add a protocol named “CollectionCellDelegate“ for your cell and add a delegate method for your button action. Pass cell itself as a parameter to that method. Conform to “CollectionCellDelegate“ from your ViewController and implement delegate method inside ViewController. Finally but most important step, assign your view controller as CollectionCellDelegate from cellForItemAt method.
protocol CollectionCellDelegate : class {
func didPressButtonFirstPercent(_ cell: CollectionCell)
}
//Inside your CollectionCell class declare a variable to hold your cell delegate
class CollectionCell: UICollectionViewCell {
//Add a variable to hold your delegate
weak var delegate: CollectionCellDelegate?
//Outlet for your button
#IBOutlet weak var firstPercent: UIButton!
//Action for your button
#IBAction func didPressButtonFirstPercent(_ sender: Any) {
delegate?.didPressButtonFirstPercent(self)
}
}
//ViewController Conform to CollectionCellDelegate
class ViewController: UIViewController, CollectionCellDelegate{
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: “Cell_Identifier”, for: indexPath) as! CollectionCell
//Set ViewController as your CollectionCell delegate
cell.delegate = self
return cell
}
//Implement delegate method here
func didPressButtonFirstPercent(_ cell: CollectionCell) {
//You can access your button here like below
Let firstPercent = cell.firstPercent
}
}
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! CollectionCell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell. firstPercent.tag = indexPath.row
example project
return cell
}
}

How to modify a custom cell inside of DidSelectRowAtIndexPath

A custom cell class has the override func layoutSubviews() where the detailTextLabel of each cell is given the title "Jim". Upon clicking on DidSelectRowAtIndexPath, is there a way to change the detail text of the cell permanently(to stop the cell from constantly making the detail Jim), to let's say "Bob"?.
//This function is in the custom cell UserCell
class CustomCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
detailTextLabel?.text = "Jim"
}
///........
}
//In the viewController with the tableView outlet
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//.....
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellId, forIndexPath: indexPath) as! CustomCell
//......
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
/* Code I need to convert the detailTextLabel.text to equal "Bob" upon clicking on certain cell */
}
The cell itself shouldn't be used to hold state for any data, but only to display it. Create a mutable array property on the controller to hold the underlaying data (strings). Set the new cells' text properties by reading this array, and in tableView:didSelectRowAtIndexPath: change the value in the array at the index for "Bob" to "Jim". Whenever the tableView reloads it will now read the updated value from the dataSource.
In addition to the UITableViewDelegate protocol also study the UITableViewDataSource protocol. By default the UITableViewController class conforms to both of these protocols and is assigned as each on its .tableView property (if you introspect its self.tableView.delegate and self.tableView.datasource values you will receive back the original UITableViewController). If you manually created your own tableview controller class that inherits from UIViewController, then you will need to assign both of these properties on the tableView in order for it to function properly.
Very simple, do it like this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
detailTextLabel?.text = "Bob"
}