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;
}
Related
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 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.
I'm developing application.
I make a custom UITableViewCell.
But I can't get custom tableviewcell's contents.
For example, here's my custom UITableViewCell's image.
TextEditorCell.h
...
#property (weak, nonatomic) IBOutlet UITextField *textField;
...
AddNewObject.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
_textEditor = [tableView dequeueReusableCellWithIdentifier:#"Text"];
_datePicker = [tableView dequeueReusableCellWithIdentifier:#"Date"];
SwitchCell *_switch = [tableView dequeueReusableCellWithIdentifier:#"Switch"];
// Configure the cell...
if (indexPath.section == 0) {
return _textEditor;
}else if (indexPath.section == 1){
return _datePicker;
}else{
_switch.titleLabel.text = #"Main Countdown";
return _switch;
}
return nil;
}
...
- (IBAction)Done:(id)sender
{
NSLog(#"Text:%#",_textEditor.textField.text);
}
Log
2013-12-27 23:47:58.498 Application[10039:80b] Text:(null)
I wrote a sentence.
But log is null.
why?
Cell is a View and it shouldn't store any data. I assume that your IBAction is inside your custom cell class. So if you want to pass the parameters in there (even on the same class) you have to unfortunately set your property to strong:
#property (strong, nonatomic) IBOutlet UITextField *textField;
I solved my own question.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
TextEditorCell *cell = (TextEditorCell*)[self.tableView cellForRowAtIndexPath:indexPath];
NSString *text = cell.textField.text;
NSLog(#"Text:%#",text);
I thank every answerer!!!
I have created a subclass of UITableViewCell and I called it DCCustomCell. This is the DCCustomCell.h file.
#import <UIKit/UIKit.h>
#interface DCCustomCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UILabel *title;
#property (weak, nonatomic) IBOutlet UILabel *date;
#property (weak, nonatomic) IBOutlet UILabel *price;
#end
All the proprieties are correcty connected with elements in my iPhone.storyboard file.
I also selected the tableViewCell in iPhone.storyboard and i setted my cell's identifier to "CustomCell" and the class to DCCustomCell.
This is the UITableViewController's viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.tableView registerClass:[DCCustomCell class] forCellReuseIdentifier:#"CustomCell"];
// Do any additional setup after loading the view, typically from a nib.
}
and this is the tableView:cellForRowAtIndexPath: method:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CustomCell";
DCCustomCell *cell = (DCCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
NSLog(#"%#" ,cell);
cell.imageView.image = [UIImage imageNamed:#"info_button.png"];
cell.title.text = #"Hello!";
cell.date.text = #"21/12/2013";
cell.price.text = #"€15.00";
return cell;
}
The problem is that the imageView is correctly setted, but all the labels are blank. If I change the imageView property name to, for example, eventImageView, the image will not be setted.
This is the result:
I can't figure out how I can solve this problem.
EDIT: if I remove
[self.tableView registerClass:[DCCustomCell class] forCellReuseIdentifier:#"CustomCell"];
from viewDidLoad all seems to work. why?
As you noticed it works when you remove
[self.tableView registerClass:[DCCustomCell class] forCellReuseIdentifier:#"CustomCell"];
You only have to do this if you use dequeueReusableCellWithIdentifier:indexPath: AND have not already set the custom class in the identity inspector for that cell. If you use registerClass: forCellReuseIdentifier the cell will be initialized with initWithStyle:reuseIdentifier: instead of initWithCoder: thus screwing up your connections you made in the storyboard.
Have you bind the Controls to IBOutlet ?
You can try setting DCCustomCell to UITableviewCell's class directly in Storyboard.
And than you need to set outlets with controls in cell
Try:
if (cell == null) {
//create and initialize cell
}
after
DCCustomCell *cell = (DCCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
You first check your outlets properly that all the labels are connected & write this also :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CustomCell";
DCCustomCell *cell = (DCCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"DCCustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSLog(#"%#" ,cell);
cell.imageView.image = [UIImage imageNamed:#"info_button.png"];
cell.title.text = #"Hello!";
cell.date.text = #"21/12/2013";
cell.price.text = #"€15.00";
return cell;
}