configure UICollectionView cell on initial lookup - ios

I am getting cells for a UICollectionView by calling dequeueReusableCellWithReuseIdentifier:. I want to set some specific configuration information the first time my cell is returned from this method and not subsequently when it gets reused. Is there a hook somewhere where I can run "one time" code on collection view cells?
Obviously I could just set this information every time or use a boolean to keep track of whether or not the cell has been initialized, but I'd like to know if there's a cleaner way first.

This is easy enough to do from within a cell's implementation but there's no convenient way for a data source to differentiate newly created vs reused cells. If your configuration must be supplied by the data source then the data source probably need to check if the cell has been configured already.
The cells will be created once so you can use init or awakeFromNib to set some initial state. Cells will then have prepareForReuse called when being reused allowing you to perform any changes you need to make per-use.

The way I ended up solving this was to put my own view inside a generic UICollectionViewCell with a view tag. Then, when I go to deque my cell, I pull out the view using viewWithTag. If I get nil back, it's the first time this code has run, so I can init my view using my own constructor normally. This seemed slightly better than keeping track of a boolean in the cell implementation.

Related

Is there a way to directly access UICollectionView elements without reloading?

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.

Can UICollectionViewUpdateItem be used to update a single label?

I'm trying to update a single label in a collection view cell. I know how to update the entire collection view and how to update a single cell, but I want to update only a label because if the whole cell updates it will change other stuff which I don't want to change yet. In the docs I found something called UICollectionViewUpdateItem but cannot figure out how to use it. Is this capable of updating a single label or if not is there another way?
If you know the index path of the cell you want to update, you can get the cell using cellForItem(at: IndexPath). From there you can edit your cell's label.
However, I suggest you don't change your underlying data so that it's in a state that is unsuitable for presentation in the UI. The collection view can decide to create cells at times that are unpredictable to you.
UICollectionViewUpdateItem is used to indicate e.g. from where a cell moved, and where it moved to, or that a cell at a certain position was deleted, updated, etc. The docs state:
You do not create instances of this class directly.
So it means you should only create it indirectly, for example through reloadItems(at: [IndexPath]). It will reload your entire cell and should not be used to update a single detail of it.

How to access UITableView Cell which is not yet in view?

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.

How to add cell to tableview's reuse queue before 'cellForRow:'?

Creating a cell costs a lot of time and make the first scroll lagging, so I want to create a cell and add it to tableview's reuse queue before cellForRow: called.
I use dequeueReusableCellWithIdentifier: in viewDidLoad, but when I scroll the table, the cell is being created again.
In general all drawing methods of scrollview should be kept as simple as possible to avoid lag. This means you should prepare your data/model in viewDidLoad/viewWillAppear or even in previous ViewController. Your cellForRow should be as simple as set this image(s) and those text(s) - no checks, no expensive operations such as bluring, retrieving data from CoreData/Network, etc.
If you are not sure which thing exactly causes your lag, you should learn how to use TimeProfiler. If you feel lost in documentation, have a look this(quite outdated though) tutorial.
With thus said I cannot be able to help you anymore until you post some code which we could discuss.

UITableview cell reinitializing every time in iOS 7

All,
I hope most of you know that with ios7 there is not need to do a null check for tableview reuse
if (cell == nil) {
But unfortunately, because of that the cells are always reinitialized, as we put the code in the same method for initializing values. The problem is only with text fields inside the tableview though.
Let me explain the scenario. I have a table view with multiple rows, and some rows contain multiple text boxes. I populate the textboxes with data from server when the page is loaded. Since the cells are always re-initialized as i explained above, whatever I enter in the field goes away and the server data is re populated once i scroll down and come back to the initial stage. This is because the populating the data code is also in the same place. After fetching a reusable cell it populates the data.
Previously till ios6, we used if(cell==nil) and hence we loaded server data inside the cell and when reusing the cell, this piece of code will never be called.
I have other dirty solutions, but would like to know if someone else has a graceful way of dealing this. Please help.
You just don't store any data in the table view cell but in the model that fills the table cell. This is always the way it should be done.
Looking from the MVC standpoint than the UITableViewCell is a view. Since it is reused by iOS you should use a model to the view.
Yes, this is the expected behavior of UITableView. For performance reasons, cells are reused. Thus, it is your responsibility to populate the views in a Table View Cell every time tableView:cellForRowAtIndexPath: is called.
The thing I don't understand from your question - are you making a network call every single time a cell comes into view? If so, cache the results somewhere. Or, if it's a small amount of data, consider just doing it all in one shot at the beginning (still need to be asynchronous though).
One thing I see a lot of developers do is move a lot of code into UITableViewCell subclasses, which sounds like a good idea because it's modular, but makes solutions for problems like this more difficult. Have the Table View Data Source manage the network calls.
If you need some inspiration, look at Apple's LazyTableImages sample.

Resources