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

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
}

Related

Seguing from uicollectionview that is inside of a tableview

I've put a uicollectionview inside of a uitableview. I'm having trouble seguing to another viewcontroller after selecting a collectionview cell that is inside of the table view cell.
// if the user selects a cell, navigate to the viewcontroller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// we check did cell exists or did we pressed a cell
if let cell = sender as? UICollectionViewCell {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell") as! TestingTableView
// define index to later on pass exact guest user related info
let index = cell2.collectionView?.indexPath(for: cell)!.row
print(index as Any)
// if segue is guest...
if segue.identifier == "guest" {
// call guestvc to access guest var
let guestvc = segue.destination as! GuestCommunityViewVC
// assign guest user inf to guest var
guestvc.guest = communities[index!] as! NSDictionary
}
}
}
}
I'm getting an error at the line:
let index = cell2.collectionView?.indexPath(for: cell)!.row
because it is saying the value is nil. Does anyone know a better method to do this?
Here is an example of how to use a delegate:
1) Create a protocol outside of a class declaration:
protocol customProtocolName:class {
func pushToNewView(withData:[DataType])
}
note: use class in order to prevent a reference cycle
2) Create a delegate inside of the UITableViewCell that holds the reference to the UICollectionView:
class customUITableViewCell {
weak var delegate:customProtocolName? = nil
}
3) Inside the UIViewController that holds the reference to the UITableView, make sure you add the protocol besides the class declaration and add the function we created to ensure that the protocol specifications are satisfied:
class customViewController: customProtocolName {
func pushToNewView(withData:[DataType]) {
//inside here is where you will write the code to trigger the segue to the desired new UIViewController
//You can take this new data and store it in this ViewController and then during the segue pass it along
}
}
4) In the UITableViewDelegate function, "cellForRowAt", set the delegate inside the customUITableViewCell to self:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! customUITableViewCell
cell.delegate = self
return cell
}
5) Inside the customUITableViewCell, where the UICollectionView delegate function handles "didSelectItemAt" delegate function, you trigger the protocol function there like so:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate?.pushToNewView(withData:[DataType])
}
This is a very simplified example, if you wanted to pass an IndexPath, then you can modify the function to do so. you can also pass back anything you want as well, it isn't limited.

UIButton to update UITableView in Swift 3

I'm wondering how I can use a UIButton action function to be able to press a button so each time it is pressed, a new row in a UITableView is added. Does anyone know how to accomplish that?
You have to set an IBOutlet for your UITableView.
In the IBAction of the UIButton, add a value to the data structure you used to implement the cells of the tableview.
Then call reloadData() function for the tableview outlet
That is, in code
#IBOutlet weak var table: UITableView!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell?.textLabel = dataStructure[indexPath.row]
return cell
}
For the IBAction
#IBAction func buttonPressed(_ sender: UIButton)
{
dataStructure.append(someNewValue); // someNewValue is the new Value for the row
table.reloadData()
}

Push TableViewController from a UICollectionView with UITableViewCell's

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

Running a Segue within a UITableViewCell Swift 2

I have a button within a UITableViewCell and need to perform a following to another View.
How can I do this?
class CustomCell: UITableViewCell {
#IBAction func btnShowView(sender: AnyObject) {
performSegueWithIdentifier("seguePrincipalImagem")
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
Instead of having the code on the cell directly (although you can also make it with delegation), you can add the code directly to your controller and bind the method to the button, something like this:
Create a function that perform the segue on your UIViewController
func btnShowView(sender: AnyObject) {
self.performSegueWithIdentifier("segue_identifier",selder:nil)
}
In the process of creating the cell that has the button (in tableView:cellForRowAtIndexPath:):
//Inside tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier",indexPath) as! YourCustomTableViewCell
cell.yourBtn.addTarget(self, action: "btnShowView", forControlEvents: .TouchUpInside)
//More code to configure cell...
return cell
And that's it.

Swift - Segue from Button inside a cell

i have a custom cell attached to TableViewCell class, and i have a button inside that custom cell, i want whey i press the button it segues to another view controller, but the:
performSegueWithIdentifier(identifier: String, sender: AnyObject?)
function is not recognised, how to fix that ?
Edit:
-performSegueWithIdentifier: method is declared in UIViewController. So you can't just call it in UITableViewCell subclass.
You can add an action to that button when you are creating cell in -tableView:cellForRowAtIndexpath: method. Then you can call -performSegueWithIdentifier: method in that action method. Here is example assuming we are in UITableViewController subclass:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.button.addTarget(self, action: "someAction", forControlEvents: .TouchUpInside)
return cell
}
And here is action method:
func someAction() {
self.performSegueWithIdentifier("moveToView", sender: self)
}
You need a custom class for your cell. In that class, create an #IBAction as response to the button click. In that action, perform your segue.
If you are using Interface Builder:
Connect your firstViewController to the secondViewController - and create a Segue Identifier.
Then you are able to use
performSegueWithIdentifier(identifier: String, sender: AnyObject?)