I have a button in a custom cell, and it is not doing anything when I click on it. I tried mistyping the addTarget method on purpose so it will crash, so I can get conformation that the button is getting called, but the app won't crash. Why is nothing happening? Below is the code for the custom cell and the tablecell.
class ProfileMusicCell: UITableViewCell {
#IBOutlet weak var customtitle: UILabel!
#IBOutlet weak var customartist: UILabel!
#IBOutlet weak var playbutton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
Below is the code for the table view
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ProfileMusicCell
cell.customtitle.text = ret[indexPath.row]
cell.customartist.text = ter[indexPath.row]
cell.customtitle.font = UIFont(name: "Lombok", size: 22)
cell.customtitle.textColor = UIColorFromRGB("4A90E2")
cell.customartist.font = UIFont(name: "Lombok", size: 16)
cell.customartist.textColor = UIColor.blackColor()
cell.playbutton.tag = indexPath.row
//I am purposely leaving out the : so the app can crash, but it is not crashing.
cell.playbutton.addTarget(self, action: "playmymusic", forControlEvents: .TouchUpInside)
}
func playmymusic(sender: UIButton!) {
let playButtonrow = sender.tag
print(ret[playButtonrow])
print(ter[playButtonrow])
}
I think the issue is that you're calling the playmymusic without the colon. The colon is needed because of the sender parameter.
The compiler is trying to call a method with this name:
func playmymusic()
instead of the real one:
func playmymusic(sender: UIButton!)
So just try to add the colon (:) at the end of action like this:
cell.playbutton.addTarget(self, action: "playmymusic:", forControlEvents: .TouchUpInside)
This is a legacy of Objective-c way to call the methods (send the messages) and I know it's a little bit confusing.
Related
I want to create multiple choice question app in which i want to display four options with one selectable answer using radio button but I am not able to understand how to do it using array , Any help will be appreciated
!!!
I herreby attached my code --
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var topicLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
var dictionary1 = [Int:String]()
var dictionary2 = [Int:Array<String>]()
override func viewDidLoad() {
dictionary1 = [0:"Whether you have experienced Pricking-pain, Desquamation,itching or dry skin sensation during seasonal alternate.", 1:"Whether your skin apt to flush( Redness) in hot humid environment ", 2:"Whether your skin has multiple disernible dilated capillaries.", 3:"whether you have once been diagnosed atopic dermatitis or seborrheic dermatitis."]
dictionary2 = [0:["Never","Seldom","Usually","Always"],1:["Never","Seldom","Usually","Always"],2:["Never","Seldom","Usually","Always"],3:["Yes", "No"]]
titleLabel.text = "Fill Skin Type Survey Form "
titleLabel.textColor = UIColor.black
topicLabel.text = "Are You with sensitive skin type ?"
topicLabel.font = UIFont.boldSystemFont(ofSize: 18)
let homeNib = UINib(nibName: "DemoTableViewCell", bundle: nil)
self.tableView.register(homeNib, forCellReuseIdentifier: "DemoTableViewCell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dictionary1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:DemoTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "DemoTableViewCell", for: indexPath) as! DemoTableViewCell
// FOR FIRST DICTIONARY
cell.questionLabel.text = dictionary1[indexPath.row]
cell.questionLabel.font = UIFont.boldSystemFont(ofSize: 16)
// FOR SECOND DICTIONARY
cell.optionsLabel.text = dictionary2[indexPath.row]?.joined(separator: " ")
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 350.0
I want to display dictionary 2 along with radio button for selecting an option , here is screenshot of my expected output
You can get the support from so many GitHub Libraries:
https://github.com/DavydLiu/DLRadioButton
https://github.com/onegray/RadioButton-ios (No longer actively maintained)
https://github.com/alhazmy13/RadioButtonSwift3
https://github.com/xxi511/radioButton-swift
https://github.com/VenkateshYadavP/PVRadioButton
https://github.com/thegoal/ISRadioButton
Or else if u want to do that programmatically using UIButton lemme know i can share the code with you.
#IBAction func btnRadioCategoryClicked(_ sender: UIButton) {
for button in btnALLTerritory {
if sender.tag == button.tag{
button.isSelected = true;
button.setImage(#imageLiteral(resourceName: "ic_Radio_filled"), for: .normal)
}else{
button.isSelected = false;
button.setImage(#imageLiteral(resourceName: "ic_Radio_Empty"), for: .normal)
}
}
}
You need to take the Group Outlets of all your UIButton and make some logic like this if you prefer to do that programmatically. Or also you can make an array to store the id of Selected button tag. And use like to select and Unselect a UIButton with that logic
Hope this help.
Simple Demo for Radio Button
You can download the demo code from here Demo Of Radio Button
By referring Abhirajsinh solution, I have created two buttons in interface and connected to controller. Make sure that you have changes tag value in attribute for button1(Tag = 0) and button2(Tag = 1). Also remove selected images in interface for each button.
class AddWorkExperienceViewController: UIViewController {
// MARK: - IBOutlets
var btnALLTerritory = [UIButton]()
#IBOutlet weak var doButton: UIButton!
#IBOutlet weak var dontButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
btnALLTerritory = [doButton,dontButton]
}
// MARK: - Actions
#IBAction func btnRadioCategoryClicked(_ sender: UIButton) {
for button in btnALLTerritory {
if sender.tag == button.tag{
button.isSelected = true;
button.setImage(#imageLiteral(resourceName: "radioButton-selected"), for: .normal)
}else{
button.isSelected = false;
button.setImage(#imageLiteral(resourceName: "radioButton-unselected"), for: .normal)
}
}
}
}
If you are using tableview for options then save the state of the each cell radio button in Model Array. Once use click on radio button, change the state of radio button and reload table view. Custom UI will be the best way to implement.
Hello I'm trying to figure out how to call a UIButton inside a custom cell within a UItable in storyboard. At the moment I have a library that creates a sidemenu working just fine (more info here) and I can see the button I placed when I launch the simulator. However, when I click on the button the action is not triggered, can you please guide me as to how I can achieve this?
Important to note that the table was create entirely in storyboard.
My work in progress code within TopratedVC.swift to get the button to trigger the action:
override func viewDidLoad() {
super.viewDidLoad()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewVibrantCell") as! CellClassMenu
cell.sendFeedBackBtn.tag = indexPath.row
cell.sendFeedBackBtn.addTarget(self, action: "sendFeedBackBtnAction:", forControlEvents: .TouchUpInside)
cell.contentView.userInteractionEnabled = false //tried with true as well, no difference
cell.bringSubviewToFront(cell.sendFeedBackBtn)
cell.userInteractionEnabled = true
return cell
}
func sendFeedBackBtnAction(sender: UIButton){
print("sendFeedBackBtnAction tapped")
}
My UITableViewVibrantCell.swift file contains the following:
import UIKit
class UITableViewVibrantCell: UITableViewCell {
#IBOutlet var sendFeedBackBtn: UIButton!
}
My sndFeedBackBtn has a referencing outlet to UITableViewVibrantCellsendFeedBackBtn which has a class of UITableViewVibrantCell. What am I doing wrong? Thank you.
What it looks like in simulator:
In your post, you show a UITableViewVibrantCell class, and dequeue a cell with the "UITableViewVibrantCell" identifier, but cast it as CellClassMenu?
Anyhow, it would be better practice to create a cell delegate for actions, and let your controller decide the implementation, rather than adding a target every time the cell is dequeued. You can do that like so:
UITableViewVibrantCell
import UIKit
protocol UITableViewVibrantCellDelegate: NSObjectProtocol {
func buttonPressed(sender: UIButton)
}
class UITableViewVibrantCell: UITableViewCell {
var delegate: UITableViewVibrantCellDelegate?
#IBOutlet var feedbackButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
feedBackButton.addTarget(self, action: #selector(self.buttonPressed(_:)), forControlEvents: .TouchUpInside)
}
func buttonPressed(sender: UIButton) {
delegate?.buttonPressed(sender)
}
}
TopratedVC
class TopratedVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewVibrantCell") as! UITableViewVibrantCell
cell.delegate = self
return cell
}
// MARK: - UITableViewVibrantCellDelegate
func buttonPressed(sender: UIButton) {
print("feedbackButton tapped")
}
}
Selectors ("sendFeedBackBtnAction:") can't pass parameters. And a param isn't needed in the sendFeedBackBtnAction function since you're calling it only for this button. So change I'd change it to simply...
func sendFeedBackBtnAction()
then I'd also recommend changing your selector to a more updated swift version...
cell.sendFeedBackBtn.addTarget(self, action: #selector(sendFeedBackBtnAction), forControlEvents: .TouchUpInside)
So basically I am trying to do this:
I have a TableView that I load a custom cell (xib) into it. This custom cell has its own corresponding custom class to go with it. The cell loads just fine but the button is not clickable (at all, as in you don't even see any type of indication that the button was clicked at all). I did some googling, tried to set the action in the cell, tried using a delegate to handle the action. I am lost.
Here is the code from the files:
ViewController.swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Use your cell's reuse identifier and cast the result
// to your custom table cell class.
let cell = tableView.dequeueReusableCellWithIdentifier("ReserveTableViewCell", forIndexPath: indexPath) as! ReserveTableViewCell
cell.delegate = self
let button = cell.locationButton.viewWithTag(1) as? UIButton
button?.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
cell.pickupDate.text = "Today"
cell.returnDate.text = "Tomorrow"
//cell.locationButton.addTarget(self, action: #selector(loc), forControlEvents: .TouchUpInside)
return cell
}
func loc(sender: UIButton!) {
print("here")
}
CustomCell.swift
import UIKit
protocol ReserveTableViewCellDelegate {
func pickupLocationClick(cell: ReserveTableViewCell)
}
class ReserveTableViewCell : UITableViewCell {
#IBOutlet weak var searchButton: UIButton!
#IBOutlet weak var compactIcon: UIImageView!
#IBOutlet weak var midsizeIcon: UIImageView!
#IBOutlet weak var suvIcon: UIImageView!
#IBOutlet weak var luxuryIcon: UIImageView!
#IBOutlet weak var sportIcon: UIImageView!
#IBOutlet weak var pickupIcon: UIImageView!
#IBOutlet weak var pickupDate: UILabel!
#IBOutlet weak var returnDate: UILabel!
#IBOutlet weak var locationButton: UIButton!
var delegate: ReserveTableViewCellDelegate?
#IBAction func locationButtonAction(sender: AnyObject) {
delegate?.pickupLocationClick(self)
}
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
}
}
Some code is still left from other attempts (which is why the protocol method doesn't match the "loc" that is now defined in the viewcontroller.swift file.
In my TableView in storyboard I have selection turned off, when it is on and you tab on the cell it makes it all look "dim" so to speak.
I have the custom class set in my tableview and the outlets/actions are link in IB.
Anyone?
In my experience, it is possible to add functionality to the button in both the Cell file and in the ViewController file (which holds your TableView as a member)
ViewController.swift
#IBAction func locationButtonAction(sender: AnyObject) {
// Do Some Action Here (Which interacts with data members of View
}
CustomCell.swift
#IBAction func locationButtonAction(sender: AnyObject) {
// Do Another Action (Which interacts with data members of the cell)
}
Both of these functions can be linked to the TouchUpInside of the Cell button using the Storyboard Editor!
Best of luck!
Couple confusing things here...
let button = cell.locationButton.viewWithTag(1) as? UIButton
This means, hey locationButton, look in your subviews to find viewWithTag of 1. Not what you want. Just use
let button = cell.locationButton
Then you need to decide what action you're calling and what class does it live in. If you want the button to call an action in the ViewController class you add a target like:
button.addTarget(self, action: #selector(ViewController.loc(_:)), forControlEvents: .TouchUpInside)
If you want the button to call an action inside the ReserveTableViewController class, which honestly is pretty odd, you need a way to reference that class
button.addTarget(myReferenceToTheReserveTableViewControllerClass, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
What you may be actually looking for is for the button to call a method inside the cell class, in which you can then respond as necessary or delegate out to another class, which would then be:
button.addTarget(cell, action: #selector(ReserveTableViewCell.loc(_:)), forControlEvents: .TouchUpInside)
I have set up project just like you did. One thing i noticed in your in ViewController.swift is that you have written following code.
let button = cell.locationButton.viewWithTag(1) as? UIButton //If you will print or debug this button you will see nil
print("Button: \(button)") //prints "Button: nil"
button?.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
Above code is not adding target for your Button. It is adding target for your Buttons subview which has tag value 1. Which is actually nil. Try following code.
cell.locationButton.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)(self, action: #selector(clicked), forControlEvents: .TouchUpInside)
Try the following code in your ViewController.swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Use your cell's reuse identifier and cast the result
// to your custom table cell class.
let cell = tableView.dequeueReusableCellWithIdentifier("ReserveTableViewCell", forIndexPath: indexPath) as! ReserveTableViewCell
cell.delegate = self
//let button = cell.locationButton.viewWithTag(1) as? UIButton
//button?.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
cell.locationButton.addTarget(self, action: #selector(loc), forControlEvents: .TouchUpInside)
cell.pickupDate.text = "Today"
cell.returnDate.text = "Tomorrow"
return cell
}
func loc(sender: UIButton!) {
print("here")
}
I'm trying to build a custom cell with different button inside, but when I tap "follow button" in on cell and color this button it seems that other follow button get a color too...Also if I scroll up and down my tableView other button randomly get color...I'm still learning how to use custom cell...
Here there is my custom cell
class customCell: UITableViewCell
{
#IBOutlet weak var follow: UIButton!
#IBOutlet var comment: UIButton?
#IBOutlet var share: UIButton?
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cellPost = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! customCell
cellPost.tag = Array(postToPrint.keys)[indexPath.row]
cellPost.follow?.tag = Array(postToPrint.keys)[indexPath.row]
cellPost.follow?.addTarget(self, action: "follow:", forControlEvents: .TouchUpInside)
return cellaPost
}
}
Here there is my function follow
func follow(sender: UIButton)
{
let postSelected = sender.tag
// In order to get indexPath from int values
let indexPath = NSIndexPath(forRow: postSelected, inSection: 1)
let cell = table.cellForRowAtIndexPath(indexPath) as! customCell
cell.follow.setTitleColor(UIColor.redColor(), forState: UIControlState)
idPostClicked = postSelected
sendHttpRequest(postClicked : idPostClicked)
}
I'm giving as tag to every cell my dictionary keys. Later I want to take cell.tag and send it as parameter in sendHttpRequest method. If I put my button function inside my customCell I want to get the cell in which there is my followButton so I can send a request with cell.tag.
However text get colored in other cell when I click only one...:/
Hmm, I feel like you are going about this in the wrong way. I would rather move the func follow into the cell itself. There's no reason for the tableView to handle this logic since it's the cell who'd like to change elements it can access on its own. Also, if you move the logic into the cell then you won't need tags or add targets etc.
class customCell: UITableViewCell
{
#IBOutlet weak var follow: UIButton!
#IBOutlet var comment: UIButton?
#IBOutlet var share: UIButton?
// Connect the follow button to this function as an action
#IBAction followPressed(sender: UIButton) {
follow.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellPost = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! customCell
return cellaPost
}
This should do the trick, I believe.
Edit
Added some missing code for UIControlState for the button. If this doesn't work could you upload a sample project? Hard to pinpoint what you are trying to do with only this piece of code.
I have this:
let mapsbut = cell.viewWithTag(912) as! UIButton
mapsbut.addTarget(self, action: "mapsHit:", forControlEvents: UIControlEvents.TouchUpInside)
and
func mapsHit(){
// get indexPath.row from cell
// do something with it
}
How is this accomplished?
You can always use the tag from your button to pass or hold a value, or a var inside of your custom cell implementation. For example, if you have your button as an outlet in your UITableViewCell (for instance):
class MenuViewCell: UITableViewCell {
#IBOutlet weak var titlelabel: UILabel!
#IBOutlet weak var button: UIButton! {
didSet {
button.addTarget(self, action: "mapsHit:", forControlEvents: UIControlEvents.TouchUpInside)
}
}
func mapsHit(sender: UIButton){
let indexPathOfThisCell = sender.tag
println("This button is at \(indexPathOfThisCell) row")
// get indexPath.row from cell
// do something with it
}
}
Notice here, that you need to set sender:UIButton as a parameter when you set "mapsHit:". This will be the button itself in wich the user has tapped.
Now, for this to work, your tag can not be "912". Instead when you build your cell, assign to the tag property of your button, the value of it's indexPath.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MenuViewCell", forIndexPath: indexPath) as! MenuViewCell
cell.titlelabel?.text = data[indexPath.row].description
cell.button.tag = indexPath.row
return cell
}
...one solution could be to have a var inside your class holding the indexPath of the last cell tapped, then you can use that value inside your mapsHit() function.