How to delete a row in a section with Swift? - ios

I need to delete a row in a section but it deletes the row in upper section. Please help find problems of my codes. Also, please advise how to delete the section when deleting the row? There is one row in a section.
var sectionTitles = [String]()
var savedURLs = [[String]]()
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return savedURLs.count
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionTitles[section]
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return savedURLs[section].count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SavingCell")
cell?.textLabel!.text = savedURLs[indexPath.section][indexPath.row]
return cell!
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
savedURLs[indexPath.section].removeAtIndex(indexPath.row)
NSUserDefaults.standardUserDefaults().setObject(savedURLs, forKey: Key_SavedURLs)
savingTableView.reloadData()
}
}

To delete empty sections modify your code to this:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
savedURLs[indexPath.section].removeAtIndex(indexPath.row)
// now check if a section is empty and, if so, delete it
if savedURLs[indexPath.section].count == 0 {
savedURLs.removeAtIndex(indexPath.section)
}
NSUserDefaults.standardUserDefaults().setObject(savedURLs, forKey: Key_SavedURLs)
savingTableView.reloadData()
}
}
although for this to work your savedURLs should be [[String]]

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
savedURLs.removeAtIndex(indexPath.section)
NSUserDefaults.standardUserDefaults().setObject(savedURLs, forKey: Key_SavedURLs)
savingTableView.reloadData()
}
}
try this.this should work..

Related

UITableView Force Right-to-Left swipe to delete not work

I have uiviewcontroller with uitableview
and swipe to delete work fine but
when I set uitableview semantic to force right-to-left the swipe to delete not even shown in the tableview
classViewController:UIViewController,UITableViewDelegate,UITableViewDataSource {
var yourArray : [Type] = []
override func viewDidLoad() {
super.viewDidLoad()
tablView.delegate = self
tablView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourArray.count
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete{
tableView.beginUpdates()
yourArray.remove(at: indexPath.row)
tableView.endUpdates()
tableView.reloadData()
}
}
}

When i remove cell from TableView on button action the app is crashed - iOS Swift

im trying to remove a cell from a TableViewController. Each time i swipe and press the delete button a crash occur.
This is the crash log:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of rows in section 0. The number of rows contained in an
existing section after the update (10) must be equal to the number of
rows contained in that section before the update (10), plus or minus
the number of rows inserted or deleted from that section (0 inserted,
1 deleted) and plus or minus the number of rows moved into or out of
that section (0 moved in, 0 moved out).'
and this is my UITableView functions.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier(cellID, forIndexPath: indexPath) as! PredefinedServicesCell
//Cell configuration.
myCell.selectionStyle = .None
myCell.containerView.layer.borderColor = UIColor(hex: 0x3399CC).CGColor
myCell.containerView.layer.borderWidth = 1
myCell.containerView.layer.cornerRadius = 10
myCell.containerView.clipsToBounds = true
myCell.servicePrice.text = "\(indexPath.row)"
myCell.serviceCurrency.text = "KWD"
myCell.serviceTitle.text = "Building iOS Application"
myCell.serviceDescription.text = "This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description"
return myCell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
what might the reason be?
Please dynamically add your numberOfRowsInSection. It's not static.
use array insted of return 10. and remove objec when you delete in editing style.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourArray.count
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
// remove object from array here
}
}
reason behind error: in your case
firs your no of table cell count is 10.
When you are delete cell your cell is deleted but count is 10. It's worng otherwise decrease your count to 9.
Keep a record of number of deleted cells and delete the same amount from array(used to populate table view) as well.
Once you remove the rows from the tableview, you must have to update your numberOfRowsInSection value also. That's why you are getting crash.
let rows=10
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return rows
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier(cellID, forIndexPath: indexPath) as! PredefinedServicesCell
//Cell configuration.
myCell.selectionStyle = .None
myCell.containerView.layer.borderColor = UIColor(hex: 0x3399CC).CGColor
myCell.containerView.layer.borderWidth = 1
myCell.containerView.layer.cornerRadius = 10
myCell.containerView.clipsToBounds = true
myCell.servicePrice.text = "\(indexPath.row)"
myCell.serviceCurrency.text = "KWD"
myCell.serviceTitle.text = "Building iOS Application"
myCell.serviceDescription.text = "This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description This is a service description"
return myCell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
rows-=1
}
}
Following the crash log, you should update number of rows after editing
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
You cannot return the number of cell as 10, after deleting the cell. It should be less the number of cell before deletion.
You have to update your data source to match the number of row/section of your tableview, and use beginUpdate & endUpdate to update your table view display. Like so:
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
tableView.beginUpdate() //optional
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
//TODO ... add your code to update data source here
tableView.endUpdate() //optional
}
}
You cannot declare a static value to your numberOfRowsInSection and then change it (10 - 1) by removing a row with deleteRowsAtIndexPaths, numberOfRowsInSection remain 10 and your rows become 9 so you have this kind of issue, make these changes to have a dynamic value:
var totalRows: Int = 10
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.totalRows
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
if self.totalRows > 0 { // This limit your deletion to avoid a crash
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.totalRows -= 1
}
}
}
Usually It's better to handle a datasource array to maintain your informations to show in each cell, so think to use an array to do it so you can use it's count property and remove it's element when you delete a cell.
Your numberOfRowsInSection should be dynamic not static. So, remove data in the dynamic array with yourdataName.remove(at:indexPath.row)
Example;
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourdataName.count;
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
yourdataName.remove(at:indexPath.row)
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}

deleting animation doesn't show up

I have UIViewController and I dragged a UITableView inside and I want to insert some elements to the table and be able to remove them here . When I use this code it works fine for UITableViewController but now when I want to remove a cell I can swap it but the deleting animation (Red sign) doesn't show up
import UIKit
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
var listArray = ["Danial"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBOutlet var table: UITableView!
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
cell.textLabel?.text = listArray[indexPath.row]
return cell
}
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool
{
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete){
listArray.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) }
}
}
The problem with your code is that you are typing:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete){
listArray.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) }
}
instead of
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete){
listArray.removeAtIndex(indexPath.row)
self.table.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) }
}
so just go to everywhere where you wrote
tableView.
and change it to self.table.
(basically what you named your tableview from the IBOutlet)

editActionsForRowAtIndexPath swipe issue

I have custom UITableViewCell with some content on it. While I am trying to swipe (to show delete custom button with image) It's simply not working, or if I'll try to do that 10 times, so I could see the swipe delete button action.
my code is:
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
//
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! MessagesCell
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Destructive, title: " ") { value in
// here some removing action
deleteAction.backgroundColor = UIColor(patternImage: UIImage(named: "swipeToDelete")!)
return [deleteAction]
}
This code will help
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
}
}
Thank you.
The issue was in IIViewDeckController that blocked swipe with its PanGesture

Delete button in UITableView (SWIFT)

I have a piece of code here, which seems to be working just fine apart from one little piece.
import UIKit
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tblTasks: UITableView!
//Returning to view
override func viewWillAppear(animated: Bool) {
tblTasks.reloadData();
}
//UItableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return taskMgr.tasks.count
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "test")
cell.textLabel?.text = taskMgr.tasks[indexPath.row].name
cell.detailTextLabel?.text = taskMgr.tasks[indexPath.row].desc
return cell
}
}
I have introduced these lines in order to be able to delete rows in the table view
func tableView(tableView: UITableView,
canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView,
commitEditingStyle editingStyle: UITableViewCellEditingStyle,
forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
}
}
and what they do is giving me the possibility to swipe rows from right to left, though the row doesn't get deleted.
What would be the best possible way to introduce a DELETE button in this case?
best regards, Vlad
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
//delete row at selected index
numbers.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
Here is a cleaned up version for Swift 3.x:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete from your source, then update the tableView
numbers.removeAtIndex(indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
Check to make sure that the editingStyle is delete before proceeding
Remove the value from your data source (in this case, numbers)
Finally, pass in the indexPath as an array to be deleted, along with the animation you would like (in this case, automatic)
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
yourArray.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}

Resources