Passing data between View Controllers in Swift (From TableView to DetailViewController) - ios

I have two files, MyTableViewController and myViewController. I set UIImageView on TableCell in MyTableVIewController. myViewController does not contain anything. And I created an array called ImageArray which contains an array of Images.
What I am aiming to do here is when I click an image on TableCell in myTableViewController, I want the clicked image to appear in the myViewController. And some description about the clicked image beside the image too. I want to use myViewController for users to get detailed information of the selected image.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell
var ImageView = cell.viewWithTag(1) as! UIImageView
ImageView.image = UIImage(named: ImageArray[indexPath.row])
ImageView.contentMode = .ScaleAspectFit
var TextView = cell.viewWithTag(2) as! UILabel
TextView.text = ImageArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("next", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "next") {
let destination = segue.destinationViewController as! myViewController
}
}
I don't know what to do to make it happen. I really appreciate if you could help me figure out! Thanks!

First and foremost, I'm assuming your MyTableViewController class conforms to both UITableViewDataSource and UITableViewDelegate protocols and that you've set your MyTableViewController class to be the delegate in code or via Storyboard.
With that sorted out,there are multiple ways to achieve the result you seek.
You can declare your ImageArray in an independent class and call it inside your MyTableViewController class, index them onto a tableView using the tableView delegate methods, and finally using the prepareForSegue method to push your images onto your myViewController. Or you can simply declare and initialize your ImageArray at the top of your MyTableViewController class like below:
var ImageArray = [("Moscow Russia.jpg", "Europe"),
("London England.jpg", "Europe")]
In the ImageArray above, ensure that your image name matches exactly as the asset name you've imported into your Xcode project.
Then we specify how many rows in section we need ImageArray to occupy on our tableView (i.e. basically count our ImageArray into our TableView) with below required method:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return ImageArray.count ?? 0
}
Next, you want to present your ImageArray in each row of of the cell using the tableView:cellForRowAtIndexPath: method.
Side Note on your TableCell: Hopefully your TableCell is subclassed from UITableViewCell and you have already declared and connected two IBOutlets, say, imageView and textLabel respectively. Also, ensure your TableCell is properly linked to your prototype cell in Storyboard under Identity Inspector) Your TableCell class should look something like below:
import UIKit
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var textLabel: UILabel!
}
Now back into your MyTableVIewController class. From your code, I see you're casting the line 'let cell = ...' as 'UITableViewCell. You should rather cast it as 'TableCell' instead since you're subclassing it. Implement the tableView:cellForRowAtIndexPath: method as follows:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as! TableCell
//Note that I'm using tuples here. Pretty cool huh. Got to love Swift!
let (imageName, textNameToGoWithImage) = ImageArray[indexPath.row]
cell.textLabel.text = textNameToGoWithImage
cell.imageView.image = UIImage(named: imageName)
cell.imageView.contentMode = .ScaleAspectFit
// You could have also used 'if let' in optional binding to safely unwrap your image if you want like below.
// if let image = UIImage(named: imageName){
// cell.imageView?.image = image
// cell.imageView.contentMode = .ScaleAspectFit
// }
return cell
}
It looks like you're a little confused about when and where to use performSegueWithIdentifier method as opposed to using -prepareForSegue method. And even when to use the tableView:didSelectRowAtIndexPath method.
Let me briefly explain here. You use the performSegueWithIdentifier method when you didn't control-drag a segue from one ViewController's scene to another in Storyboard. This way, using the performSegueWithIdentifier method will allow you to move between ViewController scenes as long as you specify the right identifier which you've set in Storyboard under 'Attributes Inspector.'
Now if you're using Storyboard instead, you wouldn't need the tableView:didSelectRowAtIndexPath method. What the tableView:didSelectRowAtIndexPath method does is that it tells the delegate that the specified row is now selected and we can do something within its code body (like push an image or a text onto another ViewController Scene like you're trying to do). But that becomes redundant when you use segues. All you have to do, is to control-drag a segue from the table cell on your MyTableViewController scene to your myViewController scene. Choose 'Show' and give the segue an identifier name like you've done "next". (A little side note: if you want the Back button functionality to display at top navigator bar when you run your app, you simply embed your MyTableViewController in a UINavigationController to give you that 'Back' button functionality. With your MyTableViewController Scene selected in Storyboard, Go to the top menu and select Editor >> Embed In >> Navigation Controller. Then walla!!)
Lets now go ahead and implement our tableView:prepareForSegue method like below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "next" {
//Note that, originally, destinationViewController is of Type UIViewController and has to be casted as myViewController instead since that's the ViewController we trying to go to.
let destinationVC = segue.destinationViewController as! myViewController
if let indexPath = self.tableView.indexPathForSelectedRow{
let selectedRow = ImageArray[indexPath.row]
destinationVC.imageName2 = selectedRow.0
destinationVC.textName2 = selectedRow.1
}
From the above code, make sure you set the 'imageName' and 'textName' as properties in your myViewController class first before you can access them with 'destinationVC' which is now of type myViewController. These two properties will hold the data we are passing from MyTableViewController class to myViewController class. And we are using the array index to pass data to these two properties accordingly.
You can then create two IBOutlets to display your image and text by passing these set 'imageName2' and 'textName2' properties to your outlets (or any UI control for that matter).
Now the reason why you will have to set properties first in
myViewController class before you pass them on or around (i.e. to a
UI element, closure, another VC etc) is that, when you hit a tableView cell from
MyTableViewController scene to segue onto your next ViewController
scene (i.e. your myViewController scene), iOS hasn't instantiated
that second scene just yet. And so you need a property to hold onto the data
you're trying to pass onto your second scene View Controller first so that you can
make use of it later when that class finally loads.
So your myViewController class should look something like below:
import UIKit
class myViewController : UIViewController {
//Your two strings to initially hold onto the data
//being passed to myViewController class
var imageName2 : String?
var textName2 : String?
#IBOutlet weak var detailImageView: UIImageView!
#IBOutlet weak var detailTextNameLabel: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
detailTextNameLabel.text = textName2!
if let image = UIImage(named: imageName2!) {
self.detailImageView.image = image
}
}
And that's it!
Things to note on labelling and conventions in Swift:
Start naming classes with block letters (i.e. class
ViewController() {})
Classes and properties should capture the meaning of what they
represent. I will recommend you change your MyTableViewController
and 'myViewController'classes accordingly to reflect what they truly
mean or do (You can go with 'MainTableViewController' and 'DetailViewController'. That will do just fine).
Use camelToe labelling for properties and methods. (I used the labels you
provided in your question in order not to confuse you too much).
Enjoy!

This should help out:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "next") {
let destination = segue.destinationViewController as! myViewController
destination.imageView.image = UIImage(named: ImageArray[tableView.indexPathForSelectedRow?.row])
destination.textView.text = ImageArray[tableView.indexPathForSelectedRow?.row]
}
}
(Where imageView and textView are views in your new viewController.)
Note:
tableView.indexPathForSelectedRow?.row should give you the selected row, as the name implies, but it can be nil, so be careful.
In addition, Swift variable naming conventions are camelCase, so imageView is the correct way, while ImageView is incorrect.

In swift 3 you can do something like this:
In your MyTableViewController class:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! UITableViewCell
// for imageview
var ImageView : UIImageView = cell.contentView.viewWithTag(1) as! UIImageView
ImageView.image = UIImage(named: ImageArray[indexPath.row])
// for text
var TextView : UILabel = cell.contentView.viewWithTag(2) as! UILabel
ImageView.text = ImageArray[indexPath.row]
return cell
}
And in your didSelectRow method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "myViewController") as! myViewController
nextVC.myImgView.image = UIImame(named: ImageArray[indexPath.row])
nextVC.myLabel.text = ImageArray[indexPath.row]
self.present(nextVC!, animated: true)
}
And inmyViewController class:
class myViewController: UIViewController
{
let myImageView = UIImageView()
let myLabel = UILabel()
}

Related

Swift: Issues passing data between tableview cell to a secondary viewcontroller with a UIImageView

Using Xcode and Swift, I have created a tableview, where I have 11 different cells within it. Each cell are custom made and only contains an image. My goal is that when I press one of the cells, it will transition onto a secondary viewcontroller. The image that the chosen cell contains will then be passed onto the secondary viewcontroller and can be seen within an imageview in the secondary view controller.
This is the code for my primary viewcontroller where I have my tableview:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
let vc = showViewViewController(nibName: "showViewViewController", bundle: nil)
vc.paintingImage?.image = #imageLiteral(resourceName: "Picture5")
let showPainting = storyboard?.instantiateViewController(identifier: "showView")
view.window?.rootViewController = showPainting
view.window?.makeKeyAndVisible()
}
And this is the only code I have for my secondary viewcontroller. Within the storyboard of my secondary viewcontroller i only have that one imageView.
#IBOutlet weak var paintingImage: UIImageView!
When i run the application I get no error, but the imageview just remains blanc, as if it can't reach the image for some reason. Hope this helps.

The UICollectoinViewCell has no member of present (in order to present another view )?

I have created a class for the custom cell that I use for a collection view in my app . In this cell I have a button that I'd like to lead to another storyboard from the current one . So I tried to use present as follow :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let cr = storyboard.instantiateViewController(withIdentifier: "test")
self.present(cr, animated: true)
but there is a problem with sender which in this case is self. The error says UICollectionViewCell has no member of present which make sense. But then how can I achive my goal as I may need to use the same concept for segus in order to transfer information from one storyboard to another ?
The solution to your problem can fixed in that way
In your custom CollectionViewCell add Button as IBOutlet i.e
class CustomCollectionViewCell : UICollectionViewCell
{
#IBOutlet weak var btnDemo: UIButton!
//Otherstuff
}
And in the ViewController that has the CollectionView add IBAction from the that UIButton on the CustomCell and in the CellForRowAtIndexPath you need to add tag to that button in order to identify which button you clicked i.e
class ViewController : UIViewController
{
#IBAction func btnButtonPressed(_ sender: Any)
{
let currentBtn = sender as UIButton
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) ->
UICollectionViewCell
{
//Initialize Cell and other necessary stuff
currentCell.btnDemo.tag = indexPath.row
}

swift getting data for selected cell in another ViewController (programatically)

This question has been answered many times. But the answers I could find on it, didn't work for me, cause I can't seem to call the cell's class.
to further explain:
I have a viewController, with a UITable. The cells are configured in a UITableViewCell class. (it's from this class I need to pull the information)
my "cell class" is called mySuggestionsCel
Here's my code for "didSelectRowAtIndexPath"
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.allowsSelection = false
var selectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
var VC = detaiLSuggestion_VC()
self.navigationController?.pushViewController(VC, animated: true)
if selectedCell.backgroundColor == UIColor.formulaFormColor() {
selectedCell.backgroundColor = UIColor.formulaMediumBlue()
UIView.animateWithDuration(0.5, animations: {
selectedCell.backgroundColor = UIColor.formulaFormColor()
})
} else {
selectedCell.backgroundColor = UIColor.formulaGreenColor()
UIView.animateWithDuration(0.5, animations: {
selectedCell.backgroundColor = UIColor.formulaLightGreenColor()
})
}
}
I tried doing
mySuggestionsCell.someVariable
I also tried selectedCell.someVariable
neither worked.
I need to get this information from my detailSuggestion_VC(), from my cell Class. But the data it needs to pull, is the data the specific cell that's getting selected has. Which is why I'm having some trouble getting this to work.
I looked around for a while. But couldn't find any questions or answers to this specific issue.
Any help would be greatly appreciated
I'm making the following assumptions:
You have a tableViewCell class file that controls your table cells.
You have a detail-view controller that your table segues to when you tap a cell.
What you want to do is to pass the tapped cell's information so your new view controller has all the cell's info.
Instead of this:
var selectedCell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
You will need to instead do a typecast into your tableViewCell class. Like so:
var selectedCell = tableView.cellForRowAtIndexPath(indexPath)! as tableViewCell
What you need to do next is to call the following function:
performSegueWithIdentifier(/*Segue Identifier goes here*/, sender: selectedCell)
Making this call will pass selectedCell's contents into sender, which can be used in prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject)
make sure you override prepareForSegue somewhere in your class.
Now, in prepareForSegue:, you can get a reference to the destinationViewController, and initialize the instance variable in the destinationViewController that will hold your selectedCell's variables.
//in prepareForSegue
let controller = segue.destinationViewController as detailSuggestion_VC
controller.cellInfo = sender

Swift: Pass UITableViewCell label to new ViewController

I have a UITableView that populates Cells with data based on a JSON call. like so:
var items = ["Loading..."]
var indexValue = 0
// Here is SwiftyJSON code //
for (index, item) in enumerate(json) {
var indvItem = json[index]["Brand"]["Name"].stringValue
self.items.insert(indvItem, atIndex: indexValue)
indexValue++
}
self.tableView.reloadData()
How do I get the label of the cell when it is selected and then also pass that to another ViewController?
I have managed to get:
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
println("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow();
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
println(currentCell.textLabel.text)
}
I just cant figure out how to pass that as a variable to the next UIViewController.
Thanks
Passing data between two view controllers depends on how view controllers are linked to each other. If they are linked with segue you will need to use performSegueWithIdentifier method and override prepareForSegue method
var valueToPass:String!
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
println("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow();
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel.text
performSegueWithIdentifier("yourSegueIdentifer", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "yourSegueIdentifer") {
// initialize new view controller and cast it as your view controller
var viewController = segue.destinationViewController as AnotherViewController
// your new view controller should have property that will store passed value
viewController.passedValue = valueToPass
}
}
If your view controller are not linked with segue then you can pass values directly from your tableView function
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
println("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow();
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
let storyboard = UIStoryboard(name: "YourStoryBoardFileName", bundle: nil)
var viewController = storyboard.instantiateViewControllerWithIdentifier("viewControllerIdentifer") as AnotherViewController
viewController.passedValue = currentCell.textLabel.text
self.presentViewController(viewContoller, animated: true , completion: nil)
}
You asked:
How do I get the label of the cell when it is selected and then also pass that to another ViewController?
I might suggest rephrasing the question as follows: "How do I retrieve the data associated with the selected cell and pass it along to another view controller?"
That might sound like the same thing, but there's an important conceptual distinction here. You really don't want to retrieve the value from the cell label. Our apps employ a MVC paradigm, so when you want to pass data information from one scene to another, you want to go back to the model (the items array), not the view (the text property of the UILabel).
This is a trivial example, so this distinction is a bit academic, but as apps get more complicated, this pattern of going back to the model becomes increasingly important. The string representation from the cell is generally is a poor substitute for the actual model objects. And, as you'll see below, it's just as easy (if not easier) to retrieve the data from the model, so you should just do that.
As an aside, you don't really need a didSelectRowAtIndexPath method at all in this case. All you need is a segue from the table view cell to the destination scene, give that segue a unique identifier (Details in my example), and then implement prepare(for:sender:):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DetailsViewController {
let selectedRow = tableView.indexPathForSelectedRow!.row
destination.selectedValue = items[selectedRow]
}
}
Alternatively, if your segue is between the cell and destination scene, you can also use the sender of the prepare(for:sender:):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DetailsViewController {
let cell = sender as! UITableViewCell
let selectedRow = tableView.indexPath(for: cell)!.row
destination.selectedValue = items[selectedRow]
}
}
But the idea is the same. Identify what row was selected, and retrieve the information from the model, the items array.
The above is Swift 3. For Swift 2.3, please see the previous version of this answer.
Okay..Its been 2 days I was searching for the answer that how could I be able to save the selected UITableViewCell label text data and display that data to an another label on an another View Controller which will come out after tapping on a cell. At last I have completed with the task and its successful. Here is the complete code with steps using Swift.I am using Xcode 6.4.
Step 1.
I have Two class assigned to the storyboard view controllers named "iOSTableViewControllerClass.swift" which is a Table View Controller and "iOSTutorialsViewControllerClass.swift" which is a normal View Controller.
Step 2.
Now make segue from iOSTableViewControllerClass to iOSTutorialsViewControllerClass by Control-dragging on the storyboard area and choose "show" from drop down menu. Click on this highlighted button according to the below image and perform the segue.
Step 3.
Now select the segue by clicking on the storyboard and give it an identifier on the Attributes Inspector. In this case I named it as "iOSTutorials"
Step 4.
Now on this step put a label on your cell as well as on the other view controller and make outlets of them on their corresponding classes.
In my case those are "#IBOutlet weak var iOSCellLbl: UILabel!" and " #IBOutlet weak var iOSTutsClassLbl: UILabel!".
Step 5.
Make a string type variable on the first Table View Controller Class. I did this as "var sendSelectedData = NSString()" also Make a string type variable on the second class. I did this as "var SecondArray:String!".
Step 6.
Now we are ready to go.
Here is the complete Code for first Class --
// iOSTableViewControllerClass.swift
import UIKit
class iOSTableViewControllerClass: UITableViewController, UITableViewDataSource,UITableViewDelegate {
// Creating A variable to save the text from the selected label and send it to the next view controller
var sendSelectedData = NSString()
//This is the outlet of the label but in my case I am using a fully customized cell so it is actually declared on a different class
#IBOutlet weak var iOSCellLbl: UILabel!
//Array for data to display on the Table View
var iOSTableData = ["Label", "Button", "Text Field", "Slider", "Switch"];
override func viewDidLoad() {
super.viewDidLoad()
//Setting the delegate and datasource of the table view
tableView.delegate = self
tableView.dataSource = self
//Registering the class here
tableView.registerClass(CustomTableViewCellClassiOS.self, forCellReuseIdentifier: "CellIDiOS")
//If your using a custom designed Cell then use this commented line to register the nib.
//tableView.registerNib(UINib(nibName: "CellForiOS", bundle: nil), forCellReuseIdentifier: "CellIDiOS")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return iOSTableData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellIDentifier = "CellIDiOS"
//In this case I have custom designed cells so here "CustomTableViewCellClassiOS" is the class name of the cell
var cell:CustomTableViewCellClassiOS! = tableView.dequeueReusableCellWithIdentifier(CellIDentifier, forIndexPath: indexPath) as? CustomTableViewCellClassiOS
if cell == nil{
tableView.registerNib(UINib(nibName: "CellForiOS", bundle: nil), forCellReuseIdentifier: CellIDentifier)
cell = tableView.dequeueReusableCellWithIdentifier(CellIDentifier) as? CustomTableViewCellClassiOS
}
//Here we are displaying the data to the cell label
cell.iOSCellLbl?.text = iOSTableData[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
// Get Cell Label text here and storing it to the variable
let indexPathVal: NSIndexPath = tableView.indexPathForSelectedRow()!
println("\(indexPathVal)")
let currentCell = tableView.cellForRowAtIndexPath(indexPathVal) as! CustomTableViewCellClassiOS!;
println("\(currentCell)")
println("\(currentCell.iOSCellLbl?.text!)")
//Storing the data to a string from the selected cell
sendSelectedData = currentCell.iOSCellLbl.text!
println(sendSelectedData)
//Now here I am performing the segue action after cell selection to the other view controller by using the segue Identifier Name
self.performSegueWithIdentifier("iOSTutorials", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//Here i am checking the Segue and Saving the data to an array on the next view Controller also sending it to the next view COntroller
if segue.identifier == "iOSTutorials"{
//Creating an object of the second View controller
let controller = segue.destinationViewController as! iOSTutorialsViewControllerClass
//Sending the data here
controller.SecondArray = sendSelectedData as! String
}
Here is the complete code for the second Class..--
// iOSTutorialsViewControllerClass.swift
import UIKit
class iOSTutorialsViewControllerClass: UIViewController {
//Creating the Outlet for the Second Label on the Second View Controller Class
#IBOutlet weak var iOSTutsClassLbl: UILabel!
//Creating an array which will get the value from the first Table View Controller Class
var SecondArray:String!
override func viewDidLoad() {
super.viewDidLoad()
//Simply giving the value of the array to the newly created label's text on the second view controller
iOSTutsClassLbl.text = SecondArray
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I do it like this.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedName = nameArray[indexPath.row]
let newView: nextViewName = self.storyboard?.instantiateViewController(withIdentifier: "nextViewName") as! nextViewName
newView.label.text = selectedValue
self.present(newView, animated: true, completion: nil)
}

Get the IndexPath from inside a UITableViewCell subclass in Swift

I have a custom UITableViewCell subclass and its associated xib. I have a UILabel and a UIButton in this cell and I have wired the touch up inside action of the button to the subclass.
What I need is when that button in the cell is tapped, to get the indexpath of the cell which has that button. And maybe send it back to the view controller via a delegate or something.
Since I'm inside a UITableViewCell subclass, I can't use a solution like this because I don't have a reference to the tableview from inside the cell subclass. Upon further investigation I found another solution and I implemented it in Swift like this.
import UIKit
class ContactCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
selectionStyle = .None
}
#IBAction func callButtonPressed(sender: UIButton) {
let indexPath = (self.superview as UITableView).indexPathForCell(self)
println("indexPath?.row")
}
}
But when I tap on the button, it crashes with an error message saying Swift dynamic cast failed.
Any idea what's wrong with my code?
Or I'm open to any other suggestions which would allow me to achieve the desired result in any other way.
Thank you.
Sounds like you need a delegate:
Delegates in swift?
Then just pass the cell itself as a parameter to the delegate, and then you can easily do tableView.indexPathForCell(cellFromDelegateMethod)
Hey you can use "Tag" of the button also.Inside the cellForRowAt method of table delegate u can tag the button with Indexpath.row . here is the example what i m tried to say.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// get ur cell nib .As it has a button
cell.startOrConntinuBtn.addTarget(self, action: #selector(sumbitOrContinue), for: .touchUpInside)
cell.startOrConntinuBtn.tag = indexPath.row }
and in the touch method "sumbitOrContinue" -
func sumbitOrContinue(sender: UIButton!) {
let tag = sender.tag
// do what you want to do like this example
let detail = self.detailList[tag]
let vc = self.storyboard?.instantiateViewController(withIdentifier: "mockExamInt") as! MockWindowVc
vc.detailId = detail.id
self.navigationController?.pushViewController(vc, animated: true)}
UIButton.Type really does not have member superview, but sender have
var cell: UITableViewCell = sender.superview.superview as UITableViewCell

Resources