How to call delegate methods of CollectionView inside TableView in Objective C? - ios

TableViewCell Class
- (void)awakeFromNib {
//Registering CollectionViewCell
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [productsData count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"collectionCell" forIndexPath:indexPath];
NSDictionary *cellData = [productsData objectAtIndex:[indexPath row]];
cell.imageView.image = [UIImage imageNamed:[cellData objectForKey:#"image"]];
return cell;
}
How to call delegate methods of collection view?

In your TableViewCell.h file add .
#property (nonatomic, assign) UICollectionView *yourCollectionView;
In your TableViewCell.m file add .
#synthesize yourCollectionView;
in your init method alloc collection view & set delegate & datasource .
yourCollectionView = [UICollectionView alloc] initWithFrame://( your frame) ];
yourCollectionView.dataSource = self;
yourCollectionView.delegate = self;
// set other properties as per tour needs .
[self.contentView addSubview:yourCollectionView];
Add check your delegate methods wotrking fine . hope it helps you .

Related

Keep reference of views from collectionView is doubled

Trying to keep reference in arrays of all views that being added to collection view .
So what happens, is that i have this array with the data, but when i scroll down the collection, it calls the reusable cells function ,and try to add them again to my array ,although i am checking if they are there before adding them again :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
//quantity
UILabel *quantityL=[[UILabel alloc] initWithFrame:CGRectMake(cell.frame.size.width/10,cell.frame.size.width/10, cell.frame.size.width/5,cell.frame.size.width/5)];
quantityL.text=[NSString stringWithFormat:#"%d",quantity];
quantityL.font=[UIFont fontWithName:[Globals sharedGlobals].titleFont size:[Globals sharedGlobals].badgeSize];
quantityL.textAlignment=NSTextAlignmentCenter;
//more and more stuff
[cell addSubview:quantityL]; //add to cell
if(![allQuantities containsObject:quantityL]) //check if already in array!
[allQuantities addObject:quantityL]; //add to array
i can see that allQuantities array is changing its size... why ?
To properly reuse and set frames: code for your controller:
#define kMyCellIdentifier #"kMyCellIdentifier"
- (void)viewDidLoad {
[super viewDidLoad];
//...
[self.collectionView setDelegate:self];
[self.collectionView setDataSource:self];
[self.collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:kMyCellIdentifier];
}
#pragma mark - UICollectionViewDelegate && UICollectionViewDataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kMyCellIdentifier forIndexPath:indexPath];
[cell.textLabel setText:#"blah"];
return cell;
}
And your cell subclass:
#interface MyCollectionViewCell : UICollectionViewCell
#property(nonatomic, readonly) UILabel *textLabel;
#end
#implementation MyCollectionViewCell
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_textLabel = [[UILabel alloc] init];
[self.textLabel setTextAlignment:NSTextAlignmentCenter];
[self.contentView addSubview:self.textLabel];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect rect = self.contentView.bounds;
[self.textLabel setFrame:rect];
}

Use more than one UICollectionViews in a ViewController

I tried to use two UICollectionViews in a single ViewController. Application crashed with the following error
reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier ItemCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard
This is my implementation how looks like
HomeViewController.h
UICollectionView *colloctionViewItems;
UICollectionView *colloctionViewCats;
#property (nonatomic, retain) IBOutlet UICollectionView *colloctionViewItems;
#property (nonatomic, retain) IBOutlet UICollectionView *colloctionViewCats;
HomeViewController.m
#synthesize colloctionViewCats, colloctionViewItems;
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// read ItemList plist
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *dicCats = [appDelegate readPlistIntoDictWithFile:#"CatagoryList.plist"];
// arrCategories
arrCats = [[NSArray alloc]initWithArray:[dicCats objectForKey:#"Catagories"]];
[self.colloctionViewItems registerClass:[ItemCell class] forCellWithReuseIdentifier:#"ItemCell"];
[self.colloctionViewCats registerClass:[CatCell class] forCellWithReuseIdentifier:#"CatCell"];
[colloctionViewItems reloadData];
[colloctionViewCats reloadData];
}
#pragma mark for Collection View Delegate methods
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section
{
if(view == colloctionViewItems){
return [arrCats count];
}
if(view == colloctionViewCats){
return [arrCats count];
}
return 0;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeZero;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ItemCell *iCell = [cv dequeueReusableCellWithReuseIdentifier:#"ItemCell" forIndexPath:indexPath];
CatCell *cCell = [cv dequeueReusableCellWithReuseIdentifier:#"CatCell" forIndexPath:indexPath];
if(cv == colloctionViewItems){
iCell.lblBtnTitle.text = [arrCats objectAtIndex:indexPath.row];
return iCell;
}
if(cv == colloctionViewCats){
cCell.lblBtnTitle.text = [arrCats objectAtIndex:indexPath.row];
return cCell;
}
return iCell;
}
If I removed one UICollectionView, all works fine. Any ideas please.
FYI: I have created Custom Collection Cell class as "ItemCell" and "CatCell" correctly (without using nibs)
It's because you dequeue both cell at the same time, even if the collection view hasn't contain the right cell. You should first check which collection view is asking about cell and after that dequeue the right one:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if(cv == colloctionViewItems){
// Item collection view contain item cell so you can safety dequeue it.
// if you try to dequeue CatCell it will fail this is why you had this issue before
ItemCell *iCell = [cv dequeueReusableCellWithReuseIdentifier:#"ItemCell" forIndexPath:indexPath];
iCell.lblBtnTitle.text = [arrCats objectAtIndex:indexPath.row];
return iCell;
}
if(cv == colloctionViewCats){
CatCell *cCell = [cv dequeueReusableCellWithReuseIdentifier:#"CatCell" forIndexPath:indexPath];
cCell.lblBtnTitle.text = [arrCats objectAtIndex:indexPath.row];
return cCell;
}
return nil;
}

How to add photos into UICollectionViewCell?

I have creates a UICollectionView which I currently have showing white cells. I have been following this tutorial to figure out how to use the delegate methods etc.
I have made it up to the point where you create the Creating custom UICollectionViewCells however in this example the tutorial he tells you to open your story board etc. I don't have a story board. I have tried to follow the instructions to create the view but with my own .xib file and I just cannot get anything to work.
How can I check out where my delegate methods are at this point?
// this is how I load the collection view
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
photoCollectionView =[[UICollectionView alloc] initWithFrame:CGRectMake(10.0, 40.0, 480.0, 713.0) collectionViewLayout:layout];
photoCollectionView.dataSource = self;
photoCollectionView.delegate = self;
[self.view addSubview:photoCollectionView];
[photoCollectionView.layer setBorderColor: [[UIColor lightGrayColor] CGColor]];
[photoCollectionView.layer setBorderWidth: 1.0];
[self.photoCollectionView reloadData];
// this is what my delegate methods look like
#pragma mark - CollectionView Delegates
#pragma mark -- UICollectionView Datasource
// 1
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
return [imageArray count];
}
// 2
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
return 1;
}
// 3
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"PhotoCell" forIndexPath:indexPath];
// I think this is where I want to set my image for the cell
NSDictionary *currentPhotoDict = [imageArray objectAtIndex:indexPath.row];
UIImage *imageForCollection = [UIImage imageWithData:[currentPhotoDict objectForKey:#"DImage"]];
// but I have no idea where to pass the imag....
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
#pragma mark -- UICollectionView Delegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// TODO: Select Item
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
// TODO: Deselect item
}
#pragma mark –- UICollectionViewDelegate FlowLayout
// 1
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize retval = CGSizeMake(210, 157+20); // add 20 for labels under neath.. might need to adjust this.
return retval;
}
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(50, 20, 50, 20);
}Subview:photoCollectionView];
[photoCollectionView.layer setBorderColor: [[UIColor lightGrayColor] CGColor]];
[photoCollectionView.layer setBorderWidth: 1.0];
[self.photoCollectionView reloadData];
As you can see in collectionView:cellForItemAtIndexPath I have my image ready
NSDictionary *currentPhotoDict = [imageArray objectAtIndex:indexPath.row];
UIImage *imageForCollection = [UIImage imageWithData:[currentPhotoDict objectForKey:#"DImage"]];
I just need to know how to load it into the collectionviewcell.
Please try to use like this....
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"PhotoCell" forIndexPath:indexPath];
// I think this is where I want to set my image for the cell
NSDictionary *currentPhotoDict = [imageArray objectAtIndex:indexPath.row];
UIImage *imageForCollection = [UIImage imageWithData:[currentPhotoDict objectForKey:#"DImage"]];
[cell setBackgroundColor:[UIColor colorWithPatternImage:imageForCollection];// Add your image here........
// but I have no idea where to pass the imag....
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
i hope it will help you...
I have UICollectionViewCell with name PhotoCell. and have label and imageview as properties.
This is how u can set Image to cell. May this is your requirement or not. I dont know. Try this
You need to set identifier at Xib of your UICollectionViewCell as MY_CELL or some other name.Then
.m
static NSString *cellidentity=#"MY_CELL";
At ViewDidLoad method
UINib *nib;
nib = [UINib nibWithNibName:#"PhotoCell" bundle:nil];
[self.collectionView registerNib:nib forCellWithReuseIdentifier:cellidentity];
My UICollectionViewCell .h is
#interface PhotoCell : UICollectionViewCell
#property (retain, nonatomic) IBOutlet UILabel* label;
#property (retain, nonatomic) IBOutlet UILabel* timelineLabel;
#property (retain, nonatomic) IBOutlet UIImageView* yourImageView;
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
// PhotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"PhotoCell" //forIndexPath:indexPath];
PhotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:cellidentity forIndexPath:indexPath];
NSDictionary *currentPhotoDict = [imageArray objectAtIndex:indexPath.row];
UIImage *imageForCollection = [UIImage imageWithData:[currentPhotoDict objectForKey:#"DImage"]];
// but I have no idea where to pass the imag....
cell.label.text = [NSString stringWithFormat:#"%d",indexPath.item];
cell.yourImageView.image=imageForCollection;
return cell;
}
Hope it helps You....

collectionviewCell not change when transition to other collectionviewController

I create 2 UICollectionView classes, each one use 2 different UICollectionViewCell
#interface PhotosCollectionViewController : UICollectionViewController
#interface FullScreenCollectionViewController : UICollectionViewController
#interface PhotoCell : UICollectionViewCell
#interface FullPhotoCell : UICollectionViewCell<UIScrollViewDelegate>
In PhotosCollectionViewController.m, I register PhotoCell class and choose next view controller is FullScreenCollectionViewController when didSelect
//Register Cell
-(id)initWithCollectionViewLayout:(UICollectionViewFlowLayout *)layout{
if (self = [super initWithCollectionViewLayout:layout])
{
[self.collectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:CELL_ID];
}
return self;
}
//dequence resuse code
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell* cell = (PhotoCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CELL_ID forIndexPath:indexPath];
NSLog(#"reuse CELL");
FICDPhoto *photo = [_photos objectAtIndex:indexPath.row];
cell.imageView.image = [photo sourceImage];
return cell;
}
//Next ViewController transition code
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *vc = [self nextViewControllerAtPoint:CGPointZero];
[self.navigationController pushViewController:vc animated:YES];
}
-(UICollectionViewController*)nextViewControllerAtPoint:(CGPoint)p
{
FullScreenCollectionViewController* nextCollectionViewController = [[FullScreenCollectionViewController alloc] initWithCollectionViewLayout:[[FullScreenFlowLayout alloc] init]];
nextCollectionViewController.useLayoutToLayoutNavigationTransitions = YES;
nextCollectionViewController.title = #"FullScreen";
return nextCollectionViewController;
}
In FullScreenCollectionViewController, I register FullPhotoCell class
[self.collectionView registerClass:[FullPhotoCell class] forCellWithReuseIdentifier:CELL_ID_FULL];
But sequence code never call
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
FullPhotoCell* cell = (FullPhotoCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CELL_ID_FULL forIndexPath:indexPath];
NSLog(#"Reuse FULL Cell");
FICDPhoto *photo = [_photos objectAtIndex:indexPath.row];
cell.imageView.image = [photo sourceImage];
return cell;
}
New layout is apply, viewDidload of FullScreenCollectionViewController also call, but the log message "reuse CELL" tell that fullScreen CollectionView still use old PhotoCell class.
I still don't understand what's problem. Please help me!
The answer is "a bit" late but this might be useful for someone else. When you use useLayoutToLayoutNavigationTransitions the collection view from the view controller initiating the transition is actually reused. This collection view has a different data source and delegate and that's why FullScreenCollectionViewController's cellForRowAtIndexPath is not being called. Take a look at this similar question:
UICollectionView UseLayoutToLayoutNavigationTransitions with different datasources

Change attributes of a UICollectionViewCell in didSelectItemAtIndexPath

I am configuring a UICollectionViewCell in a subclass, it adds 2 subviews to the contentView property, both are UIImageView and both have the hidden property set to YES. These subviews are "checked" and "unchecked" images that overlay the primary UIImageView in the cell to indicate whether or not the current cell is selected using UICollectionView's "multiple select" feature.
When the cell is tapped, collectionView:didSelectItemAtIndexPath: is called on the delegate, and I'd like to setHidden:NO on the "checked" UIImageView. Calling this on the cell does nothing at all -- the cell is seemingly locked in its originally drawn state.
Is it possible to make changes to a cell outside collectionView:cellForItemAtIndexPath:? I have tried manually adding subviews within collectionView:didSelectItemAtIndexPath:, but it just makes absolutely no change to the UI. I have verified that the delegate method is getting called, it's just not making my cell changes.
- (void) collectionView(UICollectionView *)cv didSelectItemAtIndexPath(NSIndexPath *)indexPath {
ShotCell *cell = [self collectionView:cv cellForItemAtIndexPath:indexPath];
UILabel *testLabel = UILabel.alloc.init;
testLabel.text = #"FooBar";
testLabel.sizeToFit;
[cell.contentView.addSubview testLabel];
}
The way you're trying to do this is incorrect. You need to keep a reference to the selected cell or cells in a property. In this example, I use an array to hold index paths of the selected cells, then check whether the index path passed in to cellForItemAtIndexPath is contained in that array. I unselect the cell if you click on one that's already selected:
#interface ViewController ()
#property (strong,nonatomic) NSArray *theData;
#property (strong,nonatomic) NSMutableArray *paths;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.paths = [NSMutableArray new];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight"];
[self.collectionView registerNib:[UINib nibWithNibName:#"CVCell" bundle:nil] forCellWithReuseIdentifier:#"cvCell"];
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[self.collectionView setCollectionViewLayout:flowLayout];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.theData.count;
}
-(CVCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cvCell";
CVCell *cell = (CVCell *) [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
cell.label.text = self.theData[indexPath.row];
if ([self.paths containsObject:indexPath]) {
[cell.iv setHidden:NO]; // iv is an IBOutlet to an image view in the custom cell
}else{
[cell.iv setHidden:YES];
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if ([self.paths containsObject:indexPath]) {
[self.paths removeObject:indexPath];
}else{
[self.paths addObject:indexPath];
}
[self.collectionView reloadItemsAtIndexPaths:#[indexPath]];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(150, 150);
}

Resources