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

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);
}
}

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);
}

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;
}

UICollectionViewCell background color change works in cellForItemAtIndexPath but not didSelectItemAtIndexPath

I can change my collection view cell background color in cellforitematindexpath but not in didselectitematindexpath using the code below (i only change the color in one place however). How does this happen? I know that didselectitematindexpath is being called.
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"CollectionView" forIndexPath:indexPath];
cell.layer.borderWidth=1.0f;
cell.layer.borderColor=[UIColor grayColor].CGColor;
cell.label.text = #"test"
cell.contentView.backgroundColor = [UIColor redColor];
return cell;
}
-(void)collectionView:(UICollectionView *)cv didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected cell");
CollectionViewCell *cell = [self collectionView:cv cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor redColor];
}
Several things wrong here.
You're using the wrong method to get the selected cell. Never call the delegate method directly, instead ask the collection view for the cell directly like this:
CollectionViewCell *cell = [cv cellForItemAtIndexPath:indexPath];
You're modifying the cell in a place where those modifications will not persist. When you scroll and that cell gets reused, the color will get wiped out. Instead you should call reloadItemsAtIndexPaths: when the cell gets selected, and have some code in collectionView:cellForRowAtIndexPath that checks the selected property of the cell and sets the color you want based on that. That way, the layout will remain consistent when you scroll and cells are reused.
use this..
self.collectionView.allowsMultipleSelection = YES;
then..
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath**
{
static NSString *identifier = #"Cell";
RecipeViewCell *cell = (RecipeViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[recipeImages[indexPath.section] objectAtIndex:indexPath.row]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame-2.png"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame.png"]];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (shareEnabled) {
NSString *selectedRecipe = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
[selectedRecipes addObject:selectedRecipe];
}
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (shareEnabled) {
NSString *deSelectedRecipe = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
[selectedRecipes removeObject:deSelectedRecipe];
}
}

Reusing cell causes unwanted behaviour when updating cell view

I want ot set a border to a selected cell, i save a cell property that represents the selected one and manipulate it:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSArray *eyeArray = [self eyesArrayConfigure][indexPath.row];
if (indexPath.row==5) {
int r = arc4random() % 6;
eyeArray = [self eyesArrayConfigure][r];
}
[borderedCell.contentView.layer setBorderWidth:0.0f] ;
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
borderedCell = cell;
[borderedCell.contentView.layer setBorderColor:self.view.tintColor.CGColor];
[borderedCell.contentView.layer setBorderWidth:3.0f];
}
and the cellForView: (Im usinng 2 types of cell identifiers because one cell contains a label - "Random cell":
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row ==5) {
UICollectionViewCell *randomCell =[collectionView
dequeueReusableCellWithReuseIdentifier:#"randomCell"
forIndexPath:indexPath];
randomCell.backgroundColor = [UIColor purpleColor];
borderedCell = randomCell;
[borderedCell.contentView.layer setBorderColor:self.view.tintColor.CGColor];
[borderedCell.contentView.layer setBorderWidth:3.0f];
return randomCell;
}
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
NSArray *eyeArray = [self eyesArrayConfigure][indexPath.row];
myCell.backgroundView = [[UIImageView alloc] initWithImage:eyeArray[1]];
return myCell;
}
What i get is if a click one cell it will be fine till i scroll and then i get weird behaviour when couple of cells might be with the border.
Thanks for the help.
The solution is to use a view model. You are already doing this for your cells' background views. Apply the same concept for the border.
#interface MyCollectionView ()
#property (nonatomic) NSInteger selectedRow;
#end
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
//update self.selectedRow and either reload entire collection view or just the currently selected and previously selected.
self.selectedRow = indexPath.row;
[collectionView reloadData];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
CGFloat borderWidth = (indexPath.row == self.selectedRow) ? 3.0 : 0.0;
[myCell.contentView.layer setBorderWidth:borderWidth];
return myCell;
}

UICollectionView cell is not getting added as a subview of UICollectionView

I am new to UICollectionView.
I have followed this tutorial to learn how to use a UICollectionView, but the problem is that in the .xib (not using storyboard) I am not able to add UICollectionViewCell as a subview of UICollectionView.
In the tutorial the cell is automatically created under UICollectionView in the .xib.
Any help would be appreciated.
That tutorial is for working in stroy board in xib you ve to create custom cell first create view controller add UicollectionView to view Controller
then create custom class for collection cell
then craete empty xib resource and add collection view cell
and set class name and identifier for that control
then create delegates method to add custom cell to ur collectionViewController
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"customCell";
customCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}
You can start your controller and create a custom collection view cell for setting your view element and then you can use it into your collection view controller into xib, here is a good tutorials to do this http://adoptioncurve.net/archives/2012/09/a-simple-uicollectionview-tutorial/
Use this code for creation of collectionview and adding the subview.
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return [imageArray count];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
NSMutableArray *sectionArray = [imageArray objectAtIndex:section];
return [sectionArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell identifier
static NSString *cellIdentifier = #"cvCell";
/* Uncomment this block to use nib-based cells */
// UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
// UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
// [titleLabel setText:cellData];
/* end of nib-based cell block */
/* Uncomment this block to use subclass-based cells */
CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
NSMutableArray *data = [imageArray objectAtIndex:indexPath.section];
NSString *cellData = [data objectAtIndex:indexPath.row];
[cell.titleLabel setText:cellData];
cell.imageView.image = [UIImage imageNamed:[imageArray[indexPath.section] objectAtIndex:indexPath.row]];
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
header *sectionHeader;
if (kind == UICollectionElementKindSectionHeader)
{
sectionHeader = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"Hello" forIndexPath:indexPath];
}
UICollectionReusableView *test=[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"Hello" forIndexPath:indexPath];
return test;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
if (section == 3) {
return CGSizeMake(0, 100);
}
return CGSizeZero;
}
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(80, 80);
}

Resources