I'm working on a project where I have two UITableView
s and two UITextField
s, when the user presses the button the data in the first textField
should go into the tableView
and the second go into the second tableView
. My problem is that I don't know how to put data in the tableView
each time the user pushes the button, I know how to insert data with tableView:cellForRowAtIndexPath:
but that works for one time as far as I know. So what method can I use to update the tableView
each time the user hits the button?
Asked
Active
Viewed 1.6e+01k times
80

Bhavin Bhadani
- 22,224
- 10
- 78
- 108

code Horizons
- 841
- 2
- 8
- 8
-
What have you tried? You say "tableView:cellForRowAtIndexPath:" only works "as far as" you know. Why not try it in your button's method? – Max von Hippel Aug 07 '15 at 07:11
-
1@Max von Hippel what I did was : the tableView takes the data from an array so when I append an item to the array I use this method : tableView.reloadData this way when ever I append an item the array will go to the "CellForRowAtIndexPath" and pull the informations again from the array :) – code Horizons Aug 07 '15 at 15:34
5 Answers
183
Use beginUpdates
and endUpdates
to insert a new cell when the button clicked.
As @vadian said in comment,
begin/endUpdates
has no effect for a single insert/delete/move operation
First of all, append data in your tableview array
Yourarray.append([labeltext])
Then update your table and insert a new row
// Update Table Data
tblname.beginUpdates()
tblname.insertRowsAtIndexPaths([
NSIndexPath(forRow: Yourarray.count-1, inSection: 0)], withRowAnimation: .Automatic)
tblname.endUpdates()
This inserts cell and doesn't need to reload the whole table but if you get any problem with this, you can also use tableview.reloadData()
Swift 3.0
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: yourArray.count-1, section: 0)], with: .automatic)
tableView.endUpdates()
Objective-C
[self.tblname beginUpdates];
NSArray *arr = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:Yourarray.count-1 inSection:0]];
[self.tblname insertRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tblname endUpdates];

Bhavin Bhadani
- 22,224
- 10
- 78
- 108
-
3Nice that you have provided the Objective-C version as well. It helps sometimes!! – Rashmi Ranjan mallick Oct 09 '15 at 04:54
-
1@RashmiRanjanmallick ...yes same thing I thought and edit my answer...so people understand translations :) – Bhavin Bhadani Oct 09 '15 at 04:56
-
7`begin/endUpdates` has no effect for a single insert/delete/move operation. – vadian Apr 28 '16 at 13:37
-
No, you can omit `begin/endUpdates` for a single insert operation and it is working anyway. – vadian May 09 '16 at 12:13
-
1@vadian hmm ... thats what I think ... but what do you mean by `begin/endUpdates has no effect for a single insert/delete/move operation` this sentence ??? sorry for too many questions .. – Bhavin Bhadani May 09 '16 at 12:16
-
3*No effect* means there is no difference if the lines are there or not. You need the lines only for e.g. an `insert` line followed by a `delete` line or multiple calls of the same line in a repeat loop. – vadian May 09 '16 at 12:19
-
Does the the call to `beginUpdates`/`endUpdates` have to be on the main thread? or it will handle that itself automatically? – mfaani Aug 21 '17 at 10:33
-
Looks like `begin/endUpdates` would cause the `tableView` to calculate the size of every cell. The scrolling get smoother after I remove them. – Kimi Chiu Jan 16 '18 at 08:31
-
this works fine for a tableView with one section , but with multiple dynamic sections it crashes if the item is being placed into a new section and also for the first item added to the tableview. So for multiple sections check your dataSource to see if it's the first item in the section. if so use insertSection instead of insertRow, otherwise use the above. – alionthego Feb 13 '18 at 08:04
-
doesn't inserting at `row: yourArray.count-1` insert the new row at the second-to-last row? – matt b Jun 06 '18 at 01:21
-
1@mattb not really .. array count starts from 1 like we have 10 rows and index starts from 0. So to insert the 11th row, right now we have index till 9. So we have to set -1 means at 10th index we need to insert 11th row. hope u understand now :) – Bhavin Bhadani Jun 06 '18 at 05:02
33
Swift 5.0, 4.0, 3.0 Updated Solution
Insert at Bottom
self.yourArray.append(msg)
self.tblView.beginUpdates()
self.tblView.insertRows(at: [IndexPath.init(row: self.yourArray.count-1, section: 0)], with: .automatic)
self.tblView.endUpdates()
Insert at Top of TableView
self.yourArray.insert(msg, at: 0)
self.tblView.beginUpdates()
self.tblView.insertRows(at: [IndexPath.init(row: 0, section: 0)], with: .automatic)
self.tblView.endUpdates()

Sourabh Sharma
- 8,222
- 5
- 68
- 78
-
How's this achieved with a collection view? I can insert multiple items with ease.... but this is inserting at index 0. When the item is selected the previous index 0 is shown. – scrainie Jan 22 '17 at 03:12
22
Here is your code for add data into both tableView:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var table1Text: UITextField!
@IBOutlet weak var table2Text: UITextField!
@IBOutlet weak var table1: UITableView!
@IBOutlet weak var table2: UITableView!
var table1Data = ["a"]
var table2Data = ["1"]
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func addData(sender: AnyObject) {
//add your data into tables array from textField
table1Data.append(table1Text.text)
table2Data.append(table2Text.text)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//reload your tableView
self.table1.reloadData()
self.table2.reloadData()
})
table1Text.resignFirstResponder()
table2Text.resignFirstResponder()
}
//delegate methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == table1 {
return table1Data.count
}else if tableView == table2 {
return table2Data.count
}
return Int()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == table1 {
let cell = table1.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
let row = indexPath.row
cell.textLabel?.text = table1Data[row]
return cell
}else if tableView == table2 {
let cell = table2.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! UITableViewCell
let row = indexPath.row
cell.textLabel?.text = table2Data[row]
return cell
}
return UITableViewCell()
}
}
And your result will be:

Dharmesh Kheni
- 71,228
- 33
- 160
- 165
-
-
The reason I am asking is that I am trying to do something similar and I am getting a message in the console which tells me the tableview is being forced to a resize – Sami Jun 22 '16 at 20:50
-
-
Reference to your answer, Can I ask question related to add section and move row? – Newbie Feb 19 '20 at 08:24
3
For Swift 5
Remove Cell
let indexPath = [NSIndexPath(row: yourArray-1, section: 0)]
yourArray.remove(at: buttonTag)
self.tableView.beginUpdates()
self.tableView.deleteRows(at: indexPath as [IndexPath] , with: .fade)
self.tableView.endUpdates()
self.tableView.reloadData()// Not mendatory, But In my case its requires
Add new cell
yourArray.append(4)
tableView.beginUpdates()
tableView.insertRows(at: [
(NSIndexPath(row: yourArray.count-1, section: 0) as IndexPath)], with: .automatic)
tableView.endUpdates()

Shourob Datta
- 1,886
- 22
- 30
-
2Why do you create an NSIndexPath then cast it into IndexPath? Just create an IndexPath initially. I usually do it even simpler: `[0, 1]`. Zero is the section, 1 is the row. – Starsky Oct 08 '20 at 14:25
-
1
1
You can find this comment in Apple's UITableView framework:
// Use -performBatchUpdates:completion: instead of these methods, which will be deprecated in a future release.
So, you should use this:
tableView.performBatchUpdates { [unowned self] in
tableView.insertRows(at: indexPaths, with: animation)
}

Victor Morei
- 180
- 4