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.
Related
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 implemented a UICollectionView inside a UIViewController. The header cell is created in a separate.xib file and it is implemented in a separate .h and .m files with the IBOutlets and IBActions. The rest of the cells are implemented in the same UIVIewController (The reason is because I added this Parallax effect).
I would like to modify the info of the IBoutlets (labels and buttons) that are in the header cell (CSCellUser.h) from the viewcontroller (RankingViewController) which containts the collectionview, how can I do this?
Cell: CSCellUser.h
#interface CSCellUser : UICollectionViewCell
#property IBOutlet UILabel *myScoreValueLabel;
#property IBOutlet UILabel *myRankingValueLabel;
-(IBAction) sendButtonTouchHandler:(id) sender;
#end
UIViewController: RankingViewController.h
#interface RankingViewController : CommonViewController <UICollectionViewDelegate, UICollectionViewDataSource> {
}
#property IBOutlet UICollectionView *collectionView1;
#end
UIViewController:RankingViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
//Parallax Effect, UICollectionView
// Locate the layout
CSStickyHeaderFlowLayout *layout = (id)self.collectionView1.collectionViewLayout;
if ([layout isKindOfClass:[CSStickyHeaderFlowLayout class]]) {
layout.parallaxHeaderReferenceSize = CGSizeMake(320, 220);
layout.parallaxHeaderAlwaysOnTop = YES;
}
// Locate the nib and register it to your collection view
UINib *headerNib = [UINib nibWithNibName:#"CSHeaderRanking" bundle:nil];
[self.collectionView1 registerNib:headerNib
forSupplementaryViewOfKind:CSStickyHeaderParallaxHeader
withReuseIdentifier:#"TopViewCell"];
//get the position of the user and the ranking (this should update the IBOutlets in the CSCellUser.h)
[self getUserRanking];
//get the ranking of users (this updates each cell of the ranking in cellForItemAtIndexPath)
[self getRanking];
}
- (NSInteger) numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger) collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [ranking count];
}
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: #"UsersCell" forIndexPath:indexPath];
if ([ranking count] > 0)
{
UserRanking *user = [ranking objectAtIndex:indexPath.row]; //Fill the cell
UILabel *usernameLabel = (UILabel *)[cell viewWithTag:101];
usernameLabel.text = user.username;
UILabel *scoreLabel = (UILabel *)[cell viewWithTag:102];
scoreLabel.text = [NSString stringWithFormat:#"%d", user.score];
UILabel *gamesLabel = (UILabel *)[cell viewWithTag:103];
gamesLabel.text =[NSString stringWithFormat:#"%d", user.tries];
}
return cell;
}
//Header
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableview = nil;
if ([kind isEqualToString:CSStickyHeaderParallaxHeader]) {
reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:#"TopViewCell" forIndexPath:indexPath];
}
return reusableview;
}
EDIT:
This is how I am trying to change one of the labels from cellForRowAtIndexPath but it does not change.
CSHeaderRanking *topcell = [collectionView dequeueReusableCellWithReuseIdentifier: #"TopCell" forIndexPath:indexPath];
topcell.myScoreValueLabel.text = #"32";
If TopCell is mapped in its xib, all you have to do is refer to its properties. If you want to customize, you'll need to over-ride the CCSticky... and refer to it in your xib and this class.
I have noticed that UITableViewCell is not reusing it's subviews and seems to be released when scrolling up and down. I am creating UITableViewCell subview and animating it on viewDidAppear. I want to do this only once and then I expect subview to stay in the ContentView forever until view disappears. So I have done following which I think right way but not sure what's wrong; can someone help?
UINib *nib1 = [UINib nibWithNibName:#"CustomCell" bundle:nil];
[self.tableView registerNib:nib1 forCellReuseIdentifier:#"CustomCell"];
#interface CustomCell : UITableViewCell
#property (nonatomic) IBOutlet UILabel *title;
#property (nonatomic) CustomeView *customeView;
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString cellIdentifier = #"CustomCell";
CustomCell *customCell = [tableView dequeueReusableCellWithIdentifier:accountCellIdentifier forIndexPath:indexPath];
......
customCell.customeView = (CustomeView*)[customCell.contentView viewWithTag:101];
if(!customCell.customeView) {
customCell.customeView = [CustomeView new];
//configure customview...
customCell.customeView.tag = 101;
[customCell.contentView addSubview:customCell.customeView];
}
return cell;
}
Try to change your property type to strong:
#property (strong, nonatomic) CustomeView *customeView;
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.