I'm simply trying to call a method with a custom UICollectionViewCell and it's crashing with SIGABRT
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if([_leaderboardDictionary count] > 0 && indexPath.row == 0)
{
return [self insertLeaderBoardCellAtIndexPath:indexPath];
}
else
{
return [self insertDetailGraphicCellAtIndexPath:indexPath];
}
}
-(CampaignDetailGraphic2Cell *)insertDetailGraphicCellAtIndexPath:(NSIndexPath *)indexPath
{
CampaignDetailGraphic2Cell *cell = (CampaignDetailGraphic2Cell *)[_topCollectionView dequeueReusableCellWithReuseIdentifier:#"detailWebCell" forIndexPath:indexPath];
if(cell == nil)
{
if(is3_5Inches)
{
cell = [[CampaignDetailGraphic2Cell alloc] initWithFrame:CGRectMake(0, 0, 300, 172)];
}
else
if(is4Inches)
{
cell = [[CampaignDetailGraphic2Cell alloc] initWithFrame:CGRectMake(0, 0, 300, 220)];
}
else
if(isIphone6)
{
cell = [[CampaignDetailGraphic2Cell alloc] initWithFrame:CGRectMake(0, 0, 355, 290)];
}
else
if(isIphone6Plus)
{
cell = [[CampaignDetailGraphic2Cell alloc] initWithFrame:CGRectMake(0, 0, 394, 356)];
}
}
[cell setupCell];
...
}
This method exists within my CampaignDetailGraphic2Cell class.
Any idea how I can call methods and set properties of a cell ... ?
You shouldn't create UICollectionViewCells with alloc init. You need to register a class or nib file when you set up the collection and then dequeue the cell. Once you do that you can call the methods on your cell.
ie
[self.collectionView registerClass:[CampaignDetailGraphic2Cell class] forCellWithReuseIdentifier:#"CampaignCell"];
then
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CampaignDetailGraphic2Cell* cell = (CampaignDetailGraphic2Cell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"CampaignCell" forIndexPath:indexPath];
...
return cell;
}
Related
in one of my application i have implemented dashboard screen with collection view and when user clicks on collection view cell's it is not interacting this is happening to only iPhone12 pro max users
currently i don't have that real time device to test but i have tested in iPhone12 pro max simulator and its working fine
can you please suggest what was the cause or any suggestions?
thanks in advance
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0)
{
customClassCollectionViewCellOne *cell = [[customClassCollectionViewCellOne alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
cell = (customClassCollectionViewCellOne *)[collectionView dequeueReusableCellWithReuseIdentifier:#"accountBalance_main_collectionview" forIndexPath:indexPath];
cell.balanceArray = newbalanceArray;
cell.delegate = self;
[cell.collectionView reloadData];
return cell;
}
else if (indexPath.section == 1)
{
customClassCollectionViewCellTwo *cell = [[customClassCollectionViewCellTwo alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
cell = (customClassCollectionViewCellTwo *)[collectionView dequeueReusableCellWithReuseIdentifier:#"QuickActions_main_collectionview" forIndexPath:indexPath];
cell.quickActionList = viewModel.quickActionsList;
cell.delegate = self;
[cell.collectionView reloadData];
return cell;
}
else
{
customClassCollectionViewCellThree *cell = [[customClassCollectionViewCellThree alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
cell = (customClassCollectionViewCellThree *)[collectionView dequeueReusableCellWithReuseIdentifier:#"GetInTouch_main_collectionview" forIndexPath:indexPath];
cell.getinTouchList = viewModel.touchList;
cell.delegate = self;
[cell.collectionView reloadData];
return cell;
}
}
just informing
custom collectionview cell class contains sub collection view again
Try adding your view components to the cell's content view and not directly as a subview.
I have two UICollectionViews in a single UIViewController. I am separating them by tag number so that I can use the data source and delegate methods for both. However, when I run the code it crashes with the Exception:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView received layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0xc000000000200016> {length = 2, path = 0 - 1}'.
I looked this up in the forum and most people say you need to invalidate then reload the UIControllerView but in my case this is not working.
Anyone have idea how to fix this issue ?
Here is my code:
-(void)viewDidLoad {
self.socialMediaGrayIcons = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:#"fb-gray.png"],
[UIImage imageNamed:#"twitter-gray.png"],
[UIImage imageNamed:#"insta-gray.png"],
[UIImage imageNamed:#"sms-gray.png"],
[UIImage imageNamed:#"email-gray.png"], nil];
// setup collection view
self.avatarCollectionView.tag = 200;
self.socialMediaCollectionView.tag = 201;
UINib *cellNib = [UINib nibWithNibName:#"NibCell" bundle:nil];
[self.avatarCollectionView registerNib:cellNib forCellWithReuseIdentifier:#"cvCell"];
[self.socialMediaCollectionView registerNib:cellNib forCellWithReuseIdentifier:#"smCell"];
// setup collection view layout
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:CGSizeMake(40, 40)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.avatarCollectionView setCollectionViewLayout:flowLayout];
[self.socialMediaCollectionView setCollectionViewLayout:flowLayout];
[self.avatarCollectionView reloadData];
[self.avatarCollectionView.collectionViewLayout invalidateLayout];
[self.socialMediaCollectionView reloadData];
[self.socialMediaCollectionView.collectionViewLayout invalidateLayout];
}
....
#pragma mark UICollectionView DataSource and Delegate mathods
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if (collectionView.tag == 200)
{
return self.children.count;
} else if (collectionView.tag == 201){
return self.socialMediaGrayIcons.count;
}
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell;
if (collectionView.tag == 200)
{
static NSString *cellIdentifier = #"cvCell";
cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
Child *currentChild = [self.children objectAtIndex:indexPath.row];
UIImage *curImage = [UIImage imageWithData:currentChild.thumbnail];
UIImageView *thumbView = (UIImageView *)[cell viewWithTag:100];
if (curImage != nil)
{
[thumbView setImage:curImage];
}
} else if (collectionView.tag == 201){
static NSString *cellIdentifier = #"smCell";
cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImage *curImage = (UIImage*) [self.socialMediaGrayIcons objectAtIndex:indexPath.row];
UIImageView *thumbView = (UIImageView *)[cell viewWithTag:101];
if (curImage != nil)
{
[thumbView setImage:curImage];
}
}
return cell;
}
Taking #Paulw's good advice looks like this:
#property(weak,nonatomic) IBOutlet UICollectionView *collectionViewA;
#property(weak,nonatomic) IBOutlet UICollectionView *collectionViewB;
Your datasource methods have to be religious about always dividing in two branches of a conditional based on the collection view they were passed, and always using one datasource array in one and the other in the other.
You can enforce this religion by always getting your datasource via a convenience method, like this...
- (NSArray *)datasourceForCollectionView:(UICollectionView *)collectionView {
if (collectionView == self.collectionViewA) {
return self.children;
} else { // NOTICE - no else-if, there's no other valid condition
return self.socialMediaGrayIcons;
}
}
Use it everywhere, as in...
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self datasourceForCollectionView:collectionView].count;
}
I'm very new to UICollectionViews. I'm making a universal app. What I want is that on the iPad there are 2 cells on each row. But on the iPhone there is only one cell on each row. I was able to get the iPad version set correctly. But I can't get my head around the iPhone settings.
Here are the settings so far. And has you can see on my storyboard it looks oké. But when I run it I see that there are still two cells on each row.
Can someone help me with this ?
Kind regards
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[CVCell class] forCellWithReuseIdentifier:#"cvCell"];
// Configure layout
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:CGSizeMake(100, 100)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.collectionView setCollectionViewLayout:flowLayout];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
deviceModel = (NSString*)[UIDevice currentDevice].model;
NSLog(#"device is = %#",deviceModel);
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
if ([deviceModel isEqualToString:#"iPhone Simulator"]) {
return 1;
}else
{
return 2;
}
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 3;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Setup cell identifier
static NSString *cellIdentifier = #"cvCell";
/* Uncomment this block to use subclass-based cells */
CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
if (indexPath.section == 0) {
cell.backgroundColor = [UIColor redColor];
}
if (indexPath.section == 1) {
cell.backgroundColor = [UIColor blueColor];
}
cell.titleLabel.text = [NSString stringWithFormat:#"item %ld",(long)indexPath.section];
// Return the cell
return cell;
}
Check this code which will give you one item in iPhone cell and two item in iPad..
Im using UICollectionView for my project. But i get some issue with it: cellForItemAtIndexPath is not working when i call reloadData and scroll. This is my code:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [listImage count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView1 cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"indexpath %d", indexPath.row);
NSString *cellIdentify = #"HomeCollectionViewCell";
HomeCollectionViewCell *cell = (HomeCollectionViewCell *)[collectionView1 dequeueReusableCellWithReuseIdentifier:cellIdentify forIndexPath:indexPath];
NSMutableDictionary *dictionary = [listImage objectAtIndex:indexPath.row];
//set image pop-up for first time login
UIImageView *imageViewSignUp = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon_popupSignUp.png"]];
if (indexPath.row == 5 && ![IQUser currentUser]) {
imageViewSignUp.frame = CGRectMake(120, self.view.frame.size.height-100, 60, 63);
[self.view addSubview:imageViewSignUp];
}
//set data for product or share
[cell.contentView setUserInteractionEnabled:YES];
NSString *string = [[dictionary objectForKey:kDetail] objectForKey:kImage];
if ([string rangeOfString:#"http://"].location != NSNotFound) {
[self setImageWithString:cell.imageView aURL:string];
} else {
cell.imageView.image = [UIImage imageNamed:string];
}
return cell;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
}
-(CGSize)collectionView:(UICollectionView *)collectionView1 layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize size = collectionView.frame.size;
return size;
}
-(void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
}
it is a issue on collectionView?!
What is not working with UICollectionView ? please specify your problem.
And why are you setting image on UIView in cellForItemAtIndexPath
UIImageView *imageViewSignUp = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon_popupSignUp.png"]];
if (indexPath.row == 5 && ![IQUser currentUser]) {
imageViewSignUp.frame = CGRectMake(120, self.view.frame.size.height-100, 60, 63);
[self.view addSubview:imageViewSignUp];
}
I have a problem I can't solve for some hours now...
I have multiple UICollectionViews with different numbers of cells and different cellsizes. The CollectionViews are created programmatically and the delegates and datasources are set.
The collectionviews are created like this:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
[layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
collectionViewOne = [[UICollectionView alloc] initWithFrame:CGRectMake(0,0,320,150) collectionViewLayout:layout];
[collectionViewOne setTag:99];
[collectionViewOne setDataSource:self];
[collectionViewOne setDelegate:self];
[collectionViewOne registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cell"];
[collectionViewOne setBackgroundColor:bgColor];
[collectionViewOne setShowsHorizontalScrollIndicator:NO];
[collectionViewOne setBounces:YES];
[collectionViewOne setAlwaysBounceHorizontal:YES];
[collectionViewOne setScrollEnabled:YES];
[collectionViewOne setRestorationIdentifier:#"collectionViewOne"];
[scrollView addSubview:collectionViewOne];
My functions are like these:
- (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section {
NSLog(#"restorationIdentifier: %#", collectionView.restorationIdentifier);
if (collectionView == collectionViewOne)
{
return 3;
}
else if (collectionView == collectionViewTwo)
{
return 4;
}
else
{
return 1;
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"restorationIdentifier: %#", collectionView.restorationIdentifier);
if (collectionView == collectionViewOne)
{
return CGSizeMake(100, 150);
}
else if (collectionView == collectionViewTwo)
{
return CGSizeMake(200, 150);
}
else
{
return CGSizeMake(200, 150);
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"restorationIdentifier: %#", collectionView.restorationIdentifier);
if (collectionView == collectionViewOne)
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.image = [UIImage imageNamed:#"image.png"];
[cell addSubview:imageView];
}
else if (collectionView == collectionViewTwo)
{
//create cell of type 2
}
return cell;
}
In my log I get the following output (for example):
restorationIdentifier in numberOfItemsInSection: (null)
restorationIdentifier in sizeForItemAtIndexPath : (null)
restorationIdentifier cellForItemAtIndexPath: collectionViewOne
collectionViewOne is the restorationIdentifier on collectionViewOne. So why is it not recognized in the first two methods?
Ofcourse the result is that I get crashes because the cellsizes and number of cells in the different CollectionViews are not properly set. The error:
*** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /SourceCache/UIKit_Sim/UIKit-2903.2/UICollectionViewData.m:341
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView recieved layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0x8c31c10> {length = 2, path = 0 - 2}'
How can I fix this?
This is solved. The problem was the fact that I used the same UICollectionViewFlowLayout for both UICollectionViews. This caused the exception.
In the end I used different classes for the two controllers, this solved the problem of selecting the right CollectionView in the delegate's methods.
Thanks all for your input!
You could use the tag property of the collection view to identify which collection view is which. Like this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"restorationIdentifier: %#", collectionView.restorationIdentifier);
if (collectionView.tag == collectionViewOneTag)
{
//create cell of type 1
}
else if (collectionView.tag == collectionViewTwoTag)
{
//create cell of type 2
}
return cell;
}
Where collectionViewOneTag and collectionViewTwoTag are integers that can be defined in code or in the xib file.
Hope that helps.