问题
I think this is probably an X Y problem, so I'll give some background info first.
I am building an app that can show a "form". The user can fill in the form with some stuff and create some custom things.
I think the most suitable thing to do is to use a table view for the form. And I can display all the text boxes that need to be fill in, in each of the table cells.
Here's a screenshot:
The "Add New Input" button will insert a new cell on the bottom when it is tapped. And if you swipe one of the inputs to the left, you get a "Delete" button. You can use that to delete the input.
As you can see, this table view needs to add and delete rows.
Originally, I was using a cocoapod called "TableViewModel" which makes this super easy. But then I found a really severe bug in the library so I don't want to use it anymore.
I tried using the table view's deleteRowsAtIndexPaths
and insertRowsAtIndexPaths
methods. But if I do it like this:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Hello"
return cell
}
// I use motionEnded here because I don't want to add a button or anything just to test this
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Fade)
}
It will result in an exception saying that the table view is inconsistent with the data source after I deleted one row. This means I have to have code to handle this inconsistency. This will definitely make my code harder to read.
The same thing goes with the insert method.
Also, I need to keep track of how many rows there are in each section. And my code just becomes really messy and unmaintainable with all that.
I have also searched for other libraries but they are all really weird and not as straightforward as "tableViewModel". They all seem to require me to create a model for the table view. I don't understand how to do that in my case. I just want to display a bunch of text fields!
How can I insert or delete rows more elegantly? I think I either need to write an extension
of the table view or learn to write a model for my table view. But I am able to do neither of these methods.
回答1:
Because you don't have any data source
. Also see logically
: suppose you add a new row with insertRowsAtIndexPaths . So now you have 2 rows
. However your numberOfRowsInSection
always returning 1. so it will crash and vice versa for delete. Table view are supposed to work with a collection
(NSArray
, NSDictionary
, NSSet
etc.).
For your help:
Already they have nade a form as yours
obj-c easy to understand how table view with data source work
Adding, Updating, Deleting and Moving records using Swift.
回答2:
You may use a TableView
to create the form but you must design an appropriate dataSource to keep track of these data. Now the dataSource method must be modified to
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourDataSourceForSection.count
}
You may edit this dataSource when a delete operation is performed as follows
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
//Delete the row from the data source to ensure consistency
self.array.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
You may use a model class as the dataSource
.
class NewCustomOperation: NSObject {
var name: String?
var rejectFloatingPoints: Bool?
var inputs: AvailableInputs?
var results: Results?
}
class AvailableInputs: NSObject {
var name: [String]?
var description: [String]?
}
class Results: NSObject {
var name: [String]?
var formula: [String]?
}
回答3:
I found a solution!
I basically keep an array of an array of cells for the table view to display:
var cells: [[UITableViewCell]] = [[], [], []] // I have 3 sections, so 3 empty arrays
And then I added these data source methods:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return cells.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cells[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cells[indexPath.section][indexPath.row]
}
Now, I can add and remove cells super easily:
func addCellToSection(section: Int, index: Int, cell: UITableViewCell) {
cells[section].insert(cell, atIndex: index)
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: section)], withRowAnimation: .Left)
}
func removeCellFromSection(section: Int, index: Int) {
cells[section].removeAtIndex(index)
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: section)], withRowAnimation: .Left)
}
With just two lines, I can add/remove cells with animation!
来源:https://stackoverflow.com/questions/37278581/how-can-i-add-remove-cells-in-a-table-view-more-elegantly