IOS Development making viewcells clickable - ios

I'm just beginning IOS development and am wondering if anybody could help me figure out how to get the cell details that are being clicked.
I have a cell like this:
#import <UIKit/UIKit.h>
#interface ICICell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#property (weak, nonatomic)IBOutlet ICICell *myCell;
#property (weak, nonatomic) IBOutlet UIImageView *myGallery;
#end
in the view controller I am populating the cells like this:
-(UICollectionViewCell * ) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
ICICell * aCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
aCell.myLabel.text = self.dataArray[indexPath.row];
UIImage *img;
long row = [indexPath row];
img = [UIImage imageNamed:self.iciImages[row]];
aCell.myGallery.image = img;
return aCell;
}
I have found the didDeselectItemAtIndexPath method, but is there a method didSelectItemAtIndexPath?
I am trying to get the label text for a selected cell. Bit confused why there is a didDeselect and no didSelect? Thanks in advance.

Linda Keating,
There are both methods available as you are expecting..have a reference from below
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
/* Here you can do any code for Selected item at indexpath.*/
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
}
Thanks.

Of course You can navigate into Detail Screen of Collection View cell.
Just use didSelectItemAtIndexPath method.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
VIPRoomDetailController *enterIntoRoomDetail = [[VIPRoomDetailController alloc]initWithNibName:#"VIPRoomDetailController" bundle:nil];
[self.navigationController pushViewController:enterIntoRoomDetail animated:YES];
}
Also Import Detail controller in your collection View class In my case it is VIPRoomDetailController

Related

Centred Paging for CollectionView cells in iOS Objective-C

I created a table view that has collection view inside its cells with this tutorial Creating a Scrolling Filmstrip Within a UITableView but I want to achieve a banner kind of feature that has centred paging and scrolls automatically to each cell item. I enabled page scrolling but didn't work. How do I do this? I currently have a UIView in the table view cell that serves as the data source for the collection view. Here is the code for the UIView subclass.
#interface ContainerCellView () <UICollectionViewDataSource, UICollectionViewDelegate>
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#property (strong, nonatomic) NSArray *collectionData;
#end
#implementation ContainerCellView
#pragma mark - Getter/Setter ovverides
- (void)setCollectionData:(NSArray *)collectionData {
_collectionData = collectionData;
[_collectionView setContentOffset:CGPointZero animated:YES];
[_collectionView reloadData];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.collectionData count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ArticleCollectionViewCell";
BannersCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
NSDictionary *cellData = [self.collectionData objectAtIndex:indexPath.row];
cell.articleTitle.text = [cellData objectForKey:#"title"];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *cellData = [self.collectionData objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"didSelectItemFromCollectionView" object:cellData];
}
#end
You are possibly looking for property for collectionView called isPagingEnabled which comes from UIScrollView, otherwise, you should create your cell big enough to achieve this pretty nice effect. However, you can relate here, if you are looking for paging by cells click here Hope this may help you

Incorrect data on scrolling UITableView and UICollectionView

I have attached my sample project with github and provided the link belowI have a table view and in that tableview the cell consists of a UICollectionView. This means that every cell can scroll horizontally upto a certain limit,lets say 5.Both the tableView cell and collectionview cell have custom cell classesThe tableview cell has also a UIPageControl which will change when we will scroll the UICollectionViewCells horizontally
I managed to do this part of work but suppose I have scrolled the 2nd tableview cell's collectionview to 3rd Position and this repeats somewhat around on 9th tableview cell. The 9th tableview cell also has the same data. But I havent set anything yet on 9th. So this means the problem is of reusability and data in getting incorrect while scrolling.
My Code so far is
//ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
Implementation Class
//ViewController.m
#import "ViewController.h"
#import "MyCollectionViewCell.h"
#import "MyTableViewCell.h"
#interface ViewController ()
{
MyTableViewCell* tableViewCell;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark TableView Delegates
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section{
return 10;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
tableViewCell=(MyTableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"MyTableViewCell"];
if(tableViewCell==nil)
{
tableViewCell=[[MyTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyTableViewCell"];
}
UICollectionViewFlowLayout *flowLayout =
[[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[flowLayout setMinimumInteritemSpacing:0.0f];
[flowLayout setMinimumLineSpacing:0.0f];
[tableViewCell.collectionView setPagingEnabled:YES];
[tableViewCell.collectionView setCollectionViewLayout:flowLayout];
[tableViewCell.collectionView setBackgroundColor:[UIColor whiteColor]];
tableViewCell.pageControl.tag=indexPath.row;
tableViewCell.collectionView.tag=indexPath.row;
NSLog(#"Index path row %ld",indexPath.row);
[tableViewCell setSelectionStyle:UITableViewCellSelectionStyleNone];
tableViewCell.path=indexPath;
return tableViewCell;
}
#pragma mark CollectionView Delegates
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 5;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
MyCollectionViewCell* cell=(MyCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"MyCollectionViewCell" forIndexPath:indexPath];
if(cell==nil)
{
cell=[[MyCollectionViewCell alloc]initWithFrame:CGRectMake(0, 0, collectionView.frame.size.width, collectionView.frame.size.height)];
}
[cell.myLabel setText:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return collectionView.frame.size;
}
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout: (UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
if ([scrollView isKindOfClass:[UICollectionView class]])
{
UICollectionView *mainCollection = (UICollectionView *) scrollView;
NSIndexPath *myIP = [NSIndexPath indexPathForRow:mainCollection.tag inSection:0];
MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:myIP];
CGRect visibleRect = (CGRect){.origin = mainCollection.contentOffset, .size = mainCollection.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [mainCollection indexPathForItemAtPoint:visiblePoint];
NSLog(#"visibleIndexPath %ld",(long)visibleIndexPath.row);
[cell.pageControl setCurrentPage:visibleIndexPath.row];
}
}
#end
Cells classes
//MyTableViewCell.h
#import <UIKit/UIKit.h>
#interface MyTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
#property (strong, nonatomic) NSIndexPath * path;
#end
MyCollectionViewCell.h
//MyCollectionViewCell.h
#import <UIKit/UIKit.h>
#interface MyCollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
View is Something like
My concern is that whenever I make any change lets say on cell 1 on table viewcell and scroll the collection in it to lets say 2nd index, then this is re repeated whenever i scroll the complete table
NOTE: I have kept number of cells of table to 10 to see the repeated impact.
The Github link of my sample project is https://github.com/RajanMaheshwari/TableAndCollection
First of all:
[collectionView dequeueReusableCellWithReuseIdentifier:#"MyCollectionViewCell" forIndexPath:indexPath]
always returns a view, so you don't need that:
if(cell==nil)
{
cell=[[MyCollectionViewCell alloc]initWithFrame:CGRectMake(0, 0, collectionView.frame.size.width, collectionView.frame.size.height)];
}
since it's not gonna happen.
And the real reason for you is that you have only one cell for all UITableView...
Where the idea of keeping tableCell as property comes from ?
MyTableViewCell* tableViewCell;
You need to create a cell instance for each indexPath separately, right now you have one instance which is displayed several times, that's why changing collection view page on one of them is affecting other rows - since it's the same object (view).
After you remove that problem, you need to remember that elements will be reused - which means your first row instance, you be reused again on 5th row, after it dissapears from the screen, so after you dequeue the elements, you need to set all variables to this row.
You cannot keep your variables inside this row, because it will be reused, so even though you have 100 rows, you will around 5-6 instances (depends on row height) that will be reused across whole table.
You need to keep important variables, necessary to render every row, outside of the views and configure views based on those.
In your case you should keep page index of pageControl for every row - use NSDictionary for that and keep a NSNumber for every indexPath in your UITableView.
Whenever page is changing, update the value in this NSDictionary (defaults to zero).
When you create a cell with collection view, set proper value to pageControl based on what you have in NSDictionary for this indexPath

UITableview cell retain custom image view filter

I often faces this issue when developing tableview custom cell.
Here is problem, I have a tableview and it has lots of customized cell (a UIImageView and UILabel) When user tap any of this cell pushes new UIViewController and user filling some data and tapped the "Save" viewcontroller push back with delegation method.
In this delegate method I inspect tapped cell and change that tint color (like selected state but I'm only changing custom imageview tint color). So this changes correctly but when I'm scrolling any vertical direction tint color disappear. Below pictures and code for figuring out correctly.
When pop to view controller from delegate method (works correctly)
When scrolling vertical direction tin
// Custom cell
#interface CustomCell : UITableViewCell
#property(strong, nonatomic) UIImageView *imageView;
#property(strong, nonatomic) UILabel *titleLabel;
#end
// Custom Cell implementation nothing special here.
// UIViewController delegate method when pop back
// I'm filling specific color
#interface UIViewController
#property (strong,nonatomic) CustomCell *myCustomCell;
#end
#implementation UIViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
_myCustomCell = (CustomCell *)[self.tableView dequeueReusableCellWithIdentifier:#"CustomCell" forIndexPath:indexPath];
...
}
- (void)userTappedBackButton {
_myCustomCell.imageView.image = [cell.customImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_myCustomCell.imageView.tintColor = [UIColor colorWithRed:0.27 green:0.58 blue:0.98 alpha:1];
}
#end
The problem you have is that you are saving a reference to the UITableViewCell but the cells are being reused.
You need to save the information about the cell to be highlighted in another manner, that cannot be influenced by the cells being reused. I would suggest by using the indexPath.
Something like the following should work:
#property (nonatomic, strong) NSIndexPath *lastSelectedIndexPath;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
CustomCell *cell = (CustomCell *)[self.tableView dequeueReusableCellWithIdentifier:#"CustomCell" forIndexPath:indexPath];
if([indexPath isEqual:self.lastSelectedIndexPath]) {
cell.imageView.image = [cell.customImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
cell.imageView.tintColor = [UIColor colorWithRed:0.27 green:0.58 blue:0.98 alpha:1];
}
...
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Save the selected indexPath
self.selectedIndexPath = indexPath;
}
- (void)userTappedBackButton {
// Reload the row that needs to be updated with the new tint color
[tableView reloadRowsAtIndexPaths:#[self.selectedIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Let me know if it worked out.
Keep track of the index path of the tapped cell when it is selected rather than the cell itself, which is reused as you scroll. Apply the selected styling in cellForRow when you're presenting the cell for the matching "selected" index path, in addition to when you return back to the view
Update: adding code to clarify
In your custom cell, provide simple ways to enable/disable the tint:
#interface CustomCell : UITableViewCell
#property(strong, nonatomic) UIImageView *imageView;
#property(strong, nonatomic) UILabel *titleLabel;
- (void)enableLastSelectedHighlight;
- (void)disableLastSelectedHighlight;
#end
Implementation:
#implementation CustomCell
- (void)prepareForReuse
{
[super prepareForReuse];
// Reset prior to being reused
[self disableLastSelectedHighlight];
}
- (void)enableLastSelectedHighlight
{
self.imageView.image = [cell.customImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.imageView.tintColor = [UIColor colorWithRed:0.27 green:0.58 blue:0.98 alpha:1];
}
- (void)disableLastSelectedHighlight;
{
self.imageView.image = [cell.customImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
#end
In your TableViewController.m file, keep track of the selection, either via didSelectRowAtIndexPath, or your existing custom delegate userTappedBackButton. The implementation of the will be the same:
#interface MyTableViewController ()
#property (nonatomic, strong) NSIndexPath *lastSelectedCellIndexPath;
#end
#implementation MyTableViewController
// Your existing implementation
// ...
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Update our reference to the tinted row
[self setLastSelectedCellIndexPath:indexPath];
// Un-tint any currently tinted cells
[self.tableView.visibleCells makeObjectsPerformSelector:#selector(disableLastSelectedHighlight)];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get your cell
CustomCell *cell = (CustomCell *)[self.tableView dequeueReusableCellWithIdentifier:#"CustomCell" forIndexPath:indexPath];
if (indexPath == self.lastSelectedCellIndexPath) {
// This cell should be tinted
[cell enableLastSelectedHighlight];
}
// The rest of your cell setup...
}
#end

Collection View Controller no getter method for read from property

I was following a tutorial on using Collection View Controller and I am stuck on final bit.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MainMenuItemViewCell *myCell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"MainMenuItemCell"
forIndexPath:indexPath];
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:_carImages[row]];
myCell.imageView.image = image;
return myCell;
}
on line myCell.imageView.image = image; I receive an error "no getter method for read from property"
Here is MainMenuItemViewCell.h
#interface MainMenuItemViewCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
#end
I am sure it is something stupid. I am a newbie in iOS programming so please take it into consideration
Thx
ImageView should be imageView (lowercase 'i') in your property declaration.

UICollectionReusableView for section header not working

I created a UICollectionReusuable view for UICollecton view section header. I use the following code the implement the header view.
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
ThemeHeader *headerView = [[ThemeHeader alloc] init];
headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader
withReuseIdentifier:#"header"
forIndexPath:indexPath];
NSString *title = #"Title for the header";
headerView.title.text = title;
return headerView;
}
It crashes giving me the following error:
-[UICollectionReusableView title]: unrecognized selector sent to instance 0xac846a0'
My ThemeHeader class looks like this
#interface ThemeHeader : UICollectionReusableView
#property (strong, nonatomic) IBOutlet UILabel *title;
#end
I appreciate your help in advance.
It means headerView is not an instance of ThemeHeader as you expect but an instance of UICollectionReusableView which does not have a title property.
It could be because you might not have set ThemeHeader as custom class in the identity inspector on storyboard for this resuable view.

Resources