UITableView change detailText on already created cell - ios

I have a UITableView, to which I add cells via UIButton. On creation the cell gets its textLabel & detailTextLabel from 2 arrays. However, if an item with the same Title already exists in the table, I want to change the detailTextLabel.text of the existing cell without adding a new cell.
So is there a way to update the detailText of a certain UITableViewCell when it was already created with some value?
Maybe I should just remove the old one and add new?

Creating of a UITableView cell should be just that, creation and not population of data, since we re use cells we should always assume the cell data is stale and needs a refresh, therefore you should always have a way to reset the values of the cells, if you have a custom cell you should expose the controls you are using and set their values accordingly in cellForRowAtIndexPath, if you require to change a cell you should either change the data source values and reload the cell via - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation , or grab a hold of the cell with cellForRowAtIndexPath and change the values accordigly... my point is no need to recreate the cell..

Related

How can the content of a UITableViewCell be updated properly?

I have a TableView whose cells content need to be updated when it's TableViewRowAction is excecuted. More precisely I want to update a UILabel inside the cell. Setting a new text to this label inside the action is no problem but when scrolling down/up and the cell gets reloaded, then this label inside the cell has the same text as before changing it.
I know that the cells get reused and that's why I want to know how to "avoid" this effect and how to update the content of the cells properly. I have already tried to call TableView.ReloadData() which seems to solve the problem but the cells appear in a completly different order which doesn't look very nice.
The most straightforward approach is to update the data that your UITableView is drawing from (i.e. the array of data that you're populating each cell from has been updated to reflect your text change), then reload the specific cell of the UITableView:
let indexPath = IndexPath(row: 0, section: 0)
tableView.reloadRows(at: [indexPath], with: .automatic)
As you said table cells are reused , this means you have to keep a model array for the whole table and make all the changes to it , then reload the table more importantly to set the content of the cell index in cellForRowAt
To achieve this you must create an Array that acts as a dataSource for your labels. When you are changing the text for a specific label, you must update the array. You can get the exact update location from the property indexPath of the method cellForRowAt. Every single time you scroll up and down, cellForRowAt method is called. Just use something like
label.text = array[indexPath.row]

UITextField values inside UICollectionView cell in swift

I have UITextField and an ImageView inside UICollectionView cell. It loads data from web service. The user can input data inside the text field and have to submit it. My problem is, when I scroll the collection view, the entered value in one text field in a cell got messed up with other text field values from another cell, and it displays wrong values.
my steps(suppose I have cells A, B, ......., k)
1.entering values
Cell A Textfield= 12
Cell B Textfield= 13
2.scrolling down
(I haven't entered anything in cell F Textfield, though it shows 13)
3.scrolling back to where I entered values
Cell A Textfield= 12
Cell B Textfield= (blank)
You can solve this problem by keeping the values of UITextField in an Array. Whenever you are entering value to UITextField and dismissing keyboard,then save that value to array at the same cell index value in array and when you scroll your collectionView, the textfield value should entered from array and it won't misplace value.
UICollectionView and UITableView reuse a handful of cell objects as you scroll. This helps with memory management. It also means that when you populate one text field on a cell, that text field's cell will get reused for a different row as you scroll, so if you don't reset the text field's content, you'll see the same data showing up for the wrong rows.
The solution is that your "source of truth" (aka model) must always be separate from your UI. So when the user types something in a text field, your model (perhaps an array of strings?) should be updated accordingly. Then when the user scrolls, you must use tableView:cellForRowAtIndexPath: or collectionView:cellForItemAtIndexPath: methods to populate the cell with the appropriate data. If there is no data, you must clear any data that may have been left over from another row whose cell got reused.
Other opportunities you'll have to deal with cell reuse include the willDisplayCellForRowAtIndexPath method on UITableViewDelegate, or prepareForReuse on UITableViewCell. Collection view objects have corresponding methods as well.
As far as I can understand from question I think the problem is, you are not updating values every time - cellForRowAtIndexPath function gets called on scrolling.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
what you need to do to resolve this issue is "You have to store all the values you have entered in your cell's textField and whenever above datasource method gets called for UITableView, updated cell accordingly".

UITableView within UITableViewCell does not get updated

I have tried to create a custom cell that would display a list of items. To achieve this I tried to create a custom cell with UITableView inside it with scroll disabled.
The problem I have with this is when i try to apply changes to the cells in the inner UITableView data just does not get updated and the cell stays as it was. I have tried calling [tableView reloadData], [cell setNeedsDispaly], [cell setNeedsLayout] to no avail.
It seems like the data that has been applied when the cell was initialised persists through any attempts to change it. Though, when I create a breakpoint in cellForRowAtIndexPath: the data does get updated but is not rendered.(e.g. text property of UILabel has new value, but text is old on the screen.)
You need to nil the cell and then reload the table view. For some reason iOS caches table view data and stuff doesn't get updated correctly.
You could try overriding UITableViewCell's prepareForReuse(): in that method you can set all the cell's outlets/properties to nil. You would do this for the cells in the main cell's table view. I am assuming those are custom cells as well and that you have a custom UITableViewCell subclass for them.
Refer [I have two views on one cell, when I click on a cell it will be hidden and one edit form will be expanded on that. How to resolve that? ..check in accepted answer methods ...
[tableView reloadRowsAtIndexPaths:ll withRowAnimation:UITableViewRowAnimationAutomatic] in didSelectRowAtIndexPath

Multiple cells got affected after calling cellForRowAtIndexPath

I have a UITableView, and I want to change text color of the selected row. But I see every other 15 row got affected along with the one I clicked. This is tested under the master-detail sample project.
if let indexPath = self.tableView.indexPathForSelectedRow(){
self.tableView.cellForRowAtIndexPath(indexPath)?.textLabel?.textColor = UIColor.redColor()
}
I checked cellForRowAtIndexPath value in debug session, it seems returning only one object, how come other cells got affected too?
Cells are reused - almost certainly you are not resetting your cells to a base state in prepareForReuse and configuring them correctly on each call to cellForRowAtIndexPath.
When you look at a table view that can display some number of cells at once, typically there will only exist one more cell than can be shown. When a cell is moved off the screen it is placed in a pool of cells for reuse. Just before a cell moves onto the screen it is configured by you, in cellForRowAtIndexPath. If you have configured something in the cell and you do not configure that explicitly every time you return a cell from cellForRowAtIndexPath then that configuration persists in the cell that is in the reuse pool. The function prepareForReuse is also called before each cell is reused - if you have subclassed UITableViewCell then you can implement this function to return the cell to a base configuration, so that settings like text color do not unexpectedly affect multiple cells.
This approach makes it possible to scroll through an entire table view smoothly with a minimum amount of memory used. It is an expensive operation to create and destroy cells every time one disappears and a new one is required.
The simplest fix is to always set the text color in cellForRowAtIndexPath - either to the base color or to the special color you want in some cells.

iOS: Adding row to tableview

I have a tableview that is based on a array of DB results, these results contains a date field. I have a custom cell that contains an image and labels. I'm trying to do:
At cellForRowAtIndexPath I verify if the date of current item (objectAtIndex:indexPath.row) has date field bigger than the last item (objectAtIndex:indexPath.row-1). If this is true: I want to add a cell filling the ImageView with a certain image, but I need to add a new row just for show this image.
How can I do this? I'm already doing this verification, but I need to add a new cell...
Do not use the cellForRowAtIndexPath to decide how many cells you want to have. At the point this method is called you should have already setup the data source to provide table view with all information needed.
Here is what you need to do. Refactor your code in a way so you:
Setup the data source first.
Force reload of the table view either by calling the reloadData method.
hey you can add the object in your data base(for example ns array) and refresh the table view with method
[tableView reloadData];
then the method cell for row at index path will be called again and it will refresh the table view's items.just make sure the method cellforrawantindexpath in your code knows to handle the new data type(make validations).
Your tableView data source should not contain any of that logic where the content of once cell depends on the content of another cell. Instead, you should have a data item for each requested indexPath and that data item should contain ALL logic necessary for the cell to be configured. If an action on that cell has an effect on how another cell should look, you apply a change to the corresponding data-item, and then call reloadRowsAtIndexPaths: for the indexPaths.
In short: configure cells ONLY in tableView:cellForRowAtIndexPath: or tableView:willDisplayCellAtIndexPath, and ONLY do configuring. Other logic should be placed in some data(-controller) object.
As suggested, you should add an item to your data-array. Then call -insertRowAtIndexPath: on the tableView. ReloadData is like a big ugly hammer that you only use when ALL of the data for that tableView changes.

Resources