I have a UICollectionView that instantiates a bunch of images in a Flow Layout. The problem I have is when I scroll to the bottom of the view the app crashes and gives the following error: "*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[StickerPickerViewCell setImage:]: unrecognized selector sent to instance 0x101bdf470'". This seems odd to me because I don't know why it would be trying to add more images when you are at the bottom. Here is the code I have:
#import <UIKit/UIKit.h>
#interface StickerPickerViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *testText;
#property (weak, nonatomic) IBOutlet UIImageView *stickerImage;
//- (void)setStickerImage:(StickerImage *)sticker;
#end
#import <Foundation/Foundation.h>
#import "StickerPickerViewCell.h"
#implementation StickerPickerViewCell
/*
- (void)setStickerImage:(StickerImage *)sticker{
{
self.stickerImage.image = [UIImage imageNamed:sticker.stickerImage];
}
*/
#end
#import <UIKit/UIKit.h>
#import "PhotoEditViewController.h"
#interface StickerPickerViewController : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
//method declarations
- (void)viewDidLoad;
#property (weak, nonatomic) id<StickerPickerDelegate> pickerDelegate;
#property (weak, nonatomic) IBOutlet UICollectionView *stickerView;// sticker picker collection view
#property (nonatomic, strong) IBOutlet UICollectionViewFlowLayout *flowLayout;
#end
#import <Foundation/Foundation.h>
#import "StickerPickerViewController.h"
#import "StickerPickerViewCell.h"
#implementation StickerPickerViewController
//holds all the locations to the stickers we want to appear
- (void)viewDidLoad {
[super viewDidLoad];
[self.stickerView setBackgroundColor:[UIColor whiteColor]];
//flowlayout is how the cells organize around one another in the collectionview
self.flowLayout = [[UICollectionViewFlowLayout alloc] init];
[self.flowLayout setItemSize:CGSizeMake(40, 40)];
[self.flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
self.flowLayout.minimumInteritemSpacing = 0.0f;
[self.stickerView setCollectionViewLayout:self.flowLayout];
self.stickerView.bounces = YES;
[self.stickerView setShowsHorizontalScrollIndicator:NO];
[self.stickerView setShowsVerticalScrollIndicator:YES];
}
-(void)viewDidAppear:(BOOL)animated{
}
//////////////////////////////////////////////////COLLECTION VIEW METHODS ///////////////////////////////////////////////////////////////////
//number of cells to produce
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
//return list of sticker's size
//printf("i: %lu", (unsigned long)[stickerList count]);
StickerManager* stickerManager = [self.pickerDelegate stickerManagerForStickers];
return stickerManager.stickers.count;
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
StickerManager* stickerManager = [self.pickerDelegate stickerManagerForStickers];
Sticker* sticker = stickerManager.stickers[indexPath.row];
//create cell
StickerPickerViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"stickerPickerViewCell" forIndexPath:indexPath];
//set cell image to image associated with the path in the array
cell.stickerImage.image = sticker.preview;
cell.stickerImage = (UIImageView *)[cell viewWithTag:100];
return cell;
}
//cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(75, 75);
}
//number of cell sections
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
//get the selected image as String
Sticker* selectedSticker = [self.pickerDelegate stickerManagerForStickers].stickers[indexPath.row];
[self dismissViewControllerAnimated:YES completion:nil];
[self.pickerDelegate didSelectSticker:selectedSticker];
//dismiss popover
[self dismissViewControllerAnimated:true completion:nil];
}
#end
What could be causing this crash?
Related
I am trying to show images on collectionView. I have trouble showing this images as I have created a reusable cell with imageView inside.Those images have to be equally spaced between as I want to show 3 icons on screen at once. I am using 13 icons and it has to be scrollable horizontally through screen.
I am not able to show image in cell and I do not know how to set image cells with spacing between them using just one reusable cell
CustomCollectionViewCell.h
#interface CustomCollectionViewCell : UICollectionViewCell
#property (nonatomic, retain) UIImageView *imageView;
#end
CustomCollectionViewCell.m
#implementation CustomCollectionViewCell
- (UIImageView *) imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
[self.contentView addSubview:_imageView];
}
return _imageView;
}
- (void)prepareForReuse {
[super prepareForReuse];
[self.imageView removeFromSuperview];
self.imageView = nil;
}
#end
LandingViewController.m
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
CustomCollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"CustomCell" forIndexPath:indexPath];
return cell;
}
Now OP wants horizontal scrollable direction of Collection view.So Again I created small sample project for this.I put 13 images in horizontal scroll direction.It scrolls successfully on horizontal direction of collection view.
Why I post the horizontal scrollable collectionView here is everyone can understand the answer and get the solution easily.I added extra image I mean exactly 13 images(op wants 13 images into collection view). This answer definitely helps you.
HorizontalScrollableCollectionView
Here I set the scrollDirection as Horizontal in CustomImageFlowLayout.m file
CustomImageFlowLayout.h
#import <UIKit/UIKit.h>
#interface CustomImageFlowLayout : UICollectionViewFlowLayout
#end
CustomImageFlowLayout.m
#import "CustomImageFlowLayout.h"
#implementation CustomImageFlowLayout
- (instancetype)init
{
self = [super init];
if (self)
{
self.minimumLineSpacing = 1.0f;
self.minimumInteritemSpacing = 1.0f;
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
}
return self;
}
- (CGSize)itemSize
{
NSInteger numberOfColumns;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
numberOfColumns = 3;
else{
if([UIApplication sharedApplication].statusBarOrientation==UIInterfaceOrientationPortrait)
numberOfColumns = 4;
else if([UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeRight || [UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeLeft)
numberOfColumns = 4;
}
NSLog(#"The collection view frame is - %#",NSStringFromCGRect(self.collectionView.frame));
CGFloat itemWidth = (CGRectGetWidth(self.collectionView.frame) - (numberOfColumns - 1)) / numberOfColumns;
NSLog(#"The item width is - %f",itemWidth);
return CGSizeMake(itemWidth, itemWidth);
}
#end
Then CustomCell of UICollectionViewCell
CustomCell.xib
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *img;
#property (strong, nonatomic) IBOutlet UILabel *lblCollection;
#end
CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
#end
Now Storyboard design starts
My collection view name is here collectionviewVerticalHorizontalFlowLayout
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource>
#property (strong, nonatomic) IBOutlet UICollectionView *collectionviewVerticalHorizontalFlowLayout;
#end
ViewController.m
#import "ViewController.h"
#import "CustomCell.h"
#import "CustomImageFlowLayout.h"
#interface ViewController (){
NSMutableArray *arrayImages;
NSMutableArray *arrayTitles;
CustomCell *cell;
}
#end
#implementation ViewController
#synthesize collectionviewVerticalHorizontalFlowLayout;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
collectionviewVerticalHorizontalFlowLayout.collectionViewLayout = [[CustomImageFlowLayout alloc] init];
collectionviewVerticalHorizontalFlowLayout.backgroundColor = [UIColor clearColor];
arrayImages = [[NSMutableArray alloc]initWithObjects:#"iPhone.png", #"android.png", #"windows.png", #"blackberry.png", #"lenovovibek5note.png", #"redmi.png", #"moto.png", #"sony.png", #"samsung.png", #"oneplus.png",#"redminote4.png",#"oppo.png",#"vivo.png",nil];
arrayTitles = [[NSMutableArray alloc]initWithObjects:#"iPhone", #"Android", #"Windows", #"Blackberry", #"LenovaVikeK5Note", #"Redmi", #"MotoG", #"Sony", #"Samsung", #"OnePlus", #"RedMiNote4",#"Oppo",#"Vivo",nil];
UINib *cellNib = [UINib nibWithNibName:#"CustomCell" bundle:nil];
[collectionviewVerticalHorizontalFlowLayout registerNib:cellNib forCellWithReuseIdentifier:#"cell"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//UICollectionView Data Source Methods
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return arrayImages.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cell";
cell = (CustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
if(cell==nil){
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = nib[0];
}
cell.img.image = [UIImage imageNamed:(NSString*)[arrayImages objectAtIndex:indexPath.row]];
NSLog(#"The collection view label text is - %#",[NSString stringWithFormat:#"%#",arrayTitles[indexPath.row]]);
cell.lblCollection.text = arrayTitles[indexPath.row];
cell.lblCollection.textColor = [UIColor blackColor];
return cell;
}
//UICollectionView Delegate Method
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"the clicked indexPath.row is - %ld",(long)indexPath.row);
}
#end
Final out put screen shots
First it shows
Then If I scroll horizontally in the collection view it shows
I will give you what you ask.
I wanted to same thing in one application.I successfully implemented this.Just now I tried the sample project for your question.I got what you ask exactly.I show you the code and everything below.
First CustomImageFlowLayout of NSObject Class
CustomImageFlowLayout.h
#import <UIKit/UIKit.h>
#interface CustomImageFlowLayout : UICollectionViewFlowLayout
#end
CustomImageFlowLayout.m
#import "CustomImageFlowLayout.h"
#implementation CustomImageFlowLayout
- (instancetype)init
{
self = [super init];
if (self)
{
self.minimumLineSpacing = 1.0f;
self.minimumInteritemSpacing = 1.0f;
self.scrollDirection = UICollectionViewScrollDirectionVertical;
}
return self;
}
- (CGSize)itemSize
{
NSInteger numberOfColumns;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
numberOfColumns = 3;
else{
if([UIApplication sharedApplication].statusBarOrientation==UIInterfaceOrientationPortrait)
numberOfColumns = 4;
else if([UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeRight || [UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeLeft)
numberOfColumns = 4;
}
NSLog(#"The collection view frame is - %#",NSStringFromCGRect(self.collectionView.frame));
CGFloat itemWidth = (CGRectGetWidth(self.collectionView.frame) - (numberOfColumns - 1)) / numberOfColumns;
NSLog(#"The item width is - %f",itemWidth);
return CGSizeMake(itemWidth, itemWidth);
}
#end
After that I created Custom Cell for Images
See my Design first
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *img;
#property (strong, nonatomic) IBOutlet UILabel *lblCollection;
#end
CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
#end
Then I use above class in my ViewController
Below is my Storyboard Design
Here my CollectionView name is collectionViewVertical
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
#property (strong, nonatomic) IBOutlet UICollectionView *collectionViewVertical;
#end
ViewController.m
#import "ViewController.h"
#import "CustomCell.h"
#import "CustomImageFlowLayout.h"
#interface ViewController ()
{
NSMutableArray *arrayImages;
NSMutableArray *arrayTitles;
CustomCell *cell;
}
#end
#implementation ViewController
#synthesize collectionViewVertical;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
collectionViewVertical.collectionViewLayout = [[CustomImageFlowLayout alloc] init];
collectionViewVertical.backgroundColor = [UIColor clearColor];
arrayImages = [[NSMutableArray alloc]initWithObjects:#"iPhone", #"Android", #"Windows", #"Blackberry", #"Lenova", #"Redmi", #"MotoG", #"Sony", #"Samsung", #"OnePlus", nil];
arrayTitles = [[NSMutableArray alloc]initWithObjects:#"iPhone.png", #"android.png", #"windows.png", #"blackberry.png", #"lenovo.png", #"redmi.png", #"moto.png", #"sony.png", #"samsung.png", #"oneplus.png", nil];
UINib *cellNib = [UINib nibWithNibName:#"CustomCell" bundle:nil];
[collectionViewVertical registerNib:cellNib forCellWithReuseIdentifier:#"cell"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//UICollectionView Data Source Methods
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return arrayImages.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cell";
cell = (CustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
if(cell==nil){
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = nib[0];
}
cell.img.image = [UIImage imageNamed:(NSString*)[arrayImages objectAtIndex:indexPath.row]];
cell.lblCollection.text = arrayTitles[indexPath.row];
return cell;
}
//UICollectionView Delegate Method
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"the clicked indexPath.row is - %ld",(long)indexPath.row);
}
Finally the output screen
Hi there i currently have just "think i have cracked sending content through a prepare for segue" but the problem is that my images are not showing up in the second view controller. As I'm kind of new to this i would like to know if there is something that i am missing because no matter what i can't seem to get the image of my first view controller to show in my second view controller.
GroupsViewController.h
#import <UIKit/UIKit.h>
#interface GroupsViewController : UIViewController<UICollectionViewDataSource, UICollectionViewDelegate>
#property (weak, nonatomic) IBOutlet UICollectionView *GroupsCollectionView;
- (IBAction)cellToggleAction:(id)sender;
#end
GroupsViewController.m
#import "GroupsViewController.h"
#import "GroupsHomeViewController.h"
#import "CustomCell.h"
#interface GroupsViewController ()
{
NSArray *arrayOfImages;
NSArray *arrayOfDescriptions;
}
#end
#implementation GroupsViewController
{
NSString *reuseIdentifier;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[self GroupsCollectionView]setDataSource:self];
[[self GroupsCollectionView]setDelegate:self];
reuseIdentifier= #"SmallIcon"; //set inital value of reuse identifier
arrayOfImages = [[NSArray alloc]initWithObjects:#"a.png", nil];
arrayOfDescriptions = [[NSArray alloc]initWithObjects:#"A", nil];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [arrayOfDescriptions count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[[cell IconImage]setImage:[UIImage imageNamed:[arrayOfImages objectAtIndex:indexPath.item]]];
[[cell IconLabel]setText:[arrayOfDescriptions objectAtIndex:indexPath.item]];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"GroupsHomeSegue" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"GroupsHomeSegue"])
{
NSIndexPath* indexPath = [[self.GroupsCollectionView indexPathsForSelectedItems]firstObject];
if(indexPath !=nil)
{
//NSString *selectedDescription = arrayOfDescriptions[indexPath.item]; //collects description from cell
NSString *selectedImage = arrayOfImages [indexPath.item]; //collects image from cell
GroupsHomeViewController *groupsHomeViewController = segue.destinationViewController;
groupsHomeViewController.logoImage = [UIImage imageNamed: selectedImage];
//groupsHomeViewController.groupLabel = [:selectedDescription];
}
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//Dispose of any resources that can be recreated.
}
#end
GroupsHomeViewController.h
#import <UIKit/UIKit.h>
#interface GroupsHomeViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UIImage *logoImage;
#property (strong, nonatomic) IBOutlet UILabel *groupLabel;
#end
GroupsHomeViewController.m
#import "GroupsHomeViewController.h"
#interface GroupsHomeViewController ()
#end
#implementation GroupsHomeViewController
-(void)viewDidLoad{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Thank You in advance for your kind help.
Lee Sugden,
Passing an image is not enough :) If you want it to show on your screen you should load it in an ImageView isn't it :)
Now either create UIImageView programmatically or add a imageView in your story board draw an IBOutlet and set the image as
self.yourImageView.image = self.logoImage;
else create an UIImageView programmatically as,
UIImageView *yourImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,self.logoImage.size.width,self.logoImage.size.height)];
yourImageView.image = self.logoImage;
[self.view addSubview:yourImageView];
The issue lies in your GroupsHomeViewController. You need a UIImageView as your IBOutlet rather than a UIImage, then you need to set the image property on the image view to your desired image. To do this, you need to update your GroupsHomeViewController.h file like so:
#interface GroupsHomeViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *logoImageView;
#property (strong, nonatomic) UIImage *logoImage;
#property (strong, nonatomic) IBOutlet UILabel *groupLabel;
#end
And then in your GroupsHomeViewController.m, set your image view's image in the viewWillAppear:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.logoImageView.image = self.logoImage;
}
Now, when you set logoImage in your segue, the image view will load the image just before the view appears.
This is assuming that you have the image view already on your storyboard with the outlet correctly connected.
I think the guys above may have solved this with the advice to set the image to whatever image view is holding it. But if that still hasn't solved it, with prepareForSegue, I've had problems due to iOS voodoo where the variable isn't set. So to be sure, override the setter in your GroupsHomeViewController.m to make sure the object is properly assigned to your image property.
- (void)setLogoImage:(UIImage *)logoImage
{
_logoImage = logoImage;
}
Hi there i have a slight problem with my UICollectionView. i don't currently have any settings set for spacing yet i seem to have a huge gap between my cells of which is very annoying if would be helpful if someone could tell me how to resolve this? id assume its something very simple.
Below is an example of whats happening to my CollectionViewCells:
Custom cell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *IconImage;
#property (weak, nonatomic) IBOutlet UILabel *IconLabel;
#property (weak, nonatomic) IBOutlet UILabel *IconDescription;
#end
groupsviewcontroller.m
#import "GroupsViewController.h"
#import "CustomCell.h"
#interface GroupsViewController ()
{
NSArray *arrayOfImages;
NSArray *arrayOfDescriptions;
}
#end
#implementation GroupsViewController
{
NSString *reuseIdentifier;
}
- (void)viewDidLoad
{
[super viewDidLoad];
reuseIdentifier= #"SmallIcon";
[[self GroupsCollectionView]setDataSource:self];
[[self GroupsCollectionView]setDelegate:self];
arrayOfImages = [[NSArray alloc]initWithObjects:#"sin.png", nil];
arrayOfDescriptions = [[NSArray alloc]initWithObjects:#"Sin", nil];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [arrayOfDescriptions count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[[cell IconImage]setImage:[UIImage imageNamed:[arrayOfImages objectAtIndex:indexPath.item]]];
[[cell IconLabel]setText:[arrayOfDescriptions objectAtIndex:indexPath.item]];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//Dispose of any resources that can be recreated.
}
- (IBAction)cellToggleAction:(id)sender {
//need to add toggle button to toggle between three different views
//small icon
//list view
//large icon
}
#end
1) You should check your CustomCell class, see if any size constraint is applied. Simply set your cell's background as some color and the actual cell size will be highlighted.
2) Use (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath to help yourself set the proper cell size. This func comes with UICollectionViewDelegateFlowLayout :)
I have a custom UITableViewCell in a UITableViewController, but when the Controller tries to dequeue the custom cell, it will take a long time (like 2000ms).
This line of code causes the problem
KidsListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"kidsReuseIdentifier" forIndexPath:indexPath];
The KidsListTableViewCell is a custom cell, which includes couple of UIButtons, some UILabels to show the information. And two delegate methods. It shouldn't be that slow to render that view. By the way, all of the information in the custom cell is basically static.
The is the full code of the UITableViewController. I put the custom view and regular view in different sections and I don't think this causes the problem.
#import "KidDetailTableViewController.h"
#import "KidDetailHeaderTableViewCell.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import "Helper.h"
#interface KidDetailTableViewController () <KidDetailHeaderCellDelegate>
#end
#implementation KidDetailTableViewController
{
KidDetailHeaderTableViewCell *headerCell;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"KidDetailHeader" bundle:nil] forCellReuseIdentifier:#"kidDetail"];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"detailCell"];
self.tableView.showsVerticalScrollIndicator = NO;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch (section) {
case 0:
return 1;
break;
default:
return 10;
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
if (!headerCell) {
headerCell = [tableView dequeueReusableCellWithIdentifier:#"kidDetail"];
headerCell.delegate = self;
// Keep the background color for the cell when select.
headerCell.selectionStyle = UITableViewCellSelectionStyleNone;
headerCell.nicknameLabel.text = _kidNeedsToShow.nickname;
NSString *kidFullName = [NSString stringWithFormat:#"%# %# %#", _kidNeedsToShow.firstName, _kidNeedsToShow.midName, _kidNeedsToShow.lastName];
kidFullName ? (headerCell.fullNameLabel.text = #"") : (headerCell.fullNameLabel.text = kidFullName);
// Set thumb image or use default
// if there isn't image, use default.
ALAssetsLibrary *library = [ALAssetsLibrary new];
[library assetForURL:_kidNeedsToShow.photoURL resultBlock:^(ALAsset *asset) {
[headerCell.avatarImage setImage:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]]];
} failureBlock:nil];
return headerCell;
}
else return headerCell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"detailCell" forIndexPath:indexPath];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return 290;
}
else return 60;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return 290;
}
else return 60;
}
- (void)didClickLeftButton:(UIButton *)leftButton {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
I tried to put dequeueReusableCellWithIdentifier into a different thread, apparently it wouldn't work.
UPDATE: KidDetailHeaderTableViewCell.m
- (void)awakeFromNib {
// Initialization code
[_avatarImage.layer setCornerRadius:_avatarImage.frame.size.width / 2];
[_avatarImage.layer setBorderColor:[UIColor whiteColor].CGColor];
[_avatarImage.layer setBorderWidth:1.0];
[_avatarImage setClipsToBounds:YES];
}
- (IBAction)leftButtonClicked:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:#selector(didClickLeftButton:)]) {
[self.delegate didClickLeftButton:sender];
}
}
- (IBAction)rightButtonClicked:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:#selector(didClickRightButton:)]) {
[self.delegate didClickRightButton:sender];
}
}
KidDetailHeaderTableViewCell.h
#protocol KidDetailHeaderCellDelegate <NSObject>
#optional
- (void)didClickLeftButton:(UIButton *)leftButton;
- (void)didClickRightButton:(UIButton *)rightButton;
#end
#interface KidDetailHeaderTableViewCell : UITableViewCell
#property (weak) id<KidDetailHeaderCellDelegate> delegate;
#property (weak, nonatomic) IBOutlet UILabel *fullNameLabel;
#property (weak, nonatomic) IBOutlet UIImageView *avatarImage;
#property (weak, nonatomic) IBOutlet UILabel *nicknameLabel;
#property (weak, nonatomic) IBOutlet UILabel *ageText;
#property (weak, nonatomic) IBOutlet UILabel *ageLabel;
#property (weak, nonatomic) IBOutlet UILabel *momentsStatistics;
#property (weak, nonatomic) IBOutlet UILabel *momentsLabel;
#property (weak, nonatomic) IBOutlet UIButton *rightButton;
#property (weak, nonatomic) IBOutlet UIButton *leftButton;
#end
UPDATE 2:
screenshot of instrument
The code for set the height of the cell. I have two sections, the first section actually is only used for header, the height is 290.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return 290;
}
else return 60;
}
One of my friend pointed out that problem was caused by the custom font (Yes! I used custom font in the custom view). I still not sure about why this causes the problem (the font named 'hero'), but hope this will help someone else.
I have a UICollectionView and I simply want it to show up. I have the delegate and datasource attached to the file's owner in the interface builder.
collectionView:numberOfItemsInSection:
Gets called just fine.
I have been messing with this for a few hours and just can't figure it out...
Any help would be great, Thanks in advance!
Here is the full source. Sorry if its kinda messy.
.h File
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "PinAnnotation.h"
#import "Jot.h"
#interface JotCardViewController : UIViewController <MKMapViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property (nonatomic,strong) Jot* jot;
#end
.m file
#import "JotCardViewController.h"
#import "JotViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface JotCardViewController ()
#property (nonatomic,strong) JotViewController *detailViewController;
#property (nonatomic,strong) IBOutlet UIView *cardFrontView;
#property (nonatomic,assign,getter = isFlipped) BOOL flipped;
#property (nonatomic,weak) IBOutlet MKMapView *mapView;
#property (nonatomic,strong) IBOutlet UICollectionView *collectionView;
#property (nonatomic,weak) IBOutlet UILabel *jotTitle;
#property (nonatomic,weak) IBOutlet UILabel *jotDate;
#property (nonatomic,weak) IBOutlet UILabel *sunriseSunsetDelta;
#property (nonatomic,weak) IBOutlet UILabel *jotNotes;
#end
#implementation JotCardViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[[self mapView] setRegion:MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake([self.jot.latitude floatValue], [self.jot.longitude floatValue]), 1000, 1000)];
//TODO: if there is no jot location - say that their isn't (maybe text over the map display)
CLLocation *tempLocation = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake([self.jot.latitude doubleValue], [self.jot.longitude doubleValue]) altitude:0 horizontalAccuracy:0 verticalAccuracy:0 timestamp:nil];
[self dropPin:tempLocation];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"Cell"];
[self.collectionView reloadData];
}
- (void) viewWillAppear:(BOOL)animated
{
[self refreshUIFromJot];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)flipToDetails:(id)sender
{
if (![self isFlipped]) {
if (!self.detailViewController) {
JotViewController *jotViewController = [[JotViewController alloc] initWithNibName:#"JotView" bundle:[NSBundle mainBundle]];
jotViewController.jot = self.jot;
self.detailViewController = jotViewController;
self.detailViewController.view.frame = self.cardFrontView.frame;
self.detailViewController.view.layer.cornerRadius = 10.0;
}
[UIView transitionFromView:self.cardFrontView toView:self.detailViewController.view duration:0.33 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) {
[self setFlipped:YES];
}];
} else {
[UIView transitionFromView:self.detailViewController.view toView:self.cardFrontView duration:0.33 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
[self setFlipped:NO];
}];
}
}
- (void) setJot:(Jot *) jot {
_jot = jot;
[self refreshUIFromJot];
}
- (void) refreshUIFromJot
{
[[self jotTitle] setText:self.jot.summary];
[[self jotDate] setText:self.jot.recorddate];
[[self jotNotes] setText:self.jot.note];
[[self sunriseSunsetDelta] setText:#""];
}
-(void) dropPin: (CLLocation*)newLocation{
for (id<MKAnnotation> pin in self.mapView.annotations){
MKAnnotationView* anView = [self.mapView viewForAnnotation: pin];
if (anView){
[self.mapView removeAnnotation:pin];
NSLog(#"Pin removed");
}
}
PinAnnotation *pin = [[PinAnnotation alloc] initWithCoordinates:newLocation.coordinate placeName:nil description:nil];
[self.mapView addAnnotation:pin];
}
#pragma mark - MKMapViewDelegate methods
- (void) mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
NSLog(#"Map!");
}
#pragma mark - UICollectionView DataSource
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section
{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
//cell.backgroundColor = [UIColor colorWithPatternImage:[self.results objectAtIndex:indexPath.row]];
return cell;
//###
/*
NSSet *jotImages = self.jot.images;
NSSortDescriptor *imageNameDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"imageName" ascending:YES];
NSArray *sortedJotImages = [jotImages sortedArrayUsingDescriptors:#[imageNameDescriptor]];
*/
//###
}
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// TODO: Select Item
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
// TODO: Deselect item
}
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize retval = CGSizeMake(100, 100);
return retval;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(50, 20, 50, 20);
}
#end
I was having a similar problem. cellForItemAtIndexPath was not being called. After pulling out my hair for several minutes, I removed the collectionView registerClass:forCellWithReuseIdentifier from the viewDidLoad method.
After doing that, cellForItemAtIndexPath began to get called.
I hope this helps.
I had a similar problem and here was my solution:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
was not being called was because of the itemSize for the collectionViewFlowLayout's height was too big.
[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
If I change the height to 410, it will execute cellForItemAtIndexPath.
I found I was had a wrong setup custom flow layout class causing me issues. Reverted to Flow layout and it worked fine.