Running a Segue within a UITableViewCell Swift 2 - swift

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.

Related

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
}

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.

Perform Segue from Button in TableViewCell

I have a CustomCell class that has a button. I am using a prototype cell (not a .xib). I would like to have the button in a tableviewcell perform a segue and pass a value to a new class. How do I create a unique action for a button in a tableviewcell? Thanks!
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
selectedAreaCode = areaCodes[indexPath.row]
// Configure Cell
cell.areaCodeButton.setTitle(areaCode, forState: UIControlState.Normal)
cell.areaCodeButton.addTarget(self, action: "segue", forControlEvents: UIControlEvents.TouchUpInside)
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
}
func segue() {
self.performSegueWithIdentifier("toDialer", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "toDialer") {
let nextViewController = (segue.destinationViewController as! PhoneDialer)
nextViewController.passedAreaCode = selectedAreaCode
}
}
There's a bunch of ways to get the tap action from your custom cell, but I'm assuming that you're trying to retrieve the action from a UIViewController because you're trying to segue.
Because you're dequeueing a cell, you briefly have full access to the cell in the scope of your cellForRowAtIndexPath function. As long as you have the button as a public property of the cell, you can set that button's target to your segue method.
Also, because what you're trying to pass is in the title of the button itself, you can just access the sender from the selector.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = yourCell()
cell.button.addTarget(self, action: #selector(tap(:)), forControlEvents: .TouchUpInside)
}
func segue(sender: UIButton) {
// Perform segue and other stuff
sender.title // This is the area code
}

Selecting row in tableview, removes custom cell

I have a Viewcontroller with a Searchbar at the top with a tableview below. The tableview has a custom cell with 2 labels in it. My problem is that when i run the app and i select a row/cell everything inside the cell disappears. I then force the blank cell outside the visible area of the tableview, so it will be re-used. That's when everything inside the cell is back. Does anyone know why it behaves like this?
My Custom cell class (ContactCell.swift):
import UIKit
class ContactCell: UITableViewCell {
#IBOutlet var lblContactName: UILabel!
#IBOutlet var lblContactTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
My ViewDidLoad function:
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
My Delegate and Datasource:
extension contactsTabelViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("contactCell", forIndexPath: indexPath) as! ContactCell
if let label = cell.lblContactName{
label.text = "This is a name"
}
if let label3 = cell.lblContactTitle{
label3.text = "This is a title"
}
return ContactCell()
}
}
The problem that caused this problem was that i returned ContactCell() instead of the variable cell
Solution was:
Change this:
return ContactCell()
to this:
return cell
in the cellForRowAtIndexPath function.

Table View with buttons inside of UIViewController

I am trying to use a Table View with cell inside of UIViewController and I want each row to have a button in it. The reason I am using UIViewController instead of UITableView is because I want to have other stuff in that view instead of the whole screen taken by table view.
problem I am having is I only see one button in the last cell. How I can fix this so each row has button in it?
I was hoping that could use something like this
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var logButton: UIButton!
#IBOutlet weak var mytableView: UITableView!
let carLocations = ["Row One", "Row Two", "Row Three"]
override func viewDidLoad() {
super.viewDidLoad()
mytableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return carLocations.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell: UITableViewCell = mytableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
myCell.textLabel?.text = carLocations[indexPath.row]
myCell.detailTextLabel?.text = " Detailed text"
logButton.tag = indexPath.row
// I was hoping that I could use something like this
// myCell.logButton.tag = indexPath.row
return myCell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
}
}
}
You can use Custom Cell this way.
Create a new swift file with subclass of UITableViewCell.
Assign that class to your cell by selecting your cell and go to Identity Inspector and it will look a like:
And add elements into your cell which you need for example I have added two labels and one button into cell as per your need and cell will look like:
After that connect outlet of that element into your custom call and your Custom tableview cell class will be:
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var titleLbl: UILabel!
#IBOutlet weak var DetailLabel: UILabel!
#IBOutlet weak var btn: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Now you can create a custom cell with custom tableview cell class this way in your cellForRowAtIndexPath method:
let myCell = mytableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
And you can assign values to it this way:
myCell.titleLbl.text = carLocations[indexPath.row]
myCell.DetailLabel.text = "Detailed Text"
myCell.btn.tag = indexPath.row
And final code will be:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = mytableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
myCell.titleLbl.text = carLocations[indexPath.row]
myCell.DetailLabel.text = "Detailed Text"
myCell.btn.tag = indexPath.row
return myCell
}
And your result will be:
Check this sample for more Info.
Drop a UITableViewCell on your tableview. That will give you option to customize your cell's look and feel. Create a new class inheriting from UITableViewCell and add that as a class to your tableview cell. Create outlets from cell to this new file and then use cellForRowAtIndexPath to set the properties of the controls inside your cell.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! CBTableViewCell
// add self as delegate for tablecell so delegate can call the function defined within
cell.delegate = self
cell.title.text = self.items[indexPath.row]
return cell
}
I would use Custom Cells to solve this problem...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomCell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomCell
//Do sth
return cell
}
Your cell:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet var Button: UIButton!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Actually it is very easy: You just drag a UITableView into your view in the size you want. You add a prototype cell to it and then you customise that cell by dragging in labels, etc. You make a new class, which inherits from that UITableViewCell as explained earlier. You also connect the labels and buttons to the class as explained i the other answers. Apple has a very good explanation here Go to the section where they explain how to customise the cell.