UICollectionView scroll to specific cell - ios

i try to create a UICollectionView who should open at a specific cell.
My approach is to store all cells:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) ->
UICollectionViewCell {
// my code
cells.append(cell)
return cell
}
then find the desired cell in viewDidAppear:
let result:[MyCell] = cells.filter{ $0.myProperty!.uuid == selectedUUID }
Unfortunately the desired cell can't be found within the cells array, because not all cells are stored yet.
Am i going in the right direction or do i need a different solution?
EDIT: removed misleading information

Don't work with the cell themselves.
Your cells are displaying data, right? They must. That data (could be numbers, or text, or an image, anything) should be a custom object.
For example, you're displaying a list of animals.
So you have the Animal class, with different properties (Size, weight, age). Again, all an example. Maybe you're displaying a list of students which have a FirstName, Lastname, and so on. Lets say we're using the Animal.
You have an array of Animal objects, you can have 1, or 4, or 234234, it doesn't matter. The array can hold as many animals as you want. But you only have one array.
Your collection view (or tableview) needs to create a cell for each row. How many rows?! Easy, the other methods tells us there are a specific number of rows per section. Let's say we only have one section.
How do you define rows? You give him a number. What number? The number of animals in your array. For example, 5. Or, much better, myAnimalsArray.Count. Now if you have 20 animals, you'll have 20 cells. If you have 3 animals, you'll have 3 cells.
Okay, now to the cells, you know how many you have, and the cellForRow will therefore create X cells, X being the count of your array.
You'll probably have a simple cell for testing, like
cell.title = animal.name
and then return the cell. It's all pseudo code here, but you get the idea.
Now to your actual question
I've written all that because, according to your other comments in the other answers, you seem pretty confused.
You have your animal array (the data), and no cells yet. You want to start on the animal that has a name starting with E, for example. Well, after you've all the animals on the array, you need to find the one that starts with E (or any other filter you might like). You find it with a searching method. Once its done, you will know the index of the animal in the array. It's the array item number 23, it's the Elephant.
Create an NSIndexPath object with section 0 and index 23 (because your filter found it's the 23rd item, again, i'm just using examples), and pass that indexPath object to the scroll method of the collectionview.
And you're good ;)
Do that in the ViewDidLayoutSubviews or viewDidAppear. (first one is better). But you must do it after your array of animals is loaded, otherwise you won't have any data to filter.
Once you've called the method in the link above, your collectionview will scroll, and if you've done it soon enough, it will load at that index and not at index zero.

i have solved this problem through this code hope it will helpful for you:
[self.collectionview setContentOffset:CGPointMake(0,self.collectionview.contentSize.height-self.collectionview.frame.size.height/2) animated:YES];
set above only parameter to contentsize:CGSizemake(x,y);
by adjusting your required parameter you can scroll to specific cell.
just replace above parameter inplace of c and y in contentsize:CGSizemake(x,y); method.
and you have to adjust parameter.

UICollectionView's cell is reused.
For example, if view can only show 3 cells once: A, B , C; then ur cells maybe like [A, B, C, A, B, C, A, B, ...];
each time, u set the property of cell, uuid will be reset to a new value.
so u cant filter out what u want.
Hitendra Hckr is right, u should "filter data array instead of filtering cells array".
Or u can "alloc" new cell instead of "dequeueReusableCellWithReuseIdentifier:forIndexPath:".(Not recommend)

For your case, you need to filter data array instead of filtering cells array, this way you can get exact index.
Based on the filteredIndex create indexpath using below method,
NSIndexPath(forItem: filteredIndex, inSection: yourSectionIndex)
This way you can scroll to particular cell.

Try adding a call to collectionView.reloadData() before scrollToItemAtIndexPath. This will ensure all required cells are created.

Related

Does cellForRowAtIndexPath get called multiple times for the same "item"?

Let's say I have a list of items that represent my data source:
self.items = [User]()
for model in self.fetchedItems(20){
self.items.append(model)
}
self.tableView.reloadData()
Let's say that my screen only fits 5 items.
Let's say that the first item in the array (indexPath = 0) is the user Hannah.
If the user scrolls all the way down to the bottom, then all the way back up, will cellForRowAtIndexPath get called for Hannah?
It might, it might not. There is no guarantee one way or the other. One possibility is that the cell that held the Hannah object will be returned by the dequeue method for a later index path and then when you scroll back up, the cellForRowAtIndexPath will get called gain for cell 0, and maybe it gets passed the same cell that was passed to cell 5... i.e., it is quite possible that the same cell will be used for multiple rows.
That's why it is so important to set the entire state of the cell when you dequeue it. Possibly using prepareForReuse as a helper. It is also why it's important to keep the array state fixed unless you explicitly tell the table view you have changed it (by calling reloadData or begin/end updates.)

Find Index Number Of A Specific UICollectionView Cell

I have a UICollectionView that returns 77 cells. I'm trying to figure out how to point to a specific cell, for instance the cell at row 2, column 4. To boil it down to my very basic need I need to write a statement that would do this:
if cell[46] == cell[12] {
println("they match")
}
I do not know where to start with this task. I started by trying to print the indexPath that is being used in my prepareForSegue method but that's not returning anything.
This collection view is using dynamic cells. Would it any difference to make them static cells?
There exists collectionView?.visibleCells() which returns [AnyObject] which you can cast to be of type UICollectionViewCell so you can get an array of on screen cells. Then you can access specific cells using subscript notation for comparison, but I still don't think directly comparing the cells is the best approach and if you can store your data in such a way that you can easily access the values without making a request to the server each time, that would be a much better approach for what you're attempting to accomplish.
As mentioned by #jkaufman, you need to use a method that gets you a cell from an index path. func cellForItemAtIndexPath(_ indexPath: NSIndexPath) -> UICollectionViewCell? is the method you would need, and you can pass it an index path, which can be constructed with a section and row index. From there, you could get each of your cells, and do the comparison after retrieving both cells from the cellForItemAtIndexPath.
Function documentation: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/#//apple_ref/occ/instm/UICollectionView/cellForItemAtIndexPath:

Swift: Get value of multiple selected UICollectionViewCells

I have a UICollectionView with multipleSelection allowed. How would I retrieve the value of the labels stored in each selected cell?
So if I had three cell: "first", "second", "third"
And I selected the first two, it would return an array equal to: ["first", "second"].
Access the selected items using indexPathsForSelectedItems. In your example above, that should return you an array with the first two index paths for row 0 and row 1 (assuming "first", "second", and "third" are actually in that order). Iterate through that array and use each indexPath contained within to grab the cells using cellForItemAtIndexPath:. Now that you've got the cells, you can grab the labels by casting the resulting cells as YourCustomCell and accessing the label property.
EDIT: #rdelmar makes a good point in the comments below. Your first resort should always be to avoid using the cells as a source of info and rather reference the dataSource providing info to the cell in the first place. However, should you need to obtain a reference to the cell for some purpose NOT addressable by examining the dataSource (calling one of the cell's methods, etc), the steps above are the way to go.

iOS Dynamic cell content

I have searched for this a lot and haven't found what I am looking for.
I want to have UITableViewCell such that each have dynamic content. For example, one cell can have a place name, address, phone number, image, etc. Another cell can have some or all of these attributes.
I know that I should have functions cellForRowAtIndexPath: and heightForRowAtIndexPath: return stuff appropriately.
The problem I am facing is that I have my cells designed in nib files, and am loading the layout from there. I can calculate the heights for each cell based on conditions(though this is tedious), also I need to arrange stuff in that cell if one thing is missing. For example, if place name is missing then move all the elements up via setFrame:.
There should be an easy way out I believe?
In such dynamic cases I would not bother with using storyboards to accomplish this. It should be very easy to do this programatically...
If you really do need to create this in a storyboard you could generate a full cell which could consist of (for instance) 5 labels. Now in the table view data source I presume you have some array of objects where each element represents a single row in the table view. If so then in your case each of this object can have a method that will return an array of non-empty strings (the strings that will actually be displayed) which can be a dynamical count from 1 up to 5 strings.
If you do this you will request this array in method requesting the height for row at index path and by using this count you can then return the height of the row (for instance numOfStrings*40.0f). Inside the method requesting your cell you can simply fill those labels with the same array you use to calculate the height.
As for non storyboard approach I suggest you to override an UITableViewCell, generate a static method that will return you the cell height for string count and generate an initializer with the string array which should then iterate through the array generating the labels and setting the text to it.

How to add static tableviewcells on runtime in IOS

I'm new in objective C.
I am using an static table view controller to load data related to my Class GAME.
I have 2 sections, in one section are cells related to the game, and in the last section y want to add the players who were in the game, which can be as many as I want. For this I created a button in the last cell of the first section addPlayer.
I want to create a new row in the 2nd section each time I touch addPlayer. how can I achieve this?
Thanks!
PD: Do I need to have the first row of the section 2 added by story board? Don't I?
if you want to add cells each time you add a player you could have, for example, a NSmutableArray which will contain the players and when you create a player you add it to that array and call the table's [yourTable realoadData] method. Then, your UITableViewController cellForRowAtIndexpath: method should loop through that array and add the cells dynamically. Use the array's count to keep track of the indexPath. You might have to keep track of the section so that you add the initial cells of the first section (the Date cell, the Pozo cell and the button cell) Keep in mind you will need to add a prototype cell in the Storyboard and set its identifier so that you may reuse the cell otherwise you will have to keep creating and adding cells to the table, which is not efficient.
Let me know if it works or if you have more questions!
You can't add static rows at runtime, you should go for dynamics.
What you can do, but only if you are using a Table View Controller, is create the maximum number of rows that you need, and override the – tableView:heightForRowAtIndexPath: to return zero height rows, at the indexPath that you don't need to show.

Resources