How to set a UILabel in UICollectionViewCell - ios

I have an app with a UIViewController with a UICollectionView IBOutlet in it.
The cell in the UICollectionView is MyCustomCell and has this method setting its UILabel:
-(void)setCellLabel:(NSString *)value{
NSLog(#"settinglabel");
cellLabel.text = #"hardcode"; //added for testing purposes
}
The cell has the property Class type identifying it as MyCustomCell in storyboard and its dequeue identifier as well. The UIViewController adopts the datasource and delegate protocols. The IBOutlet UILabel has its cellLabel outlet connected to the storyboard. The methods are defined as:
- (void)viewDidLoad{
[super viewDidLoad];
self.restNames = #[#"Orange",#"Naranja",#"Narnia"];
[self.collectionView registerClass:[MyCustomCell class] forCellWithReuseIdentifier:#"MyCustomCellID"];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
NSLog(#"%d",[self.restNames count]);
return [self.restNames count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
MyCustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
[cell setCellLabel:#"hi"];
NSLog(#"fitsname %#",[self.restNames objectAtIndex:indexPath.row]);
return cell;
}
I get three cells drawn in my tableview, corresponding to the 3 objects in my array. The array simply contains string objects which I was setting directly by objectAtIndexPath but I decided to set it directly to #"hi" since it wasn't working. I even changed the value used in setCellLabel method to a hardcoded value and I keep get just the "Label" default string in each cell.
Why isnt the cellLabel being set properly?

Do you have your cellLabel outlet set in interface builder?
You should have something like this in your cell's .h file:
#property (weak, nonatomic) IBOutlet UILabel *cellLabel;
then later you really just need to do this:
cell.cellLabel.text = #"";

When you're using Storyboard, the default template is wrong, because it uses the line
[self.collectionView registerClass:[UICollectionView class] forCellWithReuseIdentifier:CellIdentifier];
But the storyboard already registered it. So basically this is what you have to do to create a custom, storyboard based UICollectionView :
Create your UICollectionViewController subclass
Click&drag a UICollectionViewController to the storyboard and change the configuration as you want
Create a UICollectionViewCell subclass
Set the cell class in the storyboard, set it's reuse identifier ctrl-drag the needed outlets
Remove the [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier: CellIdentifier];
Set the static reuse identifier in the UICollectionView subclass

You have probably forgotten to tell your UICollectionView what class it’s supposed to use to create cells. This is done with the following line of code:
[self.collectionView registerClass:[MyCustomCell class] forCellWithReuseIdentifier: CellIdentifier];
You can set this at the end of the viewDidLoad of your controller.

Related

Subclassing custom UICollectionViewCell

I've succesfully created custom UICollectionViewCell that has 3 labels.
Now I want to subclass it, add dateToDisplay property and in setDateToDisplay change labels's strings (with custom date formatters).
Creation and usage of parentCell:
ParentCellIdentifier.h
static NSString *ParentCellIdentifier = #"ParentCellIdentifier";
#interface ParentCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UILabel *firstLabel;
#property (strong, nonatomic) IBOutlet UILabel *secondLabel;
#property (strong, nonatomic) IBOutlet UILabel *thirdLabel;
-(void)setupDefaults;
#end
In parentCell.xib:
Class set to ParentCell and Identifier set to ParentCellIdentifier
In ViewController I have UICollectionView:
-(void)setupCollectionView {
[_daysCollectionView registerNib:[UINib nibWithNibName:#"ParentCell" bundle:nil] forCellWithReuseIdentifier:ParentCellIdentifier];
_daysCollectionView.delegate = self;
_daysCollectionView.dataSource = self;
_daysCollectionView.backgroundColor = [UIColor clearColor];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ParentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ParentCellIdentifier forIndexPath:indexPath];
cell.firstLabel.text = #"first";
cell.secondLabel.text = #"second";
}
The setup above worked like a charm.
No I want to add ChildCell, using same xib as previously:
#interface ChildCell : ParentCell
#property (nonatomic, strong) NSDate* dateToDislpay;//labels of parentCell updated using dateformatters on setDateToDisplay:
#end
-(void)setupCollectionView left the same, registering ParentCell.xib for ParentCellIdentifier
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ChildCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ParentCellIdentifier forIndexPath:indexPath];
NSDate* date = [_dates objectAtIndex:indexPath.row];
cell.dateToDislpay = date; //here goes the error
When trying to set property of child cell, it crashes. It's correct, because in ParentCell.xib class of the cell is ParentCell.
After changing the class in xib, it works, but I want to stick with my parent class in xib, since I will use the same xib, but with different formatters only.
How can I do it?
EDIT1:
crash received:
-[ParentCell setDateToDislpay:]: unrecognized selector sent to instance
You need to go into the xib file and change the class type to ChildCell and that should fix your crash.
To subclass see here: https://stackoverflow.com/a/5056886/848719
You'll have to override initWithFrame: and awakeFromNib.
You got crash because you have register [UINib nibWithNibName:#"ParentCell" bundle:nil] Parent Cell and in cell for item you are create object of ChildCell , but it is parent cell not child cell
and parent cell does not have dateToDislpay property .
you can check same with print class
you are doing inheritance wrong way, you should read some tutorial or read some demos

iOS: dequeueReusableCellWithIdentifier returning cell with IBOutlets that are nil

I have a custom UITableViewCell with one view defined in a XIB file:
#interface MetroTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *metroLineName;
#end
I am dequeuing the cell as such:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MetroTableViewCell *cell = (MetroTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"MetroTableViewCell" forIndexPath:indexPath];
// AT THIS POINT, cell.metroLineName is equal to nil
return cell;
}
The class is being registered with the table view:
[self.tableView registerClass:[MetroTableViewCell class]
forCellReuseIdentifier:#"MetroTableViewCell"];
In the XIB file, I am also setting the class to "MetroTableViewCell"
So why is the IBOutlet set to nil?
NOTE: This problem does NOT occur when I use:
MetroTableViewCell *cell = [[[NSBundle mainBundle] loadNibNamed:#"MetroTableViewCell"
owner:self options:nil]
objectAtIndex:0];
Because you create a xib show you need registerNib not class. If you create custom cell with no xib, you will use registerClass.
So you should change this code:
[self.tableView registerClass:[MetroTableViewCell class]
forCellReuseIdentifier:#"MetroTableViewCell"];
To:
[self.tableView registerNib:[UINib nibWithNibName:#"MetroTableViewCell" bundle:nil] forCellReuseIdentifier:#"MetroTableViewCell"];
Hope this help!
Using registerClass:forReuseIdentifier: doesn't use a NIB to create the cell. It simply creates a new instance of the given class.
You want to use registerNib:forReuseIdentifier:
Instead of this:
[self.tableView registerClass:[MetroTableViewCell class]
forCellReuseIdentifier:#"MetroTableViewCell"];
use:
[self.tableView registerNib:[UINib nibWithNibName:#"MetroTableViewCell" bundle: nil]
forCellReuseIdentifier:#"MetroTableViewCell"];

How to use custom UICollectionViewCell within Storyboard?

I don't understand why the custom cell is not recognised in the Storyboard.
TNTopStoriesCollectionViewController:
static NSString * const reuseIdentifier = #"TNTopNewsCellItem";
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
TNTopStoriesCollectionViewCell *cell = (TNTopStoriesCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
[self preLoadImagesForCategory:_dataStore.fiveTopStories[indexPath.item] andImageView:cell.itemImage];
return cell;
}
I'm using a storyboard for the collectionView:
And the cell is also correctly pointing to the custom class:
#import <UIKit/UIKit.h>
#interface TNTopStoriesCollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *itemImage;
#property (weak, nonatomic) IBOutlet UILabel *title;
#end
And the correct cell identifier is also used:
And yet I get this exception within cellForItemAtIndexPath method:
[UICollectionViewCell itemImage]: unrecognized selector sent to instance
But why please?
Update:
I did everything as suggested and am now getting this:
However it still fails at the same spot. :(
The fact that this cell is called "Collection View Cell" on the left, in the hierarchical name listing of objects in the scene, and has not changed to "Top Stories Collection View Cell" suggests that you have not actually changed its class in the storyboard to TNTopStoriesCollectionViewCell successfully.
(Notice how the collection view controller is listed on the left as Top Stories Collection View Controller. The same kind of thing should have happened to the cell.)
What you see on the left should look more like this:
(Also, the fact that your label outlet is called News Label on the left is suggestive of a problem, since in code this label is called "title", and if you've hooked that up correctly I'd expect Xcode to have changed its name to "title" in the listing on the left as well.)
[I have a vague feeling that you may actually have two classes, TNTopStoriesCollectionViewCell and TNTopNewsCellItem, and you've confused yourself about them...]
In storyboard, there is another way to create Custom
CollectionViewCell.That is Separately create the new
file(CustomCellCollectionViewCell.h,CustomCollectionViewCell.m and
CustomCollectionViewCell.xib) through the IOS->Source->Cocoa Touch
Class->SubClass of UICollectionViewCell and give name in Class. After
that you can import the the .h of CustomCollectionViewCell and also
you need to register that in viewDidLoad.
- (void)viewDidLoad
{
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
UINib *cellNib = [UINib nibWithNibName:#"CustomCollectionViewCell" bundle:nil];
[collectionViewSelection registerNib:cellNib forCellWithReuseIdentifier:#"customCollectionCell"];
}
Then
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"customCollectionCell";
CustomCollectionViewCell *cell = (CustomCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}

UITableViewCell with xib

I'm developing an app for iOS which use the xib files.
Usually I use Storyboard and I don't know how to set up a UITableViewCell with xib files. When I make a xib file with a UITableView, I see a table with some row, now I need to edit this row to write what I stored in an array.
How can I use the xib file to design a UITableViewCell?
I need to do a very simple table: I would to use the Basic preset for the cell to display a title.
I know that I've to connect the delegate and DataSource to the file owner for table view and I put in the file owner the UITableViewDelegate and UITableViewDataSource.
Now how I can edit the content of the cell?
I found on the web some guide that tells to create a xib file with a UITableViewCell and I did it, but I don't know how to work with this
Firstly, you need to create the class for the customCell which inherits from UITableViewCell.
Now, add the properties you want to have in your customCell. In this example I added cellImage and cellLabel.
#property (nonatomic, strong) IBOutlet UILabel *cellLabel;
#property (nonatomic, strong) IBOutlet UIImageView *cellImageView;
After that you need to link the UILabel and the UIImageView from the CustomCell to the Nib.
You need to add:
- (void)viewDidLoad
{
....
[self.tableView registerNib:[UINib nibWithNibName:#"xibName" bundle:nil] forCellReuseIdentifier:CellIdentifier];
.....
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCellReuse";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
[cell.cellImageView setImage:[UIImage imageNamed:#"whatever"]];
[cell.cellLabel setText = #"whatever"];
return cell;
}

Style UITableViewCell inside UIScrollView/UIView

Overview
I've added a UITableView inside a UIScrollView using the storyboard.
My simple goal is to style the UITableViewCell's inside this table view.
Code
Currently, I have added a UITableView property to the view controller and added the outlet in the storyboard.
#interface NWDetailViewController : UIViewController<UITableViewDelegate,
UITableViewDataSource> {
IBOutlet UIScrollView *scrollView;
...
IBOutlet UITableView *tableView;
IBOutlet NSLayoutConstraint *tableViewHeightConstraint;
}
Created a custom UITableViewCell (NWLocationTableViewCell), added a property and connected the outlet in the storyboard:
#interface NWLocationTableViewCell : UITableViewCell {
IBOutlet UILabel *titleLabel;
}
And this is how i'm trying to populate the cell in my Controller:
-(UITableViewCell *)tableView:(UITableView *)thisTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"LocationCell";
// Same with both tableView and thisTableView
NWLocationTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[NWLocationTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
[cell.titleLabel setText:#"test"];
// or
UILabel *label = (UILabel *)[cell.contentView viewWithTag:2112];
[label setText:#"test"];
NSLog(#"%#, %#", cell.contentView.subviews, cell.class);
return cell;
}
But both methods yield nothing, hence I can't style it. Adding any static objects (UIButton for example) also don't show up.
The logs show: "(), NWLocationTableViewCell"
Its a naming problem.
in your method header you pass thisTableView as the tableView to use, but then you call [tableView dequeueReusableCellWithIdentifier]; to get a cell. It should generate an error, but probably there is another variable by that name, or a property? Anyways, if thats your verbatim code, theres your error.

Resources