Okay the situation goes as follows:
I have a collection view where in cellForRow I am using dequeueReusableCell to reuse the cells. On each cell I have a custom UIView object that is added as a subview.
Now, under a certain circumstance I must re-layout the collection view entirely. When this happens
Clear all item from data model
Call deleteItems for all visible cells' index paths
Call reloadData
At this point the collection view is empty and there are no cells displayed.
Now if I update my model again with data and reload the collection view - In cellForRow dequeueReusableCell returns reused cells/the added UIView as explained above is there!/- it does not initialize new cell objects even though the collection view was empty before the current update. I am not sure if this is the expected behaviour or I have some other problem in my code, however my question is - how can get to a point where I reset all the content on the collection view and dequeueReusableCell returns a newly initialized cell object.
I have learnt this the hard way! Save yourself some time Petar by knowing this that In any collection view/tableview, anytime there is any change of constraint or any UI element in its layout structure, you should ALWAYS, and ALWAYS make another prototype cell. It is the ONLY correct way, so don't think you ll be putting some more time in making another cell.
As I read your comment where you said you ll initiliaze another view based on that one condition where you want to reset everything. Just have another cell prototype with that another view and dequeue that now.
Hope it solves your problem
Related
I'm working on a view controller, where collection view cells are inserted when user scrolls.
I use reloadData() method only at the beginning. (viewDidLoad)
After first load, I use insertItems(at:) method whenever user scrolls.
There are a lot of cells to be added, so cells should be reusable.
But I'm wonder if cells are reused when I insert cell directly.
Are cells reused when they are inserted? (not reloadData)
Short answer: Yes, cells are reused.
Longer answer:
When you call dequeueReusableCell(withReuseIdentifier:for:) to get a cell for an item in the collection view it would return a reusable cell object located by its identifier.
Call this method from your data source object when asked to provide a
new cell for the collection view. This method dequeues an existing
cell if one is available or creates a new one based on the class or
nib file you previously registered.
Documentation
I have another question open where I'm trying to figure out how to reload the collectionView without auto-scrolling. I was also realizing there are a lot of other situations where I will need to change things in the collection view. Also I have some items that I will want to change the .alpha on and change the text of. Is there a way to do all of this in Swift? For example (to be specific) if I have a collection view with a view in each cell and that view has a textField in it, can I change the alpha and text, (change alpha with animation even) without reloading entire table?
Look at the documentation for UICollectionView. There are several "reload" methods:
reloadData()
reloadSections(_:)
reloadItems(at:)
If you just want to reload a single item, update your data source's data and then call reloadItems(at:) passing in the index path for the item.
Another option, if a cell is currently visible, is to use the cellForItem(at:) method to get a reference to an existing cell. Then you can directly access UI components of the cell as needed. You should also update your data model as needed so if the user scrolls and comes back, the cell will be rendered properly.
Most appropriate where you can update your custom view of a particular UIcollectionViewcell is reloadItemsAtIndexPaths.
You would be handling a particular item than whole collectionview with reloadData.
You can handle it via notifications or some call backs in your code where you can make decision when to update which cell.
Hope it will help you.
I want to access/update UITableView cell (using reusable cells) which is not in the current view . I know the table view cells are reusable, that can be the reason I am unable to fetch them but is there any way of virtually making and updating. OR I have to drop the reusable cell technique. Suppose tableview have total 20 cells but only say 7 are visible in the current view of iPhone. How will i update other 13 cells which are out of view bounds
Accessing and modifying cells (even if you could) would be a bad pattern. UITableViewCells are designed to be created and modified solely in the tableView:cellForRow:atIndexPath datasource method, where framework automatically asks you what to do with cells that are about to be displayed.
The whole idea behind reusability is that the system takes care of the view for you, and all you need to do is take care of your datasource and instruct the system, using the model, how to render cells, in its allocated datasource method.
This paradigm would be defeated if we started accessing cells manually and modifying them.
You can't access those cells because they are not added to the UITableView but are kept in a queue until user scrolls to them, then they are added to the UITableView. Instead update your model, which will reflect changes on the cells.
I used to use static UITableView but the table is too long and overflow the memory.
I switched a dynamic prototype UITableView with 1 type of cell, which has an UISwitch in it.
One of the cell, when turning on the switch, will turn off the switch of another cell. These cells have fixed index.
The IBAction method is in my UITableViewCell subclass and I don't want to add the UITableView as a property in my UITableViewCell.
How do I achieve the above effect?
I'm planing to use an id or similar to distinguish between the cells as each cell's switch has different effects, that doesn't solve the above requirement.
Thanks,
I would add a block property to your cell which you can use to notify your controller of changes in the switch. See my answer below to a question on this:
How can I get index path of cell on switch change event in section based table view
All your logic can now be implemented in the view controller.
You are best to create a data model in the view controller which the cells simply provide views and controls onto. When you flick one switch and the block fires, update the data model and simply reload the table. Any cells affected will show the new data model positions for their switches. Avoid using one cell to adjust another. Just update the model and reload the cells.
I have created a subclass of UITableViewController that is used as the custom class for a View in my storyboard. The view has a number of sections/rows defined as prototype cells which are instantiated and shown as expected. Most of the UITableView delegate methods simply call the super's methods that handle section amount, rows, etc.
I have cached content that is used to update the cells on -viewDidLoad and then an asynchronous operation that reloads the content from my server and rebinds the data afterwards (on the main thread, -performSelectorOnMainThread::). It is at this point that, seemingly arbitrarily, some of the cells content (labels primarily) will be cleared of data and not updated to the new data for anywhere between 10-15 seconds. At which point either the content which just show up or sometimes scrolling in the table view will cause the content to appear.
I know the selector is being called and on the main thread, the UI element's text properties are getting set but randomly they just...don't update. I've tried adding in -setNeedsDisplay on the tableView, controller's view and -reloadData on the tableView (though the last one seemed unnecessary as they're prototype cells) all to no avail.
Anyone come across this?
I am not sure if this is caused by the thread aspects, or how the tableView is handled. If it is tableView, check out this post since there are some similarity to disappearing data that my app was experiencing until I handled the dynamic, prototype tvCells correctly.
My comment did indeed fix my problem. It seems UILabel's are not updated when modified but rather it's decided internally when to repaint them - regardless if you try to force it with display or setNeedsDisplay.
Solution: Use a UITextView instead of a UILabel