I have been searching and reading all over but couldn't find any conclusive method to achieve what I want to and hope to find help here...
I have a UITableView which allows the user to add multiple Flavours and Percentages to a Recipe. I have implemented the method to add or delete rows of Flavours with a custom Cell / Nib and it works perfectly well.
The issue I'm facing now, is how to retrieve the values the user has provided per added row.
(Edit for Clarity: My problem is not the populating of data, but only the dynamic reading of all data so I can save it)
I do manage to get the values for the visible rows (I do understand how the Reuseidentifier and the Tableview works, per se that for memory management's sake, iOS only keeps track of the visible rows), but not the hidden ones.
I assume in theory that I have to create an Array of Cells outside of 'cellForRowAtIndexPath' which maintains all cells. But then I'm facing another conceptual problem that my custom Nib / cell doesn't show.... basically:

Here the code I'm using within my cellForRowAtIndexPath. As mentioned adding and remove cell works like a charm, that isn't the issue...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RecipeFlavourTableViewCell *cell;
int section = (int)indexPath.section;
if(section==0)
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(!cell){
[tableView registerNib:[UINib nibWithNibName:@"RecipeFlavourCell" bundle:nil] forCellReuseIdentifier:@"Cell"];
cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
I have seen some Libraries doing it (e.g. XLForm) but do not understand (also when checking their sources) how they iterate through the values and overcome this dequeuing problem...
Any help is highly appreciated
EDIT 2: here the code I'm using to iterate through the cells in order to save the data, but as said I can only iterate through the visible cells:
- (IBAction)saveRecipe:(id)sender {
NSInteger dynamicRows = [self.tableView numberOfRowsInSection:1];
for (int i=0; i<dynamicRows; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:1];
RecipeFlavourTableViewCell *cell = (RecipeFlavourTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
NSLog(cell.flavour.text);
}
}
After 2 days of searching I finally came up with a solid solution. In case someone bumps into the same problem of dynamic forms with a tableview, here the solution:
As we understand, what ever cell is created in cellForRowAtIndexPath, it only persists as long as it is displayed. As soon as you scroll and the cell disappears, it gets automatically thrown out of memory. This behaviour makes it impossible to iterate through all cells at a later stages.
The steps to follow in order to make it work are as follows:
Preparation
TextField Delegate
Implement:
- (void)textFieldDidEndEditing:(UITextField *)textField
and update your cellsArray Objects every time a Textfield ends editing. Per se, get the cellObject for the row and edit the properties with the value of the TextField
Add Row
When ever you add a row, just add an empty cellObject to your cellsArray and use the beginUpdates / insertRowsAtIndexPaths / endUpdates on your tableView (NOT reloadData as the already typed in data would get lost). Also add the following at the very beginning of your addRow method, as you want to make sure that if the user adds a row while editing a textfield, the latter gets persisted as well:
[self.view.window endEditing: YES];
Remove Row
Same as Add Row just reverse, remove the cellObject from your cellsArray and use deleteRowsAtIndexPaths on your tableView
Save Data
Now comes the trick: since you ought to always persist your data when a field ends editing mode, there is one case you need to cover: What if the user pushes "Save" when the focus is set on one TextField? Well at the very beginning of your Save Action insert the following:
[self.view.window endEditing: YES];
This make sure the the textFieldEndEditing will be triggered one last time for the current textField and that its data will also be persisted.
Finally iterate through your cellsArray and do whatever you want with it (validate, save etc)...
That's it, hope this can help anyone else as I couldn't find any valuable explanation anywhere else...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With