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.
Related
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
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
This question applies to tableViews and to collectionViews.
Lets talk about a collection view using a prototype cell.
Suppose the prototype cell is assigned to MyCollectionViewCell class.
Suppose that this class has two properties: countryName and countryImage (a label and a imageView, respectively).
Why I cannot assign values for name and country during this method? and what is the best way to solve that?
During this method...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
NSArray *section = self.arrayData[indexPath.section];
NSDictionary *itemOnSection = section[indexPath.row];
// Configure the cell
UIImage *image = [UIImage imageNamed:itemOnSection[#"image"]];
NSString *name = itemOnSection[#"name"];
cell.countryImage.image = image;
cell.countryName.text = name;
return cell;
}
what will happen with this method is that cell will be a valid object but cell.countryImage and cell.countryName will be nil.
what I don't understand is this: if the cell exists and is a valid object according to the debugger, why its elements are not initialized. What is the best way to solve that?
this is MyCollectionViewCell.h
#interface MyCollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *countryImage;
#property (weak, nonatomic) IBOutlet UILabel *countryName;
#end
the outlets are connected to the elements on the prototype cell and the prototype cell has this class assigned.
MyCollectionViewCell.m has nothing.
How are you registering views to be used by the collection view?
If you want to use a cell defined in a nib/xib, you will have to:
registerNib:forCellWithReuseIdentifier:
as opposed to
registerClass:forCellWithReuseIdentifier:
This should then ensure the cell sets up any outlets :)
In the UICollectionView documentations is section about the cell.
According to the cell:
Return Value The cell object at the corresponding index path or nil if
the cell is not visible or indexPath is out of range.
Probably you have problem of setting resource in
MyCollectionViewCell
Firstly create property in you're cell
#property (nonatomic, retain) NSString *countryNameTitle;
Than method to set name
//method to set name that should be called from cellForItemAtIndexPath
-(void)setCountryName
{
if ([countryNameTitle length] != 0)
{
countryName.text = countryNameTitle;
}
}
And than set name from delegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
NSArray *section = self.arrayData[indexPath.section];
NSDictionary *itemOnSection = section[indexPath.row];
// Configure the cell
UIImage *image = [UIImage imageNamed:itemOnSection[#"image"]];
NSString *name = itemOnSection[#"name"];
cell.countryImage.image = image;
cell.countryNameTitle = name;
[cell setCountryName];
return cell;
}
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
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.