This is my sectionArray
var sectionArray = [Sections]()
This is how I figure out how many rows in section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sectionArray[section].items.count
}
and this is my code to remove a row by sliding.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
sectionArray[indexPath.section].remove(at: indexPath.row)
if sectionArray[indexPath.section].title.count == 0 {
sectionArray.remove(at: indexPath.row)
}
tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
}
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .normal, title: "Delete") { action, index in
//self.isEditing = false
print("delete button tapped")
}
delete.backgroundColor = UIColor.red
return [delete]
}
Theoretically this delete stuff should work but I am getting error No exact matches in call to subscript at
sectionArray[indexPath.section].remove(at: indexPath.row)
/// This line
sectionArray.remove(at: indexPath.row)
/// should be like this
sectionArray.remove(at: indexPath.section)
/// This line will remove the section from the table
tableView.deleteSections(.init(integer: indexPath.section), with: .automatic)
You are using row to remove a section
Edit
Replace all the code you provided us with this
/*
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
sectionArray[indexPath.section].remove(at: indexPath.row)
if sectionArray[indexPath.section].title.count == 0 {
sectionArray.remove(at: indexPath.row)
}
tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
}
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .normal, title: "Delete") { action, index in
//self.isEditing = false
print("delete button tapped")
}
delete.backgroundColor = UIColor.red
return [delete]
}
*/
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .normal, title: "Delete") { action, index in
//self.isEditing = false
sectionArray[indexPath.section].remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
if sectionArray[indexPath.section].items.isEmpty {
sectionArray.remove(at: indexPath.section)
tableView.deleteSections(.init(integer: indexPath.section), with: .automatic)
}
}
delete.backgroundColor = UIColor.red
return [delete]
}
Related
please help, I have an array with names and when I select a cell I add the selected name to the second section of a table view and delete the name from that first section (all fine here) but if I don't want the name in second section for some reason, I want to be able to swipe the cell, remove the name and add it again to the firs section of the table view. When I do that with my code the number of rows fails because I deleted a row. I can't figure it out.
here is my code.
import UIKit
class QuestionsVC: UIViewController {
#IBOutlet weak var namesTableView: UITableView!
var array1 = ["Jill","Clark","Rose","Peter","Louis"]
var array2 = [String]()
override func viewDidLoad() {
super.viewDidLoad()
namesTableView.dataSource = self
namesTableView.delegate = self
}
}
extension QuestionsVC: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return array1.count
}
return array2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = array1[indexPath.row]
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
cell?.textLabel?.text = array2[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
array2.append(array1[indexPath.row])
if let index = array1.firstIndex(of: array1[indexPath.row]) {
array1.remove(at: index)
}
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if indexPath.section == 0 {
return false
}else{
return true
}
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (_, indexPath) in
self.array2.remove(at: indexPath.row)
self.array1 += [self.array2[indexPath.row]]
tableView.deleteRows(at: [indexPath], with: .fade)
}
return [deleteAction]
}
}
You have to delete the row in section 1 and insert the row in section 0 simultaneously
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (_, indexPath) in
let item = self.array2.remove(at: indexPath.row)
let insertionIndex = self.array1.count
self.array1.append(item)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .fade)
tableView.insertRows(at: [IndexPath(row: insertionIndex, section: 0)], with: .automatic)
tableView.endUpdates()
}
return [deleteAction]
}
}
replace the line
tableView.deleteRows(at: [indexPath], with: .fade)
with
tableView.reloadData()
I have custom cells of UITableView which consist of UIImage and textLabel. When I select the editing mod, the textLabel shows the following image;
I want to move it to left. I tried all of things to do but it didn't work.
Please let me know.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allRows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "editCell", for: indexPath) as! CustomTableView
cell.textLabel?.text = self.allRows[indexPath.row].bname
cell.textLabel?.textAlignment = .left
let image:UIImage = UIImage(named: "group")!
cell.imageView!.image = image
return cell
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle{
return .delete
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if editingStyle == .delete{
self.allRows.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)
}
}
#objc func leftEditButtonPressed(_ sender: UIButton) {
self.tableView!.isEditing = true
self.tableView?.setEditing(true, animated: true)
}
look at this, I hope it helps you:
swipe left/right in tableViewCell
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let closeAction = UIContextualAction(style: .normal, title: "Close", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
print("OK, marked as Closed")
success(true)
})
closeAction.image = UIImage(named: "tick")
closeAction.backgroundColor = .purple
return UISwipeActionsConfiguration(actions: [closeAction])
}
Try using the following code:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArr.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80.0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableCell") as? TestTableCell else {
return UITableViewCell()
}
cell.customImageView.image = #imageLiteral(resourceName: "ic_audio")
cell.customTitleLabel.text = self.dataArr[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.delete
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("delete at \(indexPath.row)")
}
}
Here is the output for this code:
Note: You can change the editing action in editingStyleForRowAt method and for performing the action you need to write the logic in commit editingStyle method.
Hope this help you!
I suggest you to create new label in that UITableViewCell and connect that label to custom UITableViewCell class ! then you are free to do anything !
Swift 4 :
Create a new class which is subclass of UITableViewCell !
In your storyboard in right menu which called Utilities in toolbar of Utilities go to the Identity inspector defince your cell class to your new UITableViewCell class
Drag and drop UILabel from Object library into your cell
now using drag and drop connect that label to your UITableViewCell class then create an Outlet
Perfect !
now use myLabel instead of textLabel ;)
dont forget to cast your cell as! YourCustomCellClass
Good Luck ;)
I have a tableview where I'm trying to implement a swipe-to-delete action.
I'm using swift 4 and Xcode 9.
So far I have the next code which allows me to show a delete label when swipe:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
print("deleting row")
default:
return
}
}
So far so good, now I'd like to change the background red color to another one and if it's also possible i'd like to show an icon instead of a label.
I'm trying this code I've seen for Swift 4 but it's complaining when creating the button:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteButton = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
self.tableView.dataSource?.tableView!(self.tableView, commit: .delete, forRowAt: indexPath)
return
}
deleteButton.backgroundColor = UIColor.black
return [deleteButton]
}
It gives this error -> Ambiguous reference to member 'tableView(_:numberOfRowsInSection:)'
I don't know if I'm trying the good way to edit, or if it's not editable at all on swift 4.
Any help is appreciated,
Thanks!
I am using Xcode 9.2 and swift 4. Used same code but with no errors. Full code is here. That may help to you.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height), style: .plain)
tableView.dataSource = self
tableView.delegate = self
self.view.addSubview(tableView)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "Lalala"
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
print("deleting row")
default:
return
}
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteButton = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
self.tableView.dataSource?.tableView!(self.tableView, commit: .delete, forRowAt: indexPath)
return
}
deleteButton.backgroundColor = UIColor.black
return [deleteButton]
}
}
I was tried like this ,may be this will help you.
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
print("Did tap the button")
self.deleteSession(sessionId: self.tableModel[indexPath.row].Id)
print("the session id is '\(self.tableModel[indexPath.row].Id)'")
self.tableModel.remove(at: indexPath.row)
print("\(indexPath.row)")
tableView.deleteRows(at: [indexPath], with: .fade)
print("\([indexPath])")
self.medilogTableView.reloadData()
}
deleteAction.backgroundColor = UIColor.red
//deleteAction.backgroundColor = UIColor(patternImage: UIImage(named: "delete_button")!)
//renameAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0)
return [deleteAction]
}
medilogTableView is name of the table
You must implement your edit code inside the "in" callback :
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteButton = UITableViewRowAction(style: .default, title: "Delete") { (action, indexPath) in
// here implement your delete code
}
deleteButton.backgroundColor = .blue
return [deleteButton]
}
Sample of implementation for your "delete code" :
self.tableView.beginUpdates()
self.data.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .left)
self.tableView.endUpdates()
How can I get the marked key then remove it from UITableView swift 3 ?
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
self.grocery.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
To remove you can simply set the value as nil to remove it from firebase. After you've called the remove function then make sure to remove the row from the tableView.
func removeObjectFromFireBase(userKey: String, removeThisGrocery: String) {
let ref = Database.database().reference()
let groceryRef = ref.child("Users").child(userKey).child("Grocery")
groceryRef.child(removeThisObject).setValue(nil)
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive, title: "DELETE") { (rowAction, indexPath) in
//Call the removeFromFirebase function with the required parameters
removeObjectFromFirebase(userKey: userKey, removeThisGrocery: groceryKey)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
deleteAction.backgroundColor = UIColor.red
return [deleteAction, addAction]
}
You can remove any data from Firebase as following:
let ref = Database.database().reference()
let groceryRef = ref.child("Users").child(userKey).child("Grocery")
groceryRef.removeValue()
I have a table of names and I am making a swipe and delete function for them which removes them from a names variable which is an array.
I selected the functions which most closely resembled the tutorial inside xcode and filled them out, but my app crashes randomly when I click the delete button. Here is my code for the delete button:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (rowAction: UITableViewRowAction, indexPath: IndexPath) -> Void in
print("Deleted")
self.catNames.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
self.tableView.reloadData()
}
}
I'm new to coding and learning swift, I am following a tutorial for swift 2 and working with swift 3 so there are a few issues I have when following along, this being one I'm properly stuck on.
Works for Swift 3 and Swift 4
Use the UITableViewDataSource tableView(:commit:forRowAt:) method, see also this answer here:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.catNames.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
First you need to add this function
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
then your function is ok but no need of tableview reload data just call tableview.beingUpdates and tableview.endUpdates
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.catNames.remove(at: indexPath.row)
self.tableView.beginUpdates()
self.tableView.deleteRows(at: [indexPath], with: .automatic)
self.tableView.endUpdates()
}
}
In Swift 4 Try This
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
arrStudentName.remove(at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .middle)
tableView.endUpdates()
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
self.animals.remove(at: indexPath.row)
self.dataDisplayTbleView.reloadData()
}
}
**
for swift 3
**
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.catNames.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
My answer for you
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
{
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
if editingStyle == .delete
{
array.remove(at: indexPath.row)
tblDltRow.reloadData()
}
}
You need to refresh the table
You don't have to reload the tableView.
Before you use tableView.deleteRows(at: [IndexPath], with: UITableView.RowAnimation) you must substrate the number of rows you want delete in numberOfRowsInSection
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return //Your current number of rows - The number of rows to delete
}
Normally the number of rows is the number of Items from an array (yourArray.count), that means you can delete the items from this array before you delete the cells and you get the same result.
self.tableView.beginUpdates()
self.tableView.deleteRows(at: [ IndexPath(row: index, section: section) ], with: .fade)
self.remove_object_from_model()
self.tableView.endUpdates()
For Swift 5
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.catNames.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}