UICollectionview is not working, I am not getting any Cell - ios

I am trying to use a collection view and reuse a collection view cell and I have to get 23 images and name from server which I have not started coz of the problem I am facing
This is my custom cell file collection view file objective c
Below is my custom cell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UICollectionViewCell
{
UIImageView *imageView;
}
#property (nonatomic, retain) UIImageView *imageView; //this imageview is the only thing we need right now.
#end
Here is my custom cell.m file
#import "CustomCell.h"
#implementation CustomCell
#synthesize imageView;
- (id)initWithFrame:(CGRect)aRect
{
if (self = [super initWithFrame:aRect])
{
//we create the UIImageView in this overwritten init so that we always have it at hand.
imageView = [[UIImageView alloc] init];
//set specs and special wants for the imageView here.
[self addSubview:imageView]; //the only place we want to do this addSubview: is here!
//You wanted the imageView to react to touches and gestures. We can do that here too.
UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onButtonTapped:)];
[tap setNumberOfTapsRequired:1];
[self addGestureRecognizer:tap];
//We can also prepare views with additional contents here!
//just add more labels/views/whatever you want.
}
return self;
}
-(void)onButtonTapped:(id)sender
{
//the response to the gesture.
//mind that this is done in the cell. If you don't want things to happen from this cell.
//then you can still activate this the way you did in your question.
}
#end
These are the methods in my normal view controller.m file
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cvCell" forIndexPath:indexPath];
[[[cell contentView] subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
// create a uiview where we can place all views that need to go into this cell
UIView * contents=[[UIView alloc] initWithFrame:cell.contentView.bounds];
[contents setBackgroundColor:[UIColor clearColor]];
[cell.contentView addSubview:contents];
// set tag to the indexPath.row so we can access it later
[cell setTag:indexPath.row];
// add interactivity
UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onButtonTapped:)];
[tap setNumberOfTapsRequired:1];
[cell addGestureRecognizer:tap];
if (cell.selected) {
cell.backgroundColor = [UIColor blueColor]; // highlight selection
}
else
{
cell.backgroundColor = [UIColor redColor]; // Default color
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor redColor]; // Default color
}
I don't get any cell when I moved to this view, it is just blank with the background image and I have even given a blank picture to see how the view is but I don't get anything please help!!!

The cells are not displaying because you might not have set the datasource and delegate properly.
Since you have added the cells in storyboard you don't need to add the imageview as subview in the collection view cell.
First connect the outlet of imageview that you have added in storyboard to the CustomCell. Then remove
{
UIImageView *imageView;
}
#property (nonatomic, retain) UIImageView *imageView;
You can remove - (id)initWithFrame:(CGRect)aRect this method and you can add the tap gesture initialization in awakeFromNib method
-(void)awakeFromNib {
UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onButtonTapped:)];
[tap setNumberOfTapsRequired:1];
[self addGestureRecognizer:tap];
}
No need to do
imageView = [[UIImageView alloc] init];
[self addSubview:imageView];
Again in cellForItemAtIndexPath
remove the following lines
[[[cell contentView] subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
UIView * contents=[[UIView alloc] initWithFrame:cell.contentView.bounds];
[contents setBackgroundColor:[UIColor clearColor]];
[cell.contentView addSubview:contents];
After making these changes please try again

Related

How to fix UICollectionViewCell with UIImageView Overlap Programmatically

I'm create UICollectionView programmatically to uiview (i use single view). like this
UICollectionViewFlowLayout *CATLayout=[[UICollectionViewFlowLayout alloc]init];
CATLayout.minimumInteritemSpacing = 2.0f;
CATLayout.minimumLineSpacing = 2.0f;
CATLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
CATLayout.sectionInset = UIEdgeInsetsMake(1.0f, 1.0f, 1.0f, 1.0f);
self.ColStickersListView=[[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, StickersListView.frame.size.width, StickersListView.frame.size.height) collectionViewLayout:CATLayout];
self.ColStickersListView.delegate=self;
self.ColStickersListView.dataSource=self;
self.ColStickersListView.tag=2;
[self.ColStickersListView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"CollStickersList"];
[self.ColStickersListView setBackgroundColor:[UIColor clearColor]];
[StickersListView addSubview:ColStickersListView];
and
UICollectionViewCell *cell = [ColStickersListView dequeueReusableCellWithReuseIdentifier:#"CollStickersList" forIndexPath:indexPath];
// for background selected
NSString *imageName=anObject;
NSString *filename=[NSString stringWithFormat:#"%#/Stickers/List/%#",[appDel DocsPath],imageName];
NSLog(#"%#",filename);
cell.backgroundColor=[UIColor clearColor];
UIImage *image=[UIImage imageNamed:filename];
UIImageView *photoView=[[UIImageView alloc]initWithFrame:CGRectMake(StickersListPadding,StickersListPadding,StickersListThumbSize-(StickersListPadding*2),StickersListThumbSize-(StickersListPadding*2))];
photoView.image=image;
photoView.contentMode=UIViewContentModeScaleAspectFit;
photoView.userInteractionEnabled = YES;
[cell.contentView addSubview:photoView];
return cell;
it's work perfect for display image to cell.
Problem !!
if scroll page to bottom and scroll return to top again that image in cell it's overlap.
How to fix it.!!! (Programmatically only with single view)
I suspect because you aren't setting the frame on the UIImageView it is deriving its size from the image that is being set on it. So in some cases it might overflow its parent view -> the cell in this case.
I suggest you setup some constraints on the UIImageView, this can be done programmatically.
So try to set left, right, top and bottom constraints on the UIIMageView so that it stays within the bounds of the cell
During scroll
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath is beeing called repeatively..
the means your are adding UIImageView *photoView repeatedly to cell.contentView
UIImageView *photoView=[[UIImageView alloc]initWithFrame:CGRectMake(StickersListPadding,StickersListPadding,StickersListThumbSize-(StickersListPadding*2),StickersListThumbSize-(StickersListPadding*2))];
//codes..
[cell.contentView addSubview:photoView];
doing something like this prevent that:
UICollectionViewCell *cell = [ColStickersListView dequeueReusableCellWithReuseIdentifier:#"CollStickersList" forIndexPath:indexPath];
if (cell == nil)
{
UIImageView *photoView=[[UIImageView alloc]initWithFrame:CGRectMake(StickersListPadding,StickersListPadding,StickersListThumbSize-(StickersListPadding*2),StickersListThumbSize-(StickersListPadding*2))];
// codes...
[cell.contentView addSubview:photoView];
}
Another way of solving this is by creating a custom collection cell:
// CustomCollectionCell.h
#interface YourCollectionCell : UICollectionViewCell
#property (nonatomic) UIImageView *photoView;
#end
// CustomCollectionCell.m
#implementation YourCollectionCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// and setting up you imageview here
self.photoView=[[UIImageView alloc]initWithFrame:YourRect];
self.photoView.contentMode=UIViewContentModeScaleAspectFit;
self.photoView.userInteractionEnabled = YES;
[self.contentView addSubview:self.photoView];
}
return self;
}
and using it like:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCollectionCell *cell = (CustomCollectionCell *)[ColStickersListView dequeueReusableCellWithReuseIdentifier:#"CollStickersList" forIndexPath:indexPath];
cell.photoView.image=image;
return cell;
}
Hope i've helped you, happy coding.. Cheers & Good night!

Why isn't content showing up in one of the two UICollectionView's in my app that are sharing the same custom UICollectionViewCell?

I have a 2 UICollectionView's.
One is dedicated to a grid style display and the other to a single file display. This is controlled by a UISegmentedControl.
The grid style collection view was created in interface builder:
The other collection view was created programmatically within the viewDidLoad method of the custom class of my default grid style collection views controller.
- (void)viewDidLoad
{
[super viewDidLoad];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
[layout setItemSize:CGSizeMake(140, 272)];
[layout setMinimumLineSpacing:1];
[layout setMinimumInteritemSpacing:1];
[layout setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[layout setScrollDirection:UICollectionViewScrollDirectionVertical];
_collectionView2 = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
[_collectionView2 setDelegate:self];
[_collectionView2 setDataSource:self];
[_collectionView2 registerClass:[VAGGarmentCell class] forCellWithReuseIdentifier:#"Cell2"];
[_collectionView2 setBackgroundColor:[UIColor redColor]];
[self.view addSubview:_collectionView2];
[_collectionView2 setHidden:YES];
}
I'm using the same custom cell with both these collection views.
Here are my dataSource and delegate methods which both collection views use.
1:
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if ([collectionView isEqual:_collectionView]) {
NSArray *people = [_thisController objects];
return [people count];
} else if ([collectionView isEqual:_collectionView2]) {
NSArray *people = [_thisController objects];
return [people count];
}
return 0;
}
2:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
if ([collectionView isEqual:_collectionView2]) {
NSLog(#"collectionview 2 loaded");
static NSString *CellIdentifier = #"Cell2";
VAGGarmentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
PFFile *userImageFile = [object valueForKey:#"image"];
[[cell imageView] setFile: userImageFile];
[[cell imageView] loadInBackground];
[[cell title] setText:[object valueForKey:#"title"]];
[[cell price] setText:[NSString stringWithFormat: #"£%# GBP", [object valueForKey:#"price"]]];
return cell;
} else if ([collectionView isEqual:_collectionView]) {
NSLog(#"collectionview 1 loaded");
static NSString *CellIdentifier = #"Cell";
VAGGarmentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: CellIdentifier forIndexPath:indexPath];
[[cell activityIndicator] startAnimating];
PFFile *userImageFile = [object valueForKey:#"image"];
[[cell imageView] setFile: userImageFile];
[[cell imageView] loadInBackground];
[[cell activityIndicator] stopAnimating];
[[cell title] setText:[object valueForKey:#"title"]];
[[cell price] setText:[NSString stringWithFormat: #"£%# GBP", [object valueForKey:#"price"]]];
return cell;
}
return 0;
}
Here is method triggered when the segmented control is tapped:
- (void)displayTypeSegmentSelected
{
_selectedDisplayTypeIndex = [_displayTypeControl selectedSegmentIndex];
if (_selectedDisplayTypeIndex == 0) {
NSLog(#"Single file item view selected");
[_collectionView setHidden:YES];
[_collectionView2 setHidden:NO];
[_collectionView2 reloadData];
} else {
NSLog(#"Grid style view selected");
[_collectionView setHidden:NO];
[_collectionView2 setHidden:YES];
[_collectionView reloadData];
}
}
I feel everything is done correctly. My main collection view shows up when I tap the grid style side of the segmented control.
When I tapped the single file segment control option this was the result:
As you can see the cells show up but are empty. I'm not quite sure what is going on. If I tap the grid style segment option the main collection view displays fine.
However although the single file collection view shows the correct amount of cells, no content is shown. There should be an image and some text underneath it.
I can't help but think I'm missing a step. Is there some step taken in IB automatically that I haven't done programmatically with my second custom view?
Please note that I haven't yet changed cell size settles to make collection view 2 single file style. I want to first get the content to show up before I move any further.
Help is appreciated
Regards
Update:
#import "VAGGarmentCell.h"
#implementation VAGGarmentCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
and .h for garment cell:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface VAGGarmentCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet PFImageView *imageView;
#property (weak, nonatomic) IBOutlet UIButton *addFavouriteButton;
#property (weak, nonatomic) IBOutlet UITextView *title;
#property (weak, nonatomic) IBOutlet UILabel *price;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
I think the problem is trying to use the cell in _collectionView2 that is defined in your storyboard collection view. Instead of doing that, delete the cell from the storyboard collection view, and make the cell in a xib file. Change the class of that cell to VAGGarmentCell, and hook up any IBOutlets to the VAGGarmentCell class. In viewDidLoad, register the nib (not the class) for both controllers.,
[_collectionView2 registerNib:[UINib nibWithNibName:#"VAGGarmentCell" bundle:nil] forCellWithReuseIdentifier:#"Cell2"];
[self.collectionView registerNib:[UINib nibWithNibName:#"VAGGarmentCell" bundle:nil] forCellWithReuseIdentifier:#"Cell"];
You can use the same reuse identifier or different ones, it doesn't matter as long as the ones you register are the same as the ones you use in celForItemAtIndexPath for their respective controllers.

applying gesture on all UICollectionViewCells

in my app i have a UICollectionView. i want to apply to it's cells a long pressure gesture. i implemented that but when i run the app only the last cell works and the others do not respond. what it wrong? here is my code.
#interface
#property (nonatomic, strong) UILongPressGestureRecognizer *longPressure;
in view did load:
self.longPressure = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handlePressue:)];
self.longPressure.delegate = self;
[self.collectionView addGestureRecognizer:self.longPressure];
gesture handler:
- (void)handlePressue:(UILongPressGestureRecognizer*)gesture{
[[gesture.view viewWithTag:1] setBackgroundColor:[UIColor yellowColor]];
}
in collectionView:cellforitemAtIndexPAth:
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 75, 75)];
imageView.tag = 1;
[imageView setBackgroundColor:[UIColor redColor]];
[cell addGestureRecognizer:self.longPressure];
[cell addSubview:imageView];
return cell;
is there anything wrong?
you need to add gesture on the each cell not for the UICollection View. that might be your problem.the last cell works because the gesture is added to the last cell only.
You need to creat long press gesture for each cell. Because gesture like other ui control,only one in the project.If you want add it to other view,you need copy another one.
Have a look at following Code snippet
MyFlowLayout *myLayout = [[MyFlowLayout alloc]init];
[self.collectionView setCollectionViewLayout:myLayout animated:YES];
UIGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc]
}
initWithTarget:self action:#selector(handlePinch:)];
[self.collectionView addGestureRecognizer:pinchRecognizer];
Handling the Pinch:
- (IBAction)handlePinch:(UIPinchGestureRecognizer *)sender {
// Get a reference to the flow layout
MyFlowLayout *layout =
(MyFlowLayout
*)self.collectionView.collectionViewLayout;
// If this is the start of the gesture
if (sender.state == UIGestureRecognizerStateBegan) {
// Get the initial location of the pinch?
CGPoint initialPinchPoint =
[sender locationInView:self.collectionView]; //Convert pinch location into a specific cell
NSIndexPath *pinchedCellPath =
[self.collectionView
indexPathForItemAtPoint:initialPinchPoint];
// Store the indexPath to cell
layout.currentCellPath = pinchedCellPath; }
else if (sender.state == UIGestureRecognizerStateChanged) {
// Store the new center location of the selected cell layout.currentCellCenter =
[sender locationInView:self.collectionView]; // Store the scale value
layout.currentCellScale = sender.scale; }
else {
[self.collectionView performBatchUpdates:^{ layout.currentCellPath = nil;
layout.currentCellScale = 1.0;
} completion:nil];
} }
For performance reasons I suggest you to avoid adding subviews and/or gestures to every single cell. Instead, add a singe longPressureGesture to your collectionView and on the gesture selector handle your per-cell switch business logic. Something as follow:
On your viewDidLoad or where you setup your collection, add the following gesture:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(showDeleteActions:)];
longPress.delegate = self;
[_aCollectionView addGestureRecognizer:longPress];
then on the selector do the single-cell handling:
- (void)showDeleteActions:(UILongPressGestureRecognizer*)gesture {
if (gesture.state == UIGestureRecognizerStateBegan)
{
NSIndexPath *indexPath = [_aCollectionView indexPathForItemAtPoint:[gesture locationInView:_aCollectionView]];
UICollectionViewCell *cell = [_aCollectionView cellForItemAtIndexPath:indexPath];
NSLog(#"cell to delete at IndexPath: %#", indexPath);
}
}
this approach is much more efficient abd far more stable.
Here what it is causing that your UILongPressGestureRecognizer getting overwrite to last cell. So you need to create UILongPressGestureRecognizer for each cell in cellForRowAtIndexPath:
Here is a small code snippet that can help you out
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 75, 75)];
imageView.tag = 1;
[imageView setBackgroundColor:[UIColor redColor]];
UILongPressGestureRecognizer *longPressure =[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handlePressue:)];
longPressure.delegate = self;
cell.userInteractionEnabled = YES; // Make userInteractionEnabled enable so it can detect touch
[cell addGestureRecognizer:self.longPressure];
[cell addSubview:imageView];
return cell;
There is no need to create any property for the UILongPressGestureRecognizer in .h file. And also remove code to add userInteractionEnabled on whole UICollectionView.

How to create a custom UICollectionViewCell and add image from URL to it?

i want to load my images i've got from flickr into uicollectionsview
i followed allot of guides but they all fall apart when i have to do this
cell.imageView.image
it basically says it can't find imageView in object of uicollectionsviewcell
i also tried a method like this, but it didn't work
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"flickerCell";
UICollectionViewCell *flickerCell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
UIImageView *recipeImageView = (UIImageView *)[flickerCell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
[flickerCell addSubview:recipeImageView];
return flickerCell;
}
recipieImageView is something i got some a tutorial.
my cell is named flickerCell in the storyboard and photoURLs has 33 objects i can view in code . so it's all there. also photoURLs is a NSMutablearray
how ever. in this method my recipeImageView returns nill ???
i have a cell.h which has the imageView
#import <UIKit/UIKit.h>
#interface Cell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#end
so if anyone know a way i can display all the images that photoURLs has in a uicollectionview it would be very helpful
UPDATE
i now tried a new way but still not working. imageView returns nil
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"flickerCell";
Cell *flickerCell = (Cell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
return flickerCell;
}
UPDATE AGAIN
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"flickerCell";
Cell *flickerCell = (Cell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSLog(#"flickercell = %#", flickerCell);
flickerCell.backgroundColor = [UIColor whiteColor];
flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
return flickerCell;
}
with this in viewdidload
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:#"flickerCell"];
NSLOG of flickerCell returns this :
flickercell = <Cell: 0x9dec2f0; baseClass = UICollectionViewCell; frame = (0 0; 120 115); layer = <CALayer: 0x9dec430>>
As I get it you are using a custom UICollectionViewCell. However in the method you pasted you create a pointer to UICollectionViewCell which has no built-in UIImageView. So that's why you get the error in the first try.
About the second - did you register your custom UICollectionViewCell class with the CollectionView?
======
Edit: after a long chat with the poster we solved all the problems.
The first one was that the registered class was UICollectionViewCell, not the inherited custom one.
The second problem was that the view was actually in a xib file, so registerNib:forCellWithReuseIdentifier: should be used instead of registerClass:forCellWithReuseIdentifier:
The third one was that the custom cell was configured in a storyboard xib instead of its own xib file that is wired with the custom class ("Cell" in our case)
And fourth main problem was that UIImage was incorrectly created with imageNamed: which should be used only for images that are embedded in the project. The correct way to create the UIImage in our case is: flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
It may help you.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"flickerCell";
Cell *flickerCell = (Cell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
return flickerCell;
}
You can easily create a custom UICollectionViewCell class with custom the animation while tap the UICollectionViewCell.
So, You don't need to add any specific method/action for the animation.
In storyboard - Add a UICollectionViewCell with cell identifier, UIImageView and UILabel.
Assign both UIImageView and UILabel property to Storyboard cell.
Import the 'UviCollectionCell.h' in your view controller.
In YourViewController.h
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UviCollectionCell *cell = (UviCollectionCell *) [cv dequeueReusableCellWithReuseIdentifier:#"collection_cell" forIndexPath:indexPath];
[cell.cellImageView setBackgroundColor: [UIColor randomColor]];
// You can add your image here.
cell.cellImageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
[cell.cellTitle setText:[NSString stringWithFormat:#"S %ld - R %ld",(long)indexPath.section,(long)indexPath.row]];
//cell.backgroundColor = [UIColor randomColor];
return cell;
}
UviCollectionCell.h
#import <UIKit/UIKit.h>
#interface UviCollectionCell : UICollectionViewCell<UIGestureRecognizerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *cellImageView;
#property (strong, nonatomic) IBOutlet UILabel *cellTitle;
#end
UviCollectionCell.m
#import "UviCollectionCell.h"
#implementation UviCollectionCell
// Initialize the collectiion cell based on the frame and add the tap gesture recognizer for custom animation
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
// Custom animation while tap the CollectionCell view.
UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(selectedCellAnimation)];
[tapReconizer setNumberOfTouchesRequired : 1];
[tapReconizer setDelegate:self];
[self addGestureRecognizer:tapReconizer];
return self;
}
// Initialize the collection cell based on the nscoder and add the tap gesture recognizer for custom animation
-(id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
// Custom animation while tap the CollectionCell view.
UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(selectedCellAnimation)];
[tapReconizer setNumberOfTouchesRequired : 1];
[tapReconizer setDelegate:self];
[self addGestureRecognizer:tapReconizer];
return self;
}
// Initialize the collectiion cell and add the tap gesture recognizer for custom animation
-(id) init {
self = [super init];
// Custom animation while tap the CollectionCell view.
UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(selectedCellAnimation)];
[tapReconizer setNumberOfTouchesRequired : 1];
[tapReconizer setDelegate:self];
[self addGestureRecognizer:tapReconizer];
return self;
}
// Customize the animation while tap the UICollectionViewCell with custom animation duration.
- (void)selectedCellAnimation {
[UIView animateWithDuration:0.4 delay:0 options:(UIViewAnimationOptionCurveEaseIn) animations:^{
CALayer *layer = self.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 25.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:0 options:(UIViewAnimationOptionCurveEaseOut) animations:^{
CALayer *layer = self.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m24 = 0;
rotationAndPerspectiveTransform =CATransform3DRotate(rotationAndPerspectiveTransform, 0.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
} completion:nil];
}];
}
#end
In your code
imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
what does [photoURLs objectAtIndex:indexPath.row] return?
For use with imageNamed: it MUST return a NSString object which is the name of a resource located in the main bundle. It won't work with a URL, even less if this URL is pointing to a remote URL.
Anyway, you shouldn't use imageNamed. This method caches the image in the system's cache, which is not optimal/required in a collection/table view. Instead use an alternative method to create the UIImage object.
A solution to your problem depends whether you need to load your image data from a remote server or if these resources are located on the device.
In the first case, you need an asynchronous approach in conjunction with a "placeholder image" which represents an image while being loaded when it is displayed in the cell.
In the second case, you may use a simple synchronous approach to load images (similar to your existing solution, but using imageWithContentsOfFile: for example), unless the images are large, in which case you need an asynchronous approach too.
Note: your code has a few other issues, too - but first and foremost you need to tell where your images come from.
A possible (but not optimal) solution for loading images from the disk on the device:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"flickerCell";
FlickerCell* flickerCell = (FlickerCell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
NSURL* url = [self.photoURLs objectAtIndex:indexPath.row]; // file URL
flickerCell.imageView.image = [UIImage imageWithContentsOfFile:[url path]];
return flickerCell;
}
A more sophisticated solution would load and decode images ahead in a background thread - before they are actually displayed. That way, when they are actually displayed, the images are possibly already encoded and will render much faster. This also requires a cache.

subView in UICollectionViewCell displayed wrong when UICollectionView scrolled

I make a custom UICollectionViewCell and add a subView to its contentView:
BooksCell.h
#interface BooksCell : UICollectionViewCell
#property (strong, nonatomic) UIImageView *certifyImageView;
#end
BooksCell.m
- (id)initWithFrame:(CGRect)frame {
self= [super initWithFrame:frame];
if(self){
_coverImageView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 15, 88, 117)];
_coverImageView.userInteractionEnabled = YES;
[self.contentView addSubview:_coverImageView];
UIImage *certifyImage = [UIImage imageNamed:#"13-6.png"];
_certifyImageView = [[UIImageView alloc] initWithFrame:CGRectMake(17.5, _coverImageView.frame.size.height-3, certifyImage.size.width, certifyImage.size.height)];
_certifyImageView.image = certifyImage;
_certifyImageView.hidden = YES;
}
return self;
}
ViewController
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
BooksCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"BooksCell" forIndexPath:indexPath];
cell.coverImageView.image = [UIImage imageNamed:#"13-5.png"];
// **Here I want some cell display certifyImageView and some not.**
if(indexPath.row%2==0){
cell.certifyImageView.hidden = NO;
}
return cell;
}
I add the collectionView as subView to the Viewcontroller, and set it's frame correctly, now the collectionView displaied coverImageView and certifyImageView normally, but when I scroll the collectionView, certifyImageView displaied on the wrong cell,I guess it maybe caused by the Reuse Cell, and how to sole it?
I think because it is reusing the cell that already set the certifyImageView.hidden to NO so you have to set it back to YES
Maybe try this
if(indexPath.row%2==0){
cell.certifyImageView.hidden = NO;
}
else{
cell.certifyImageView.hidden = YES;
}
This way you will make sure that the certifyImageView will be set to hidden if thats what you want.

Resources