I have an UICollection View i am using the peek and pop method to look into it normally it works fine but if i use peek and pop i get the error
The code for the collection view class
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 3;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
AppsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.titleLabel.text = #"TwitClient";
cell.iconimg.image = [UIImage imageNamed:#"twitclient"];
cell.appsbutton.userInteractionEnabled = NO;
cell.appsbutton.hidden = NO;
cell.appsbutton.alpha = 0.0;
cell.phoneImageView.image = [UIImage imageNamed:#"app3"];
cell.descLabel.text = #"TwitClient is an app which helps you find tweets on any subject from around the earth. You can search tweets with or without hashtags";
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(69, 126, 277, 490)];
imageView.image = [UIImage imageNamed:#"T-2"];
[cell addSubview:imageView];
return cell;
}
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0);
}
This is where 3d touch is implmented
- (UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
AppsViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"...."];
previewingContext.sourceRect = self.appsView.frame;
return appsvc;
}
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
{
[self presentViewController:viewControllerToCommit animated:YES completion:nil];
}
I dont really know what i have done wrong i have done another collection View like this but no error's
Related
I'm face a strange problem, when I execute from an action (button) the reloadData of my UICollectionView the cells are not displayed correctly, only the background image of the cells are ok.
My "INVPropertyCell" is composed with a background image and 2 labels (title & price). When I execute the reloadData the above labels from cells disappeared randomly.
I have done a lot of searches in the different forums, some people have the same problem but I didn't find out a fix.
Below, you will find my code, if someone can help me it would be very very appreciated.
Jérôme.
- (void)viewDidLoad
{
NSLog (#"INVPropertiesViewController -- viewDidLoad");
[super viewDidLoad];
// Enregistrement de la cellule.
[self.clProperties registerNib:[UINib nibWithNibName:#"INVPropertyCell" bundle:nil] forCellWithReuseIdentifier:#"propertyCell"];
// Enregistrement du header de section
[self.clProperties registerNib:[UINib nibWithNibName:#"INVPropertyHeaderSection" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"headerCollectionCell" ];
self.clProperties.delegate = self;
self.clProperties.dataSource =self;
NSLog (#"INVPropertiesViewController -- End of viewDidLoad");
}
- (void)viewWillAppear:(BOOL)animated
{
NSLog (#"INVPropertiesViewController -- viewWillAppear");
[super viewWillAppear:animated];
categoryDictionary = [ServiceDatas getCategoriesDictionary];
tblProperties = [(NSArray*)[ServiceDatas getListPropertiesByLieuFromLocalDataStore:self.selectedResidence] mutableCopy];
if(tblProperties.count==0 & self.selectedResidence.propertiesCount.longValue >0)
tblProperties = [(NSArray*)[ServiceDatas getListPropertiesByLieuFromServer:self.selectedResidence] mutableCopy];
tblPropertiesByCategory = [ServiceDatas createCategoryBreakDown:tblProperties];
keysCategories = [tblPropertiesByCategory allKeys];
[self.clProperties reloadData];
NSLog (#"INVPropertiesViewController -- End of viewWillAppear");
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
// [self.clProperties.collectionViewLayout invalidateLayout];
return tblPropertiesByCategory.count;
}
- (UICollectionReusableView *)collectionView: (UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
UICollectionReusableView *reusableview = nil;
if(kind == UICollectionElementKindSectionHeader){
INVPropertyHeaderSection *headerSection = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"headerCollectionCell" forIndexPath:indexPath];
id categoryId = [keysCategories objectAtIndex:indexPath.section];
CategoryModel *category = categoryDictionary[categoryId];
if(category!=nil){
headerSection.backgroundColor = [Utils colorFromHexString:category.color];
headerSection.lblCategory.text = [category.title uppercaseString];
}
reusableview = headerSection;
}else if(kind == UICollectionElementKindSectionFooter){
if (reusableview==nil) {
reusableview=[[UICollectionReusableView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
}
}
return reusableview;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
// Return the number of rows in the section.
id categoryId = [keysCategories objectAtIndex:section];
NSMutableArray *tblProperties = [tblPropertiesByCategory objectForKey:categoryId];
return [tblProperties count];
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
INVPropertyCell *cell = nil;
id categoryId = [keysCategories objectAtIndex:indexPath.section];
NSMutableArray *tblProperties = [tblPropertiesByCategory objectForKey:categoryId];
if(tblProperties!=nil){
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"propertyCell" forIndexPath:indexPath];
PropertyModel *property = [tblProperties objectAtIndex:indexPath.item];
NSLog(#"Ligne %ld - Colonne %ld - Lieux %#",indexPath.section, (long)indexPath.item, property.title );
CategoryModel *category = categoryDictionary[categoryId];
if(category!=nil){
[cell initWithProperty:property backgroundColor:[Utils colorFromHexString:category.color]];
}
}
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
// Récupération du bien courant.
id categoryId = [keysCategories objectAtIndex:indexPath.section];
NSMutableArray *tblProperties = [tblPropertiesByCategory objectForKey:categoryId];
PropertyModel *property = [tblProperties objectAtIndex:indexPath.row];
NSLog(#"Property sélectionnée : %#",property.title);
self.selectedProperty = property;
if(property!=nil && [property.title isEqualToString:EMPTY_PROPERTY]){
self.selectedProperty = nil;
}
// Déclenche le Segue pour aller à l'écran "Property"
[self performSegueWithIdentifier:#"segueEditPropertyView" sender:self];
}
// Layout: Set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize mElementSize = CGSizeMake(107, 106);
if(indexPath.item==0){
mElementSize = CGSizeMake(106, 106);
}
return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0.0;
}
// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0,0,0,0); // top, left, bottom, right
}
- (IBAction)btnRefresh:(id)sender {
[self.clProperties reloadData];
}
i think,you have to register class before register nib for both INVPropertyCell and INVPropertyHeaderSection cell.
You try check and alloc cell if it is null in collectionView..cellForItemAtIndexPath
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"propertyCell" forIndexPath:indexPath];
if (cell == null) {
Array *xibs = [[NSBundle mainBundle] loadNibWithNamed:#"propertycell"
...];
cell = xibs[0];
}
I'm coding in swift, so maybe above syntax is wrong, but this is idea :)
I've an array of UIColor's in my data source, what I'm trying to do is to fit all cells' size so they can all be seen on screen without scrolling.
I don't know how to do it, so far I've:
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.dataSource.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
UIColor *cellColor = (UIColor *)self.dataSource[indexPath.row];
cell.backgroundColor = cellColor;
for (UIView *view in cell.contentView.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
if ([[(UIImageView *)view image] isEqual:[UIImage imageNamed:#"V_BG.png"]]) {
[view removeFromSuperview];
}
}
}
if ([cellColor isEqual:self.existingColor]) {
UIImageView *img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"V_BG.png"]];
img.frame = CGRectMake(0, 0, 30, 30);
img.center = cell.contentView.center;
img.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:img];
}
return cell;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[[NSNotificationCenter defaultCenter] postNotificationName:UIColorDidChangeNotification
object:[NSString stringWithFormat:#"%ld", (long)indexPath.row]];
[self.navigationController popViewControllerRetro];
}
#pragma mark Collection view layout things
// Layout: Set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat fixSize = ([UIScreen mainScreen].bounds.size.width / 3) - 2;
return CGSizeMake(fixSize, fixSize);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 2;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 2;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
I am using a UICollectionView to produce a grid of cells say total of 10 i.e. 0-9.
Now, I want to insert a new cell in the grid on click of one of the cells.
so I have added the following line of code [_collectionView insertItemsAtIndexPaths:#[[NSIndexPath indexPathForItem:10 inSection:0]]]; inside the function didSelectItemAtIndexPath.
So now, if I set indexPathForItem: as 10 (i.e. insert at last) then I get 'Assertion failure' error on this line. If I set `indexPathForItem:' anything between 0-9 then I get 'EXC_BAD_ACCESS...' error on this line.
This is my complete code implementing UICollectionView:
- (void)loadView
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
_collectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 97.5, self.view.frame.size.width, self.view.frame.size.height-67.5) collectionViewLayout:layout];
[_collectionView setDataSource:self];
[_collectionView setDelegate:self];
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[_collectionView setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:_collectionView];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section
{
return 35;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
cell.layer.borderWidth=.5f;
cell.layer.borderColor=[UIColor blackColor].CGColor;
if(indexPath.item<31)
{
_dayNumber = [[UILabel alloc] initWithFrame:CGRectMake(30, 30, 15, 15)];
_dayNumber.font = [UIFont systemFontOfSize:12];
_dayNumber.text = [NSString stringWithFormat:#"%ld",(indexPath.item + 1)];
[cell addSubview:_dayNumber];
}
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout: (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.view.frame.size.width/7, self.view.frame.size.width/7);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout: (UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex: (NSInteger)section
{
return 0.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0;
}
// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout: (UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0,0,0,0); // top, left, bottom, right
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
[_collectionView insertItemsAtIndexPaths:#[[NSIndexPath indexPathForItem:0 inSection:0]]];
}
Any help?
Well,
first let's consider this method,
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section
{
return 35; // returning constant value means that you can't add or remove cells later
}
so let me change this to
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section
{
return self.itemsCount;
}
declare itemsCount property in your class interface, like this
#interface YourClass ()
#property (nonatomic) NSInteger itemsCount;
#end
initialize it in loadView or init method,
_itemsCount = 35; // or whatever you want, initial count
now we can insert/delete items, right ? when we call insertItemAtIndexPaths all we have to do is updating actual data before that call, (for example self.itemsCount++, [self.myItems addObject:newItem] )
here is changes in your code
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
self.itemsCount++; // updating data
[_collectionView insertItemsAtIndexPaths:#[[NSIndexPath indexPathForItem:0 inSection:0]]];
}
One last important thing, in cellForItemAtIndexPath don't alloc init any kind of view and add as subview on cell, this code every time creates UILabels on cell, if you want custom view on cell (like an imageview, button, etc ..) you should subclass UICollectionViewCell and create this stuff in it's init method, here is how it will look like
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
YourCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
cell.layer.borderWidth = 0.5;
cell.layer.borderColor = [UIColor blackColor].CGColor;
cell.dayNumber.font = [UIFont systemFontOfSize:12];
cell.dayNumber.text = [NSString stringWithFormat:#"%d",(indexPath.row + 1)];
return cell;
}
assuming you also changed this line,
[_collectionView registerClass:[YourCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
note that YourCell is a subclass of UICollectionViewCell and has property dayNumber
Apple has a great guide about collection views. I recommend to read it.
Good luck.
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 am trying to create a simple collection view with custom cells that have an UIImageView as a background. It's going to look something like :
This is my code :
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[MyCell class] forCellWithReuseIdentifier:#"MY_CELL"];
leftInset = rightInset = 0;
numberOfDays = 31;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 200;
}
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section
{
return numberOfDays;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
MyCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"MY_CELL" forIndexPath:indexPath];
if(indexPath.row < 10)
cell.imageView.image = [UIImage imageNamed:#"no"];
else if(indexPath.section%3==1)
{
cell.imageView.image = [UIImage imageNamed:#"ok"];
}
else if(indexPath.section%3==2)
{
cell.imageView.image = [UIImage imageNamed:#"sa"];
}
else{
cell.imageView.image = [UIImage imageNamed:#"happy_vote"];
}
return cell;
}
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(CELL_DIM, CELL_DIM);
}
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
// top left bottom right
return UIEdgeInsetsMake(5, leftInset, 0, 0);
}
MyCell.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"Init with frame!");
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)];
[self.contentView addSubview:self.imageView];
[self.imageView setBackgroundColor:[UIColor redColor]];
}
return self;
}
It works fine for around 10 sections in the collection view. The problem is when I want to add more sections, the vertical scrolling starts to move really slow. I noticed that all the cells are allocated all at once. I am searching for a way to make this more resource friendly, and have the scrolling move continuously rather than slow and laggish. Could you tell me how to take care of the resources allocation to avoid this problem ? Thank you.
PS : I've tried removing the image view from the cell background and in the method cellForItemAtIndexPath: set a background color for the cell but again, after 10 or more sections it moves really slow.
What you might want to do to help performance time is to check if an object is already initiated. You could also separately instantiate your images so that it doesnt have to be read from memory every time:
Make image1 a property of the view controller:
- (void)viewDidLoad
{
image1 = [UIImage imageNamed:#"image1"];
image2 = [UIImage imageNamed:#"image2"];
image3 = [UIImage imageNamed:#"image3"];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
MyCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"MY_CELL" forIndexPath:indexPath];
if(indexPath.row < 10)
cell.imageView.image = [UIImage imageNamed:#"no"];
else if(indexPath.section%3==1)
{
cell.imageView.image = image1;
}
else if(indexPath.section%3==2)
{
cell.imageView.image = image2;
}
else{
cell.imageView.image = image3;
}
return cell;
}