Swift unrecognized selector sent to instance error - ios

I recently converted my project from Objective-C to Swift and in doing so I acquired this error whenever I click a button in the table view's cell. I have multiple cells being filled with information from a mysql server. I have two buttons, a follow button and followed button, when one is clicked the other is supposed to show. I've been working on this for a while but I've been stuck on this error.
Error I'm getting when I click the button in the tableview
CustomCellSwift[1425:372289] -[CustomCellSwift.ViewController followButtonClick:]: unrecognized selector sent to instance 0x100b13a40
In CustomCell.swift
class CustomCell: UITableViewCell {
#IBOutlet weak var firstStatusLabel: UILabel!
#IBOutlet weak var secondStatusLabel: UILabel!
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var followButton: UIButton!
#IBOutlet weak var followedButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.followButton.isHidden = true
self.followedButton.isHidden = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func populateCell(_ testObject: Test, isFollowed: Bool, indexPath: IndexPath, parentView: Any) {
// Loading Background Color
self.backgroundColor = UIColor.white
// Loading Status Labels
self.firstStatusLabel.text = testObject.testStatus1
self.secondStatusLabel.text = testObject.testStatus2
self.firstStatusLabel.isHidden = true
self.secondStatusLabel.isHidden = true
if isFollowed {
self.followedButton.tag = indexPath.row
self.followedButton.addTarget(parentView, action: Selector(("followedButtonClick")), for: .touchUpInside)
self.followedButton.isHidden = false
self.followButton.isHidden = true
// Status Labels
self.firstStatusLabel.isHidden = false
self.secondStatusLabel.isHidden = false
}
else {
self.followButton.tag = indexPath.row
self.followButton.addTarget(parentView, action: Selector(("followButtonClick:")), for: .touchUpInside)
self.followedButton.isHidden = true
self.followButton.isHidden = false
// Status Labels
self.firstStatusLabel.isHidden = false // True when done testing
self.secondStatusLabel.isHidden = false // True when done testing
}
}
}
ViewController.swift
CellForRowAt indexPath
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let CellIdentifier = "Cell"
var cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! CustomCell
if cell != cell {
cell = CustomCell(style: UITableViewCellStyle.default, reuseIdentifier: CellIdentifier)
}
// Coloring TableView
myTableView.backgroundColor = UIColor.white
// Configuring the cell
var testObject: Test
if !isFiltered {
if indexPath.section == 0 {
testObject = followedArray[indexPath.row]
cell.populateCell(testObject, isFollowed: true, indexPath: indexPath, parentView: self)
}
else if indexPath.section == 1 {
testObject = testArray[indexPath.row]
cell.populateCell(testObject, isFollowed: false, indexPath: indexPath, parentView: self)
}
}
else {
testObject = filteredArray[indexPath.row] as! Test
cell.populateCell(testObject, isFollowed: false, indexPath: indexPath, parentView: self)
}
return cell
}
Follow Button Code
#IBAction func followButtonClick(sender: UIButton!) {
// Adding row to tag
let buttonPosition = (sender as AnyObject).convert(CGPoint.zero, to: self.myTableView)
if let indexPath = self.myTableView.indexPathForRow(at: buttonPosition) {
// Showing Status Labels
let cell = self.myTableView.cellForRow(at: indexPath) as! CustomCell
cell.firstStatusLabel.isHidden = false
cell.secondStatusLabel.isHidden = false
// Change Follow to Following
(sender as UIButton).setImage(UIImage(named: "follow.png")!, for: .normal)
cell.followButton.isHidden = true
cell.followedButton.isHidden = false
self.myTableView.beginUpdates()
// ----- Inserting Cell to Section 0 -----
followedArray.insert(testArray[indexPath.row], at: 0)
myTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .fade)
// ----- Removing Cell from Section 1 -----
testArray.remove(at: indexPath.row)
let rowToRemove = indexPath.row
self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 1)], with: .fade)
self.myTableView.endUpdates()
}
}
Unfollow button code is the same as the follow button.
I think the problem is in CustomCell.swift in the button selector(("")) but the error is saying -[CustomCellSwift.ViewController followButtonClick:] which means in ViewController in the follow button code but I don't know what to do anymore.

Two changes for Swift 3:
The selector should look like:
#selector(ClassName.followButtonClick(_:))
The function should have an underscore:
#IBAction func followButtonClick(_ sender: UIButton!) { ...
Notice that these two should be in the same class, otherwise, make sure you initialize the ClassName class.
If you want the selector method(followButtonClick(_:)) to be in the UITableViewCell class. Remove #IBAction(I don't think you need it there):
func followButtonClick(_ sender: UIButton!) { ...

For Swift3, you need to change the following:
self.followedButton.addTarget(parentView, action: Selector(("followedButtonClick")), for: .touchUpInside)
With:
self.followedButton.addTarget(parentView, action: #selector(self.followButtonClick(_:)), forControlEvents: .touchUpInside)

For Swift 2.2 with Xcode 8:
self.followedButton.addTarget(parentView, action: #selector(CustomCell.followButtonClick(_:)), forControlEvents: .TouchUpInside)

Related

Save user settings using user default swift

I'm working on an application where users can view terms and like or dislike terms.
I'm stack on saving user settings from the table view using user default. I want to save when users click the like or dislike buttons, and when they run the app again the button stays filled
I have a table view cell that contains an outlet for the button and action
import UIKit
class TerminologistTVCell: UITableViewCell {
#IBOutlet weak var btnLike: UIButton!
#IBOutlet weak var btnDislike: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
lconfigureUI()
dconfigureUI()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func lconfigureUI(){
let thumbsdown = UIImage(systemName: "hand.thumbsdown")
let thumbsdownfilled = UIImage(systemName: "hand.thumbsdown.fill")
btnDislike.setImage(thumbsdown, for: .normal)
btnDislike.setImage(thumbsdownfilled, for: .selected)
}
func dconfigureUI(){
let thumbsup = UIImage(systemName: "hand.thumbsup")
let thumbsupfilled = UIImage(systemName: "hand.thumbsup.fill")
btnLike.setImage(thumbsup, for: .normal)
btnLike.setImage(thumbsupfilled, for: .selected)
}
#IBAction func btnLike(_ sender: UIButton) {
sender.isSelected.toggle()
if (sender.isSelected){
btnDislike.isSelected = false
}else{
btnDislike.isSelected = false
}
}
#IBAction func btnDislike(_ sender: UIButton) {
sender.isSelected.toggle()
if (sender.isSelected){
btnLike.isSelected = false
}else{
btnLike.isSelected = false
}
}}
And the ViewController to view the terms and save settings. I tried to save the setting in cellForRow it worked, but when I clicked on the button, it saved for all cells(the button is filled in all cells), not for a cell that I pressed. I want to save for pressed cell
class TerminologistVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var termaArray = MDTerms()
let termName = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return termaArray.arabicTerm.count
}
let userDefaults = UserDefaults.standard
let btnLikePressed = "Likepressed"
let btnDisLikePressed = "DisLikepressed"
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TerminologistTVCell
cell.textLabel?.text = self.termaArray.arabicTerm[indexPath.row]
cell.btnLike.tag = indexPath.row
cell.btnLike.addTarget(self, action: #selector(likeTerm(sender:)), for: .touchUpInside)
cell.btnDislike.tag = indexPath.row
cell.btnDislike.addTarget(self, action: #selector(dislikeTerm(sender:)), for: .touchUpInside)
if userDefaults.bool(forKey: btnLikePressed){
cell.btnLike.isSelected = true
}else{
cell.btnLike.isSelected = false
}
if userDefaults.bool(forKey: btnDisLikePressed){
cell.btnDislike.isSelected = true
}else{
cell.btnDislike.isSelected = false
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
#objc
func likeTerm(sender: UIButton){
print("cell index = \(sender.tag)")
if sender.isSelected{
userDefaults.set(true, forKey: btnLikePressed)
}else{
userDefaults.set(false, forKey: btnLikePressed)
}
}
#objc
func dislikeTerm(sender: UIButton){
print("cell index = \(sender.tag)")
if sender.isSelected{
userDefaults.set(true, forKey: btnDisLikePressed)
}else{
userDefaults.set(false, forKey: btnDisLikePressed)
}
}
My application looks like
ViewController
You are using only two keys in UserDefault which are btnDisLikePressed and btnLikePressed, and clearly you will always get the same values for all cells with all terms. Instead use the termaArray.arabicTerm[indexPath.row] (or in your case cell.textLabel?.text) as the key in UserDefaults.

number of radio buttons in a static tableview cell in swift

I have been trying to add 3 radio buttons for gender selection in a static tableviewcell.But am not able to do that.Can any one help to do this.
func setGenderCell(indexPath : IndexPath) -> UITableViewCell {
let cell : SetGenderTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "SetGenderTableViewCell", for: indexPath) as! SetGenderTableViewCell
cell.subject.text = self.profileData[indexPath.row].getName()
cell.genderImage.image = UIImage(named: self.profileData[indexPath.row].getImage())
cell.maleButton.addTarget(self, action: #selector(self.maleGenderSelect), for: .touchUpInside)
cell.femaleButton.addTarget(self, action: #selector(self.femaleGenderSelect), for: .touchUpInside)
cell.othersButton.addTarget(self, action: #selector(self.othersGenderSelect), for: .touchUpInside)
cell.maleButton.tag = 1
cell.femaleButton.tag = 2
cell.othersButton.tag = 3
return cell
}
#objc func maleGenderSelect(){
let cell : SetGenderTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "SetGenderTableViewCell", for: IndexPath) as! SetGenderTableViewCell
cell.maleRadioImage.image = UIImage(named: "")
cell.femaleRadioImage.image = UIImage(named: "")
cell.othersRadioImage.image = UIImage(named: "")
}
#objc func femaleGenderSelect(){
}
#objc func othersGenderSelect(){
}
Reference Image:
Refer this pseudo Code,
Create GenderCellDelegate
protocol GenderCellDelegate : class {
func genderSelected(_ gender : Gender)
}
Enum For gender
enum Gender : Int {
case male = 1, female, other
}
GenderTableViewCell
class GenderTableViewCell: UITableViewCell {
#IBOutlet weak var btnMale : UIButton!
#IBOutlet weak var btnFemale : UIButton!
#IBOutlet weak var btnOther : UIButton!
weak var delegate : GenderCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
// Your can do below from XIB also
// Set buttons images for selcted and normal state
btnMale.setImage(UIImage(named: "radio-on"), for: .selected)
btnFemale.setImage(UIImage(named: "radio-on"), for: .selected)
btnOther.setImage(UIImage(named: "radio-on"), for: .selected)
btnMale.setImage(UIImage(named: "radio-off"), for: .normal)
btnFemale.setImage(UIImage(named: "radio-off"), for: .normal)
btnOther.setImage(UIImage(named: "radio-off"), for: .normal)
// Optional - if required
btnMale.isSelected = true // For default selection
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func btnMaleSelected(_ sender : UIButton) {
self.btnMale.isSelected = true
self.btnFemale.isSelected = false
self.btnOther.isSelected = false
delegate?.genderSelected(.male)
}
#IBAction func btnFemaleSelected(_ sender : UIButton) {
self.btnMale.isSelected = false
self.btnFemale.isSelected = true
self.btnOther.isSelected = false
delegate?.genderSelected(.female)
}
#IBAction func btnOtherSelected(_ sender : UIButton) {
self.btnMale.isSelected = false
self.btnFemale.isSelected = false
self.btnOther.isSelected = true
delegate?.genderSelected(.other)
}
}
Your Controller
class MyController : UIViewController , UITableViewDelegate, UITableViewDataSource, GenderCellDelegate {
:
:
func genderSelected(_ gender: Gender) {
switch gender {
case .male:
print("Male selected")
break
case .female:
print("Female selected")
break
case .other:
print("Other selected")
break
}
// reload tableview row for gender cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let genderCell = tableView.dequeueReusableCell(withIdentifier: "GenderTableViewCell") as! GenderTableViewCell
genderCell.delegate = self
return genderCell
}
}

Delegate function from protocol not being called

I have a previously working delegate and protocol that since the conversion to Swift 3 is no longer being called.
protocol TaskCellDelegate {
func doneHit(_ cell : TaskCell)
}
class TaskCell : UITableViewCell {
var delegate : TaskCellDelegate?
#IBOutlet weak var label: UILabel!
#IBOutlet weak var detailLabel: UILabel!
#IBOutlet weak var _checkBox: M13Checkbox!
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: #selector(TaskCell.buttonClicked(_:)))
tap.numberOfTapsRequired = 1
_checkBox.addGestureRecognizer(tap)
_checkBox.isUserInteractionEnabled = true
_checkBox.markType = .checkmark
_checkBox.boxType = .circle
_checkBox.stateChangeAnimation = .expand(.fill)
}
func buttonClicked(_ sender:UITapGestureRecognizer) {
delegate?.doneHit(self)
}
}
As you can see, when the _checkBox is tapped it should call the function doneHit in my class (not added because it doesn't seem necessary but I can) but I set a breakpoint and it's never called. I've set my delegate and conformed to the protocol in my class but nothing is happening. The doneHit function is supposed to update my backend but its not being called. If you need more info, I can provide.
Edit 1:
class TasksTVC: UITableViewController, TaskCellDelegate {
func doneHit(_ cell:TaskCell) {
if let indexPath = self.tableView.indexPath(for: cell) {
task = tasksInSectionArray[indexPath.section][indexPath.row]
if task.done == false {
cell._checkBox.setCheckState(.checked, animated: true)
task.done = true
task.completedBy = user
cell.detailLabel.text = "Completed By: \(task.completedBy)"
cell.label.textColor = UIColor.gray
print("cell checked")
}
else {
cell._checkBox.setCheckState(.unchecked, animated: true)
task.done = false
task.completedBy = ""
cell.detailLabel.text = ""
cell.label.textColor = UIColor.black
print("cell unchecked")
}
fb.updateTaskDoneBool(ref, taskID: task.id, taskDone: task.done)
fb.updateTaskCompletedBy(ref, taskID: task.id, taskCompletedBy: task.completedBy)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
cell.selectionStyle = .none
task = tasksInSectionArray[indexPath.section][indexPath.row]
cell.label.text = task.title
if task.done == true {
cell._checkBox.setCheckState(.checked, animated: true)
cell.detailLabel.text = "Completed By: \(task.completedBy)"
cell.label.textColor = UIColor.gray
}
else {
cell._checkBox.setCheckState(.unchecked, animated: true)
cell.detailLabel.text = ""
cell.label.textColor = UIColor.black
}
doneHit(cell)
cell.delegate = self
return cell
}}
Looks like you didn't set correctly the delegate property in your TaskCell instance , I will make a very basic example hopefully it helps you to catch the issue:
Result (Edited)
Code
TableViewController
import UIKit
protocol TaskCellDelegate {
func doneHit(_ cell: TaskCell)
}
class TableViewController: UITableViewController, TaskCellDelegate {
func doneHit(_ cell: TaskCell) {
let alert = UIAlertController(
title: "Info",
message: "button touched in cell",
preferredStyle: .alert
)
present(alert, animated: true, completion: nil)
}
}
extension TableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TaskCell
cell.delegate = self // probably you forgot to set this part?
return cell
}
}
TaskCell (Edited)
Instead creating a new UITapGestureRecognizer to attach to the checkbox, you can use addTarget method to attach event handler for the UIControlEvents.valueChanged value.
import UIKit
import M13Checkbox
class TaskCell: UITableViewCell {
var delegate: TaskCellDelegate?
#IBOutlet weak var checkbox: M13Checkbox!
override func awakeFromNib() {
super.awakeFromNib()
checkbox.addTarget(self, action: #selector(buttonClicked), for: .valueChanged)
}
func buttonClicked() {
delegate?.doneHit(self)
}
}
There are following cases if delegate is not being called:
The action: buttonClicked is not being called.
The View Controller not Conforming to the protocol.
class ViewController: UIViewController, TaskCellDelegate {
The protocol method not implemented inside View Controller.
func doneHit(_ cell : TaskCell) {
print("delegate implementation called")
}
Delegate not assigned in cellForRowAtIndexPathMethod:
cell.delegate = self

get indexPath of UITableViewCell on click of Button from Cell

I have a button (red color cross) in the UITableViewCell and on click of that button I want to get indexPath of the UITableViewCell.
Right now I am assigning tag to each of the button like this
cell.closeButton.tag = indexPath.section
and the on click of the button I get the indexPath.section value like this:
#IBAction func closeImageButtonPressed(sender: AnyObject) {
data.removeAtIndex(sender.tag)
tableView.reloadData()
}
Is this the right way of implementation or is there any other clean way to do this?
Use Delegates:
MyCell.swift:
import UIKit
//1. delegate method
protocol MyCellDelegate: AnyObject {
func btnCloseTapped(cell: MyCell)
}
class MyCell: UICollectionViewCell {
#IBOutlet var btnClose: UIButton!
//2. create delegate variable
weak var delegate: MyCellDelegate?
//3. assign this action to close button
#IBAction func btnCloseTapped(sender: AnyObject) {
//4. call delegate method
//check delegate is not nil with `?`
delegate?.btnCloseTapped(cell: self)
}
}
MyViewController.swift:
//5. Conform to delegate method
class MyViewController: UIViewController, MyCellDelegate, UITableViewDataSource,UITableViewDelegate {
//6. Implement Delegate Method
func btnCloseTapped(cell: MyCell) {
//Get the indexpath of cell where button was tapped
let indexPath = self.collectionView.indexPathForCell(cell)
print(indexPath!.row)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as! MyCell
//7. delegate view controller instance to the cell
cell.delegate = self
return cell
}
}
How to get cell indexPath for tapping button in Swift 4 with button selector
#objc func buttonClicked(_sender:UIButton){
let buttonPosition = sender.convert(CGPoint.zero, to: self.tableView)
let indexPath = self.tableView.indexPathForRow(at:buttonPosition)
let cell = self.tableView.cellForRow(at: indexPath) as! UITableViewCell
print(cell.itemLabel.text)//print or get item
}
Try with the best use of swift closures : Simple, Quick & Easy.
In cellForRowAtIndexPath method:
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellIdentifier", for: indexPath) as! CustomCell
cell.btnTick.mk_addTapHandler { (btn) in
print("You can use here also directly : \(indexPath.row)")
self.btnTapped(btn: btn, indexPath: indexPath)
}
Selector Method for external use out of cellForRowAtIndexPath method:
func btnTapped(btn:UIButton, indexPath:IndexPath) {
print("IndexPath : \(indexPath.row)")
}
Extension for UIButton :
extension UIButton {
private class Action {
var action: (UIButton) -> Void
init(action: #escaping (UIButton) -> Void) {
self.action = action
}
}
private struct AssociatedKeys {
static var ActionTapped = "actionTapped"
}
private var tapAction: Action? {
set { objc_setAssociatedObject(self, &AssociatedKeys.ActionTapped, newValue, .OBJC_ASSOCIATION_RETAIN) }
get { return objc_getAssociatedObject(self, &AssociatedKeys.ActionTapped) as? Action }
}
#objc dynamic private func handleAction(_ recognizer: UIButton) {
tapAction?.action(recognizer)
}
func mk_addTapHandler(action: #escaping (UIButton) -> Void) {
self.addTarget(self, action: #selector(handleAction(_:)), for: .touchUpInside)
tapAction = Action(action: action)
}
}
In Swift 4 , just use this:
func buttonTapped(_ sender: UIButton) {
let buttonPostion = sender.convert(sender.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: buttonPostion) {
let rowIndex = indexPath.row
}
}
You can also get NSIndexPath from CGPoint this way:
#IBAction func closeImageButtonPressed(sender: AnyObject) {
var buttonPosition = sender.convertPoint(CGPointZero, to: self.tableView)
var indexPath = self.tableView.indexPathForRow(atPoint: buttonPosition)!
}
Create a custom class of UIButton and declare a stored property like this and use it to retrieve assigned indexPath from callFroRowAtIndexPath.
class VUIButton: UIButton {
var indexPath: NSIndexPath = NSIndexPath()
}
This is the full proof solution that your indexPath will never be wrong in any condition. Try once.
//
// ViewController.swift
// Table
//
// Created by Ngugi Nduung'u on 24/08/2017.
// Copyright © 2017 Ngugi Ndung'u. All rights reserved.
//
import UIKit
class ViewController: UITableViewController{
let identifier = "cellId"
var items = ["item1", "2", "3"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.title = "Table"
tableView.register(MyClass.self, forCellReuseIdentifier: "cellId")
}
//Return number of cells you need
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! MyClass
cell.controller = self
cell.label.text = items[indexPath.row]
return cell
}
// Delete a cell when delete button on cell is clicked
func delete(cell: UITableViewCell){
print("delete")
if let deletePath = tableView.indexPath(for: cell){
items.remove(at: deletePath.row)
tableView.deleteRows(at: [deletePath], with: .automatic)
}
}
}
class MyClass : UITableViewCell{
var controller : ViewController?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUpViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
let label : UILabel = {
let label = UILabel()
label.text = "My very first cell"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let btn : UIButton = {
let bt = UIButton(type: .system)
bt.translatesAutoresizingMaskIntoConstraints = false
bt.setTitle("Delete", for: .normal)
bt.setTitleColor(.red, for: .normal)
return bt
}()
func handleDelete(){
controller?.delete(cell: self)
}
func setUpViews(){
addSubview(label)
addSubview(btn)
btn.addTarget(self, action: #selector(MyClass.handleDelete), for: .touchUpInside)
btn.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
label.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16).isActive = true
label.widthAnchor.constraint(equalTo: self.widthAnchor , multiplier: 0.8).isActive = true
label.rightAnchor.constraint(equalTo: btn.leftAnchor).isActive = true
}
}
Here is a full example that will answer your question.
In your cellForRow:
#import <objc/runtime.h>
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
setAssociatedObject(object: YOURBUTTON, key: KEYSTRING, value: indexPath)
}
#IBAction func closeImageButtonPressed(sender: AnyObject) {
let val = getAssociatedObject(object: sender, key: KEYSTROKING)
}
Here val is your indexPath object, your can pass any object like you can assign pass cell object and get it in button action.
try this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = (tableView.dequeueReusableCell(withIdentifier: "MainViewCell", forIndexPath: indexPath) as! MainTableViewCell)
cell.myButton().addTarget(self, action: Selector("myClickEvent:event:"), forControlEvents: .touchUpInside)
return cell
}
this function get the position of row click
#IBAction func myClickEvent(_ sender: Any, event: Any) {
var touches = event.allTouches()!
var touch = touches.first!
var currentTouchPosition = touch.location(inView: feedsList)
var indexPath = feedsList.indexPathForRow(atPoint: currentTouchPosition)!
print("position:\(indexPath.row)")
}
class MyCell: UICollectionViewCell {
#IBOutlet weak var btnPlus: UIButton!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
cell.btnPlus.addTarget(self, action: #selector(increment_Action(sender:)),
for: .touchUpInside)
cell.btnPlus.tag = indexPath.row
cell.btnPlus.superview?.tag = indexPath.section
}
#objc func increment_Action(sender: UIButton) {
let btn = sender as! UIButton
let section = btn.superview?.tag ?? 0
let row = sender.tag
}

Swift 2 can not add a slider to a UITableView Cell

I m trying to create a slider cell in a UItableview with swift, it appear, but it's not working, I want to display the value of it in live but it's not working, I tried to use action on the slider itself, I tried changed Editing Changed Method not working too.
Here is my cell code :
import UIKit
class SliderCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var maxLegendLabel: UILabel!
#IBOutlet weak var minLegendLabel: UILabel!
#IBOutlet weak var slider: UISlider!
#IBOutlet weak var answerLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
slider.userInteractionEnabled = true
slider.continuous = true
// slider.addTarget(self, action: #selector(sliderValueChanged), forControlEvents: UIControlEvents.ValueChanged)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func sliderAction(sender: UISlider) {
print("slider ACTION value")
print(sender.value)
}
func sliderValueChanged(sender: UISlider) {
print("slider value")
print(sender.value)
answerLabel.text = "Your choice : " + String(sender.value)
}
func displayBlock(block: Block){
titleLabel.text = block.title
minLegendLabel.text = block.range?.legendMin
maxLegendLabel.text = block.range?.legendMax
slider.minimumValue = Float((block.range?.min)!)!
slider.maximumValue = Float((block.range?.max)!)!
slider.value = 1
}
}
and here is how I declare it in my tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell method :
let cell = tableView.dequeueReusableCellWithIdentifier(CurrentFormTableView.CellIdentifiers.SliderCell, forIndexPath: indexPath) as! SliderCell
cell.displayQuestion(block)
cell.selectionStyle = UITableViewCellSelectionStyle.None
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160.0
return cell
Add this in Table view cell:
sliderDemo = UISlider(frame:CGRectMake(0, 0, 200,20))
var numberOfSteps : NSInteger = numbers.count - 1
sliderDemo.minimumValue = 6.5
sliderDemo.maximumValue = 4.1
sliderDemo.continuous = true
sliderDemo.value = 4.0
sliderDemo.addTarget(self, action: "sliderValueDidChange:", forControlEvents: .ValueChanged)
self.view.addSubview(sliderDemo)
func sliderValueDidChange(sender:UISlider!)
{
println("number:\(sender.value)")
}
I added the slider to the Storyboard itself and in the code I did this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MenuTableViewCell
if indexPath.row == 0 {
cell.slider.alpha = 1
} else {
cell.slider.alpha = 0
}
return cell
}
It means that it will show the slider only on the first cell, and every other cell won't show it.
Of

Resources