I have a collection view in my app, I want it to contain a custom cells. I've created a custom cell view xib file. Then I use it in my data source method :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
OtherCustomersCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:OTHER_CUSTOMERS_CELL_IDENTIFIER forIndexPath:indexPath];
if(cell == nil){
NSArray *nsObjects = [[NSBundle mainBundle] loadNibNamed:#"OtherCustomersCell" owner:nil options:nil];
for(id obj in nsObjects)
if([obj isKindOfClass:[OtherCustomersCell class]])
cell = (OtherCustomersCell*) obj;
}
[cell.name setText:#"AAAA BBBBB"];
return cell;
}
But when I run the app, there is just a black rectangular where the collection view should be (at the bottom under the table view):
What am I doing wrong?
Thank you in advance.
Collection views work differently than table views in that you don't have to create a cell if one can't be dequeued.
Instead, you have to register the nib for the cell first:
- (void)viewDidLoad
{
...
UINib *cellNib = [UINib nibWithNibName:#"OtherCustomersCell" bundle:nil];
[collectionView registerNib:cellNib forCellWithReuseIdentifier:OTHER_CUSTOMERS_CELL_IDENTIFIER];
}
You can then dequeue the cell and it will be created automatically for you if necessary:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
OtherCustomersCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:OTHER_CUSTOMERS_CELL_IDENTIFIER forIndexPath:indexPath]; // cell won't be nil, it's created for you if necessary!
[cell.name setText:#"AAAA BBBBB"];
return cell;
}
You have to register UICollectionView instance in the following way in viewdidload then you can use this.
[self.photoListView registerNib:[UINib nibWithNibName:#"UIcollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"Identifier"];
Related
The code is a simple collection view with a bunch of images
I ran it and Xcode doesn't argue about anything but the simulator shows a black screen after running the app.
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return recipePhotos.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier =#"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
// Configure the cell
UIImageView * recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image=[UIImage imageNamed:[recipePhotos objectAtIndex:indexPath.row]];
return cell;
}
Check collection view datasource outlet, maybe it was not connected with your controller?
Check receipeImageView is not nil.
Did you register your UICollectionViewCell with identifier #"Cell"?
If you don't want black background, you have to set
collectionView.backgroundColor = [UIColor clearColor];
Then you must register the cell
UINib *cellNib = [UINib nibWithNibName:#"yournibname" bundle:nil];
[collectionView registerNib:cellNib forCellWithReuseIdentifier:#"cell"];
Both need to be implemented in viewDidLoad method
I have a tableview, in this tableview i have four rows, in each row i added a collection view programatically and i check that if its my first row i should register 1st nib of collection view cell, if its my 2nd row, i should register 2nd nib of collection view cell and so on and than i simply reloads the collection view. I used the below code:-
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"cellID"];
if(cell==nil){
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cellID"];
cell.selectionStyle=UITableViewCellSelectionStyleNone;
}
[cell.contentView.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
UICollectionView *collectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height)];
collectionView.dataSource=self;
collectionView.delegate=self;
if (indexPath.row==0) {
[collectionView registerNib:[UINib nibWithNibName:#"QuotesCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"quotes"];
} else if (indexPath.row==1){
[collectionView registerNib:[UINib nibWithNibName:#"AlphabeticalWiseCategoriresCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"alphabets"];
} else if (indexPath.row==2){
[collectionView registerNib:[UINib nibWithNibName:#"DaysCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"days"];
}else if(indexPath.row==3){
[collectionView registerNib:[UINib nibWithNibName:#"LifeAspectsCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"life"];
}
[collectionView reloadData];
return cell;
}
My problem/question is how could i come to know with which collection view nib i have to deal with in following delegates, because here i have to specify the same reuse identifier that i have used while registering nib with collection view ?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
}
My Second problem is how could i detect which tableview row's collection view cell's is clicked since i have different collection view?
Firstly, why do you not use static table view? If you hardcode every cell, I think it will be good enhancement.
Next about your problem, iOS provides every UIView tag property.
If you remake your table to static table, then you will can set tag property via InterfaceBuilder. If not:
UICollectionView *collectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height)];
collectionView.dataSource=self;
collectionView.delegate=self;
collectionView.tag = indexPath.row;
Then:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
switch collectionView.tag {
case 0:
...
break
case 1:
...
break
}
}
And your can use this approach to resolve your second problem
You could keep the collectionView you created each time, say, in an array. So the index of each collectionView in the array will be equal to the indexPath.row. By retrieve the index of the collectionView parameter in - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath, you could know which collectionView you are dealing with, as well as the UICollectionViewCell.
I've got an issue with my UICollectionView where my cells are always initiated blank/in a default state with no data.
The data only appears in the cells after scrolling them in and out of view.
Code:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"EquipmentCell";
APInventoryCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
if (!cell) cell = [[APInventoryCollectionViewCell alloc] init];
//set cell data...
cell.label.text = [arrayOfStrings objectAtIndex:indexPath.row];
return cell;
}
Your problem is that you probably set the arrayOfStrings somewhere in the viewDidLoad method of your view controller, the problem with that is that the collectionview datasource calls are done before that.
What you should do in your viewDidLoad method just call [collectionview reloadData]; an you will be fine
All,
I am adding a UICollectionView to a UIView but it's failing to load cells because it seems that this:
[self.buttonsCollectionView registerNib:[UINib nibWithNibName:#"AccountMenuCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"AccountMenuCell"];
Is getting loaded after it hits the delegates for the UICollectionView. Normally this would be placed in viewDidLoad but is not available in a UIView.
- (AccountMenuCollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
AccountMenuCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"AccountMenuCell" forIndexPath:indexPath];
[cell.accountMenuButton setTitle:#"Deposit" forState:UIControlStateNormal];
return cell;
}
Any guidance?
EDIT:
So I am using a view from the storyboard initially and then adding a subview which is Account Menu. Within this view I have a Collection View.
Try to use with the default method and instantiate your Cell inside of the cellForItem...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
AccountMenuCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"AccountMenuCell" forIndexPath:indexPath];
[cell.accountMenuButton setTitle:#"Deposit" forState:UIControlStateNormal];
return cell;
}
and .. verify with Breakpoints if your code is running..
I have a very frustrating problem with UICollectionView and its dequeuing mechanism.
In a nutshell, I have a custom UIView with a label inside. I set this up as the selection background view in my custom cell as follows:
//My Custom Cell Class
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
_selectionView = (MyCustomView *)[[[NSBundle mainBundle] loadNibNamed:#"MyNibName" owner:self options:nil] objectAtIndex:0];
self.selectedBackgroundView = _selectionView;
[self bringSubviewToFront:_selectionView];
}
return self;
}
Note that all the layout work, etc for both the cell and selectedBackgroundView is done in the nibs.
Whenever the cell is selected, I'd like to set custom text in the label for selectionView so in my custom cell I also have the following method:
//In my Custom cell class
- (void) setSelectedViewLabelText:(NSString *)paramText{
if(!self.isSelected){
return;
}
self.selectionView.label.text = paramText;
}
To set the text I have in my UICollectionViewController:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCellClass *selectedCell = (MyCellClass *)[self.collectionView cellForItemAtIndexPath:indexPath];
[selectedCell setSelectedViewLabelText:someString];
}
The problem is that whenever the UICollectionView recycles the cell, it inits them again and obviously the setSelectedViewLabelText method isn't called.
I have an annoying feeling that I may have to track the selected indexPaths and enumerate through them to see if a cell is selected and call the method, but I have potentially large data sets and can foresee how this will become a performance problem.... any ideas?
Thanks in advance!
Keep track of your selected cell, like:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCellClass *selectedCell = (MyCellClass *)[self.collectionView cellForItemAtIndexPath:indexPath];
[selectedCell setSelectedViewLabelText:someString];
selectedIndexPath = indexPath;
}
In cellForItemAtIndexPath check indexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//.......
if([selectedIndexPath isEqual:indexPath]){
[cell setSelectedViewLabelText:someString];
}
return cell;
}
Hope this helps.. :)