UICollectionView Static CustomCell reuse - ios

I have a problem i create UICollectionView with custom cell to display items. But after refresh of the UICollectionView reusable cell populate for wrong index
UICollectionView before refresh.
UICollectionView after refresh.
Code example of the reusable collection view cell.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GalleryCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (indexPath.item != 0)
{
[cell setCollectionItem:[collectionData_ objectAtIndex:indexPath.row - 1]];
}
return cell;
}

Think it's reusing another cell (the balloon in this case) and is not setting anything for the first index cell. If you make an else statement to create a new camera cell, hopefully it will reappear.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GalleryCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (indexPath.item != 0) {
[cell setCollectionItem:[collectionData_ objectAtIndex:indexPath.row - 1]];
} else {
// Set camera item here
}
return cell;
}

This problem occurs because the cells will be reused. Cells are reused to improve the performance of the system. If your table has 1000 cells, the system does not allocate 1000 cells but a much lower then reuse-
Try with adding else clause to the if
if (indexPath.item != 0)
{
[cell setCollectionItem:[collectionData_ objectAtIndex:indexPath.row - 1]];
}
else
{
//Set your cell at index 0 with your camera image
[cell setCollectionItem:#"camera-image"];
}

Related

Executing network request once cellForItemAtIndexPath is completed for CollectionView?

I have a collection view that in which a cell is populated based on an array of int's.
After the cells are created I want to check for parameters for each cell via network request.
At the moment I carry out the network request for each cell in this method and it causes a cell to be created before its parameters are assigned due to inconsistent networks.
Is there a method to run a network function (sendGetPar:) on completion of laying out the cells? Obviously this can then be reused when the user scrolls etc.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
BOOL isFocusOn = [_userDefault boolForKey:#"mixFocusOn"];
if (isFocusOn == TRUE) {
CDCChannelStrip *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
NSNumber *setChan = [self.focusChannels objectAtIndex:indexPath.section];
NSInteger chanInt = [setChan intValue] +1;
cell.clipsToBounds = YES;
[cell initData:(chanInt)];
[self.mixMonitorView setChannelsStripToType:(cell)];
[self.mixMonitorView sendGetPar:chanInt];
return cell;
}
I believe the Apple's documentation would be helpful
probably the methods:
collectionView:didEndDisplayingCell:forItemAtIndexPath:
Tells the delegate that the specified cell was removed from the collection view.
collectionView:didUpdateFocusInContext:withAnimationCoordinator:
Tells the delegate that a focus update occurred.
Something like this:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
BOOL isFocusOn = [_userDefault boolForKey:#"mixFocusOn"];
if (isFocusOn == TRUE) {
CDCChannelStrip *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
NSInteger chanInt = indexPath.row +1;
cell.clipsToBounds = YES;
[cell initData:(chanInt)];
[self.mixMonitorView setChannelsStripToType:(cell)];
[self.mixMonitorView sendGetPar:chanInt];
return cell;
}
-(void) sendGetPar:(NSInteger)index // you could return the parameter via this method.
{
NSLog(#"Parameter:%ld", (long)index);
}

Display different cells based on data type in UICollectionView

I have three different types of cells with different content size (containing image, label and button) in UICollectionview. I am getting data from web services. I want to show correct cell based on these types.
Firstly you register nibs of layouts for your cells:
[collectionView registerNib:myCellTypeImageNib forCellWithReuseIdentifier:#"MyModelTypeImageCellIdentifier"];
[collectionView registerNib:myCellTypeLabelNib forCellWithReuseIdentifier:#"MyModelTypeLabelCellIdentifier"];
[collectionView registerNib:myCellTypeButtonNib forCellWithReuseIdentifier:#"MyModelTypeButtonCellIdentifier"];
Then return them appropriately:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyModel *modelObject = self.dataArray[indexPath.item];
UICollectionViewCell *cell = nil;
switch (modelObject.type) {
case MyModelTypeImage:
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyModelTypeImageCellIdentifier" forIndexPath:indexPath];
//adjust cell
break;
case MyModelTypeLabel:
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyModelTypeLabelCellIdentifier" forIndexPath:indexPath];
//adjust cell
break;
case MyModelTypeButton:
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyModelTypeButtonCellIdentifier" forIndexPath:indexPath];
//adjust cell
break;
}
return cell;
}
You can use
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
Note: indexpath
For example. Add all the images in to an array.
self.myArray = [[NSArray alloc] initWithObjects:#"first.jpg",
#"second.jpg",
#"third.jpg",
#"last.jpg",nil]
Then in cellForRow... do the following:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// configure cell
...
cell.myImageView = [self.myArray objectAtIndex:indexPath.row;
}

How to avoid UICollectionView repeating cells?

Hello I have a UICollectionView. I load data from a NSMutableArray and it has 4 objects. But my problem is its repeating the same cells again.
`
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return mutArrayArtists.count;
}
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 2;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
artist = [mutArrayArtists objectAtIndex:indexPath.row];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = artist.artistImage;
UILabel *lblArtistname=(UILabel *)[cell viewWithTag:102];
lblArtistname.text=artist.artistName;
UILabel *lblSongCount=(UILabel *)[cell viewWithTag:101];
lblSongCount.text=artist.numberofSongs;
return cell;
}
`
But the result is like this
How can I avoid this? Please help me
Thanks
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 1; //instead of 2
}
The section here does not mean the number of columns. It means that the collection view will contain 2 sections vertically above each others
This is the problem:
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 2;
}
You have two sections to the collection view, and in your cell provider, you don't distinguish the sections. Change it to say return 1; (assuming you do want just one section in the collection) or update the cellForItemAtIndexPath function (by inspecting indexPath.section) to split the sections out as you intend.
This might be helpful
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}

Xcode UICollectionView How To Disable Some Cells by indexpath

I have been trying to figure out how to disable cells in a collectionview by indexpath or by using the cellsforitemsatindexpath method of collectionview. I have the following code below but this only disables the last cell in the loop. I also have the following image for when I run the code in Xcode. So far only the third cell horizontal is disabled on first row at top, but I want to disable or set values to nil the first 3 cells from the top row horizontal. From the image link below, the missing '9' on the third cell indicates that value was set to nil. Any suggestions are appreciated.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCollectionCell" forIndexPath:indexPath];
if (cell != nil)
{
// May not need this
NSInteger cellIndex = [myObjectsArray objectAtIndex:indexPath.row];
for (int i = 0; i < rangeNumOfCellsToDisable; i++)
{
if (indexPath.row == i)
{
// If true, code goes here
}
else
{
// If not true, code that sets stuff to nil goes here
}
}
}
return cell;
}
Screenshot Image
https://drive.google.com/folderview?id=0BzaP1abbReAhMTYtSEh3alFlaGs&usp=sharing
Screenshots: https://drive.google.com/folderview?id=0BzaP1abbReAhVzhCeEY2eFZibFE&usp=sharing
Hi please try this solution.
I am assuming that you want first three cells to be disabled or you can have any cells disabled..
in .h file
-#property(nonatomic,retain)NSMutableArray *disableArray;
in.m file
disableArray=[[NSMutableArray alloc]init];
[disableArray addObject:#"0"];
[disableArray addObject:#"1"];
[disableArray addObject:#"2"];
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCollectionCell" forIndexPath:indexPath];
if (cell != nil)
{
// May not need this
NSInteger cellIndex = [myObjectsArray objectAtIndex:indexPath.row];
if([disableArray containsObject:[NSString stringwithformat:#"%d",indexPath.row]])
{
//the row which you want to disable do whatever you want over here...Hope this helps.
}
}
return cell;
}

How to make two collection views appear on the same view controller?

I want to have two UICollectionView in same page. Two UICollectionView that would show different data as required. How can I do this?
Thanks in advance.
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifierHall2 = #"hall2";
/* Uncomment this block to use subclass-based cells */
timeCell *cell = (timeCell *)[myCollectionViewHall2 dequeueReusableCellWithReuseIdentifier:cellIdentifierHall2 forIndexPath:indexPath];
[cell.timeButton setTitle:[[allSimilarMutableArray valueForKey:#"showTime"] objectAtIndex:indexPath.item] forState:UIControlStateNormal];
return cell;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifierHall3 = #"hall3";
/* Uncomment this block to use subclass-based cells */
timeCell *cell = (timeCell *)[myCollectionViewHall3 dequeueReusableCellWithReuseIdentifier:cellIdentifierHall3 forIndexPath:indexPath];
[cell.timeButton setTitle:[[allSimilarMutableArray valueForKey:#"showTime"] objectAtIndex:indexPath.item] forState:UIControlStateNormal];
return cell;
}
You can do the same by differentiating in 'cellForItemAtIndexPath'
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionView == self.collectiveview1) {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionCell" forIndexPath:indexPath];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
[titleLabel setText:celldata];
UIImageView *imageView = (UIImageView *)[cell viewWithTag:200];
[imageView setImage:[UIImage imageNamed:connimage]];
return cell;
} else {
static NSString *cellIdentifier = #"FollowCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
[titleLabel setText:celldata];
UIImageView *imageView = (UIImageView *)[cell viewWithTag:200];
[imageView setImage:[UIImage imageNamed:cellImage]];
return cell;
}
}
Hope it helps.
Because both UICollectionView's respond to the same protocol: UICollectionViewDataSource, you must differentiate between them in the method:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
You can do this multiple ways, depending on how your UICollectionView's are created.
1. If you created them in Storyboard or in Interface Builder, link them to your class using IBOutlet's. Then you can distinguish between them with the following code:
if (collectionView == self.firstCollectionView) { ... }
else if (collectionView == self.secondCollectionView) { ... }
Both firstCollectionView and secondCollectionView must be properties in your View Controller class.
2. Another way is to set tags to them either on Storyboard/Interface Builder or in code with tag property.
So you can for example do this:
self.firstCollectionView.tag = 100;
self.secondCollectionView.tag = 200;
And then again in the cellForItemAtIndexPath method you can distinguish them like:
if (collectionView.tag == 100) { ... }
else if (collectionView.tag == 200) { ... }
Even if you created the collection views in code, you can use the same techniques. Either create properties that point strongly to the collections and compare the pointers or compare them by tags.
The delegate method for cellForItemAtIndexPath also passes in the instance of the collection view it's requesting a cell for. This code snippet is correcting the code example you put in the original post. To take your example, here's how you do this:
- (void)viewDidLoad {
// Initialization of collectionView done previously, set delegates to yourself.
[self.collectionView1 setDelegate:self];
[self.collectionView2 setDelegate:self];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Setting the cellIdentifier to "hall2" by default, no need to check twice.
NSString *cellIdentifier = #"hall2";
// The collectionView requesting a cell is collectionView2, change the cellIdentifier
if ([collectionView isEqual:self.collectionView2]) {
cellIdentifier = #"hall3";
}
// Since the collectionView we need is already passed, just dequeue and reuse from it.
timeCell *cell = (timeCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.timeButton setTitle:[[allSimilarMutableArray valueForKey:#"showTime"] objectAtIndex:indexPath.item] forState:UIControlStateNormal];
return cell;
}
I hope this helps you understand how to use multiple collection views with the same delegate.
You can tag the two collection view with different value.
In order to add two UICollectionView in the same page, i user collectionView.tag to identify each of them and decide witch data to pass to each one.
Also, i needed to define different cell sizes for each collection view, but in this method collectionView.tag wasn't working for me. So i had to define a different UICollectionViewLayout to each UICollectionView and then:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionViewLayout == layout1) {
return CGSizeMake(100,100);
} else {
return CGSizeMake(50, 50);
}
}

Resources