I'm using tableView cell with button name of delete and I want to delete my JSON data from tableView cell I need to so That JSON ID to delete the JSON data from my Tableview. I'm using to get the JSON ID for that indexPath in didSelect row function. but the problem is I can't get JSON Id from that indexPath without pressing the row.
var selectedList: JSONList?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedList = JSONList[indexPath.row]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableviewCell
cell?.Numbers.text = JSONList[indexPath.row].Number
cell?.Trash.addTarget(self, action: #selector(Deleting), for: .touchUpInside)
cell?.selectionStyle = .none
return cell!
}
//here is my delete function calling
func Deleting() {
let selectedListObj = selectedList
print(selectedListObj!.id)
}
First of all set a tag to the button which it will be in your case the
row of the IndexPath, add this code in cellForRowAt:
cell?.Trash.addTarget(self, action: #selector(deleting(_:)), for:
.touchUpInside)
cell?.Trash.tag = indexPath.row
You need to modify the deleting() function to be #objc since selectors
after swift 3+ are a must to add that and add the button as param into it:
#objc private func deleting(_ button:UIButton){
// here you got the object
let selectedObject = JSONList[button.tag]
}
use closure to get the tapped buttons cells indexpath.
update the table view cell with ibaction and call the closure whenever tapping on trash button.
class FakeTableCell: UITableViewCell{
var selectedCell: ((UITableViewCell) -> ())?
#IBAction func trashButtonTapped(){
selectedCell?(self)
}
}
then we can get the indexpath of the cell in cell for row for indexpath as follows
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = FakeTableCell()
cell.selectedCell = { selectedCell in
if let ip = tableView.indexPathForRow(at: selectedCell.center){
self.deleteData(with: ip.row)
}
}
return cell
}
func deleteData(with row: Int){
// get the object by JSONList[row]
let item = JSONList[row]
// perform deletion
}
Related
I want to click a button in a custom xib file and it goes to a link passed in through an api using decodable.
I am able to make the entire row redirect to a link from the api by using:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let item = page!.tradeshows[indexPath.row]
if let eventURLS = item.url {
UIApplication.sharedApplication().openURL(eventURLS, options: [:], completionHandler: nil)
} else {print("link not working")
}
}
But I don't want to select the entire row, I only want to select the button from the custom .xib file.
I also tried:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) - > UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell",
for: indexPath) as!EventTableViewCell
let item = page!.tradeshows[indexPath.row]
cell.registerButton.addTarget(self, action: #selector(UpcomingEventsViewController.onClickedRegistrationButton(_: )),
for: .touchUpInside)
cell.registerButton.tag = indexPath.row
return cell
}
#objc func onClickedRegistrationButton(_ button: UIButton) {
let buttonLink = button.tag
}
but I'm not sure how to set the link from the json data so that the indexPath is correct using this second approach.
As the action is not directly related to the view controller it's more efficient to pass the URL to the cell and open the URL there. The target / action code is not needed.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! EventTableViewCell
let item = page!.tradeshows[indexPath.row]
cell.url = item.url
return cell
}
In the cell add a property url and an IBAction for the button
class EventTableViewCell : UITableViewCell {
var url : URL!
// other properties
#IBAction func pushButton(_ sender : UIButton) {
UIApplication.shared.open(url)
}
// other code
}
Side note:
Your first snippet is Swift 2 code. The method will never be called in Swift 3+
You need
#objc func onClickedRegistrationButton(_ button: UIButton) {
UIApplication.sharedApplication().openURL(NSURL(string:tableData[button.tag])!)
}
I got a play button on my tableview custom cell, whenever I tapped the play button. I want the selected button image to change to pause image.
The issue is that all the other buttons images are getting updated.
So all the images are changing to the pause image, instead of the selected button.
I tried to get the indexpath of the button tapped and reload only that row, but that doesn't seem to make a difference.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let playerCell = tableView.dequeueReusableCell(withIdentifier: "playerCell", for: indexPath) as! PlayerCell
let item = subcategory?.items?[indexPath.row]
// Tap gestures extension for cell button action
playerCell.playPause.addTapGestureRecognizer {
AudioController.shared.setupPlayer(item: item)
if let selectedCell = tableView.cellForRow(at: indexPath) as? PlayerCell {
selectedCell.playPause.setImage(#imageLiteral(resourceName: "pause"), for: .normal)
tableView.reloadRows(at: [IndexPath(row: indexPath.row, section: 1)], with: .none)
}
print("index \(indexPath)")
}
What you can do is add a tag to the button. So within the method that you create the cells override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell, you add a tag to the button within that cells that represents the indexPath. Then from within the selector that you assign the button, you can get the cell that you want to alter.
For example:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath)
cell.button.tag = indePath.row
cell.button.addTarget(self, action: #selector(yourSelector(_sender:)), for: .touchUpInside)
}
func yourSelector(_sender: UIButton){
let cell = tableView.cellForRow(at: IndexPath(row: sender.tag, section: 0)) as! YourCellType
// Change the image, play/pause audio for that cell
}
When you tap on the button in cell, tableView(_:didSelectRowAt:) won't be trigger, so I suggest using delegate to detect button action.
And you need to keep tracking the change of the cell's button status.
For example:
PlayCell.swift
protocol PlayCellDelegate: class {
func playCellPlayButtonDidPress(at indexPath: IndexPath)
}
class PlayerCell: UITableViewCell {
let playButton: UIButton = {
let button = UIButton()
button.addTarget(self, action: #selector(playButtonPressed(_:)), for: .touchUpInside)
return button
}()
weak var delegate: PlayCellDelegate?
var item: MyItem? {
didSet {
if item?.status == .paused {
// set pause image for playButton here
} else if item?.status == .playing {
// set play image for playButton here
}
}
}
var indexPath: IndexPath?
#objc func playButtonPressed(_ sender: UIButton) {
guard let indexPath = self.indexPath else { return }
delegate?.playCellPlayButtonDidPress(at: indexPath)
}
}
Model.swift
struct Subcategory {
// ...
var items: [MyItem]?
}
struct MyItem {
// ...
var status: Status.stop
enum Status {
case playing, paused, stopped // etc..
}
}
TableViewController.swift
class TableViewController: UITableViewController, PlayCellDelegate {
private var subcategory: Subcategory?
private let cellId = "Cell"
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as? PlayerCell {
cell.delegate = self
cell.item = subcategory?.items?[indexPath.row]
cell.indexPath = indexPath
return cell
}
return UITableViewCell()
}
func playCellPlayButtonDidPress(at indexPath: IndexPath) {
// you only need to change model here, and reloadRows will update the cell.
if subcategory?.items?[indexPath.row].status == .play {
subcategory?.items?[indexPath.row].status = .pause
} // other logic..
tableView.reloadRows(at: [indexPath], with: .none)
}
}
Hope it helps!
I have a TableView inside Another TableView, and the inner tableView contains buttons. I am able fire a method when click on button, but not able to get the indexPath. The app is getting crashed when I use the below code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell") as! MyCell
cell.myButton?.addTarget(self, action:#selector(myButtonPressed(_:)), for:.touchUpInside)
return cell
}
#objc func myButtonButtonPressed(_ sender: AnyObject) {
let button = sender as? UIButton
let cell = button?.superview?.superview as? UITableViewCell
let clasObj = myCell()
let indexPath = myCell.InsidetabView.indexPath(for: cell!)
let index = (indexPath?.row)!
print(index)
}
I gave tag to the button on TableView, cellForRowAt indexPath Method and accessed it on buttonPressed method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell") as! MyCell
cell.myButton?.addTarget(self, action:#selector(myButtonPressed(_:)), for:.touchUpInside)
cell.button.tag = indexPath.row
return cell
}
#objc func myButtonButtonPressed(_ sender: AnyObject) {
let button = sender as? UIButton
let row = button!.tag
}
I have a button in my table and when it was click it will trigger the selected table index. for example when i click the button at a selected index it will trigger the code below. Thank You
code
func indexWasPressed(cell: ToDoListTableViewCell) {
trigger it here
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.item)!")
Use below code to get index from TableViewCell:
func indexWasPressed(cell: ToDoListTableViewCell) {
let indexPath = yourTableView.indexPath(for: cell)
let index = indexPath.row
}
try this:-
#objc func buttonPressed(sender: UIButton) {
// printing selected row
print("index path: \(sender.tag)")
//do you want section try this
var section = Int()
let pointInTable: CGPoint = sender.convert(sender.bounds.origin, to: self.tblView)
let cellIndexPath = self.tblView.indexPathForRow(at: pointInTable)
section(cellIndexPath!)
section = cellIndexPath!.row
print(section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("cell for rows in \(indexPath.section)")
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifire", for: indexPath) as! yourcell
cell.yourbutton.tag = indexpath.row
cell.yourbutton.addTarget(self, action: #selector(buttonpressed(sender:)), for: UIControlEvents.touchUpInside)
}
I'm quite new to Swift and I would like to know what is the easiest and simplest way for me to add in 10 buttons to 10 of my cell rows in my TableViewController.
P.S: It would be nice if the 10 buttons perform differently instead of duplicate.
import UIKit
import FirebaseDatabase
var ref: DatabaseReference?
var databaseHandle: DatabaseHandle?
var postData = [String]()
class TableViewController5: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference() //set the firebase reference
// Retrieve the post and listen for changes
databaseHandle = ref?.child("Posts3").observe(.value, with: { (snapshot) in
postData.removeAll()
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
postData.append(key)
}
self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.font = UIFont.init(name: "Helvetica", size: 23)
cell.textLabel?.text = postData[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 80
}
}
From what I can understand, you should use prototype cell and add an IBAction in the cell and in that cell you should perform the segue and pass whatever data you need to customise the page you load.
In your tableView(_:cellForRowAt:) method, you can set a tag for the button.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? prototypeCell
cell.voteButton.tag = indexPath.row
return cell
}
Then in your cell's class, in the IBAction I mentioned earlier, check for the tag and set the data to pass accordingly.
Then in your prepareForSegue:sender: method, just pass the data you want to pass to the next view controller and all should work fine.
Check if it helps You
//Common cell Variable
var cell = UITableViewCell()
//UIButton commonly Declared
var acceptRequest = UIButton()
var declineRequest = UIButton()
My TableView Cell contains two button as shown Accept & Decline
In my tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) I added Handlers for button
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Cell for dequeuing
cell = self.RequestListTableView.dequeueReusableCell(withIdentifier: "Cell")!
//Used Tags here
//You can Make use of TableViewCell class here and Access Buttons from there
acceptRequest = cell.viewWithTag(4) as! UIButton
//Adding action Handlers for UIbuttons
self.acceptRequest.addTarget(self, action: #selector(RequestListView.AcceptRequest(sender:)), for: .touchUpInside)
return cell
}
my Button handler
func AcceptRequest (sender: UIButton) {
//Dequeue cell with identifier can be ignored
cell = self.RequestListTableView.dequeueReusableCell(withIdentifier: "Cell")!
//Get button position from TableView : Required
let buttonPosition : CGPoint = sender.convert(CGPoint.zero, to: self.RequestListTableView)
//Get index Path of selected Cell from TableView
//Returns Table Cell index same as didSelect
let indexPath : IndexPath = self.RequestListTableView.indexPathForRow(at: buttonPosition)!
//Can be used if you need to update a view
cell = self.RequestListTableView.cellForRow(at: indexPath)!
//Now time to access using index Path
cell.textLabel.text = array[indexPath.row] //Example
}
Can use this Procedure for even single Button or for multiple buttons too
In case if you have more than one button in one cell, this will help you