I have a button in a custom cell
class CardTableViewCell: UITableViewCell {
#IBOutlet weak var detailsButton: UIButton!
}
in my view controller then I do this
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//.....more code....
openDealCell.detailsButton.addTarget(self, action: "push:", forControlEvents: UIControlEvents.TouchUpInside)
}
and then:
func push(sender:AnyObject) {
println("tap")
}
But when I clicked the button nothing happens.
What I am doing wrong?
Fix it! The problem was not in the code but in my cell in the storyboard:
where user interaction for the cell wasn't enabled and all the other view didn't allow the user interaction.
Right now I created demo project with exactly the same code as your and it works. Please check here at GitHub. The issue definitely in the other stuff that you didn't show us, that code does not have any problems
Related
I'm doing todolist app and I need action for button, which on tapped will do change image in a cell which I tapped on it. Cell retrieves data from Firebase to UITableView. I used button and image outlets and both reported this error:
The button from the TaskViewController to the UIButton is invalid. Outlets cannot be connected to repeating content.
I have this code for retrieves data to cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TasksCell", for: indexPath) as! TasksCell
let arrayTasks = tasks[indexPath.row]
cell.taskName.text = arrayTasks.content
return cell
}
and I have this in Storyboard
object left of the label is button.
The button picture is set in storyboard.
I don't know how to do it, because I don't have much experience. Please help me.
Try:
Open the Identity Inspector.
Click the prototype cell.
Set the Class to TasksCell (in my example, it is WorkTableViewCell).
Click in the Module field, empty it, and press enter. It should change to Current - project_name_here (for example, Current - Artistry.
Here's a screenshot of what it should look like. Check it to make sure you selected the right items in the right order:
Then, delete the old outlet(s) to the cell (button, label, everything) from the Connections Inspector. Do that step while selecting the cell, and then while selecting the view controller (but while selecting the view controller, only delete the outlet to the "completed" button).
And finally, re-add them by opening the code (in a new window) for your TasksCell class, not the TaskViewController class (probably in TasksCell.swift), and directly under the line:
class TasksCell: UITableViewCell {
(or similar), hold control and drag the button, label, etc. as shown:
And finally, finish creating the new outlets only from the label, button, etc. to the TasksCell class as mentioned earlier (see note below before pressing "connect"):
Change the Name as necessary. It could be something like taskName for the label, or completedButton for the button. Do not change the Type or any other fields. Press "connect", and the code from your question should work.
In your TasksCell class, connect the button to the cell, and you can access it easier (yeah agree to #ingraham, you can't connect it to your view controller):
class TasksCell: UITableViewCell {
#IBOutlet weak var buttonCheckbox: UIButton!
#IBOutlet weak var taskName: UILabel!
#IBOutlet weak var updatedDate: UILabel!
}
You can use image view for button. Also you can use this method for changing image
override func tableView(_ tableView: UITableView, didSelec tRowAt indexPath: IndexPath) {}
Edit:
I made a table view cell class:
class TableViewCell: UITableViewCell {
#IBAction func bAction(_ sender: Any) {
button.titleLabel?.text = "asdaf"
}
#IBOutlet weak var button: 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
}
}
then I edit tableView function:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TableViewCell! = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as? TableViewCell
cell.textLabel?.text = "abc"
// Configure the cell...
cell.bAction(Any.self)
return cell
}
I'm using a table view with custom cell. In this custom cell I got a like button.
when I tap this button I want this one to get colored. I figure how to color this button but I need to do reload data for displaying it with color. But when I call "table.reloadData()" there is a little scroll view stretch automatically.
There is a way to display changes without reloadData() or to disable scrollView stretching?
Have you tried reloading just the row that you have clicked on?
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Top
For some things, though, you shouldn't have to reload at all. If all you want is to change the background colour of the cell, you can do it like this. I now notice that you're working in Objective-C and my example is Swift - hopefully it's still clear enough :-)
First define a custom cell - mine is a simple one with just a label and a button, you will already have something similar. I'm not sure if you need to change the colour of the cell, or the button, so I have done both
import UIKit
class myCell: UITableViewCell
{
#IBOutlet weak var labelTitle: UILabel!
#IBOutlet weak var cmdButton: UIButton!
#IBAction func cmdButtonClicked(sender: AnyObject)
{
self.backgroundColor = UIColor.redColor()
cmdButton.backgroundColor = UIColor.blueColor()
print("click \(sender.tag)")
}
}
If you do need to keep a track of which button has been clicked, you will need to set the tag in cellForRowAtIndexPath - but you may not even need this
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell:myCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! myCell
cell.labelTitle.text = data[indexPath.row]
cell.cmdButton.tag = indexPath.row
return cell
}
I am trying to do what I believed was a simple task using Swift. I have created a Custom TableView Cell and added a button to it. I want to be able to just see when you click on the button some action take place. Unfortunately, when I click on the button there is nothing happening. Can someone shed some light on this? I have placed the code below:
Custom TableView Cell:
import UIKit
class TestTableViewCell: UITableViewCell {
#IBOutlet weak var testBtn: 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
}
func buttonTappedOnCell()
{
println("buttonTapped!")
}
}
Below is the code in the View Controller which the call is being made:
func tableView(tableView: UITableView,
cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {
tableView.registerNib(UINib(nibName:"TestTableViewCell", bundle:nil), forCellReuseIdentifier:"TestButtonCell")
let cell =
tableView.dequeueReusableCellWithIdentifier("TestButtonCell", forIndexPath: indexPath) as TestTableViewCell
cell.testBtn.addTarget(cell, action: "buttonTappedOnCell", forControlEvents: UIControlEvents.TouchDown)
return cell
}
I also tried changing the call to include the ':' -> cell.testBtn.addTarget(cell, action: "buttonTappedOnCell:", forControlEvents: UIControlEvents.TouchDown) but this did not work. Another thing I tried is moving the call function into the view controller and having the target action point to self. This unfortunately did not work either. A quick example of this working would be great. At the end of day would like to be able to have a custom table view cell that contains 6 radio buttons allowing the user to select just one. But baby steps first at this point. Thanks for any help.
I think the issue is caused by the event you specified in the code.
cell.testBtn.addTarget(cell, action: "buttonTappedOnCell", forControlEvents: UIControlEvents.TouchDown)
Change that ToouchDown to TouchUpInside
cell.testBtn.addTarget(cell, action: "buttonTappedOnCell", forControlEvents: UIControlEvents.TouchUpInside)
Also why are you setting it programmaticaly ? From your code I think you have the button on your storyboard. So why should you add the IBAction programmaticaly ? (Since the action is also invoked on the same class).
Declare your buttonTappedOnCell as an IBAction and connect it directly to your button on storyboard/xib.
What I'm facing is I've developed code in Swift. It has a some custom cells and UIButtons in them. The buttons are IBOutlet Connections with properties in their respective Cells and actions against them are bound in the same classes. Now the Question is that it works perfect in iOS 8. But I don't know what's wrong with iOS 7 whenever I touch the button, the complete cell is tapped and Tableview's didSelectRowAtIndexPath: is called. What I've done so far is
Check .userInteractionEabled for parent views and cell and changing it's values
Remove buttons and re add them as found on different forums but no luck
Checked Tableview's delegate methods numberOfSections, numberOfRowsInsection: and heightForRowAtIndexPath: and changed their return types to NSInteger and CGFloat as found on stackoverflow Against a Question.
Has anyone else faced this issue and found solution so far?
Edit
Checked by reseting target action of UIButton after setting values to cell. No Luck
I have tested your problem. Its running fine for me. Please see my code below.
In TestTableViewController.swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as CustomCell
// Configure the cell...
cell.testButton.addTarget(cell, action: "testButtonClicked", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
NSLog("didSelectRowAtIndexPath called")
}
In CustomCell.swift
class CustomCell: UITableViewCell {
#IBOutlet var testButton: 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
}
func testButtonClicked() {
NSLog("Button Clicked")
}
}
When I clicked on the button it logs "Button Clicked" and when clicked on cell it logs "didSelectRowAtIndexPath called". You might be doing something wrong in reset() function or second last function.
I have done the code below in my app and it is working fine.
Do not try to code on your custom tableview cell.
You can get values of that cell in your viewcontroller.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row==0)
{
static NSString *simpleprice = #"Price";
price = (PriceCell *)[tableView dequeueReusableCellWithIdentifier:simpleprice];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PriceCell" owner:self options:nil];
price = [nib objectAtIndex:0];
[price.btnPrice addTarget:self action:#selector(buyPressed) forControlEvents:UIControlEventTouchUpInside];
}
return price;
}
Hope this helps you. This works for ios7 and ios8 also.
Thanks...
i have faced such issue after long time digging it, i found root cause and it was in Cell XIB
what i did as Before:
i) First i have added CustomCell .h and .m.
ii) After then i have added XIB by new file option, you have noticed,
there is option like "View" that's i have selected and add in to the bundle. Bind it with my CustomCell.h.
Solution :
i) Add XIB by new file option, Choose View in user interface.
ii) In XIB you can see view at left panel. delete that view.
iii) Drag and drop there UITableViewCell from User Interface panel. After complete this steps XIB would be seen similar something like below image.
Change your cell.button Action target to self, and copy your button action method into viewController class (.mm) file where the UITableView is available.
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