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
Related
I need some help with a uicollectionview that I've been trying to implement in Objective-C/xcode: I am unable to have the cells appear/populate the collectionview (CV).
Currently I am using the interface builder, and a custom class for cells.
The CV is to be a wide strip that is a single row of square image cells, that can be scrolled/swept through horizontally.
My attempts at implementation result in the wide strip but it never populates with cells.
I have explored other stackoverflow threads similar to this issue, where they discuss the subclassing of cell but I was unable to make it work. Have also tried programmatic implementation and had the same issue. Would really appreciate any insight as I have been stuck at this point for days. Below the code I am using, are screenshots of interface builder showing different settings... some I know are useful to include and I apologize if I have shared anything useless.
from ViewController.h
#interface ViewController : UIViewController <UICollectionViewDelegate,UICollectionViewDataSource>
#property (weak, nonatomic) NSMutableArray *medCollectionCells;
from ViewController.m
#import "CoolCell.h"
#property (weak, nonatomic) IBOutlet UICollectionView *medCollection;
- (void)viewDidLoad
{
_medCollectionCells = [NSMutableArray arrayWithObjects:#"1st cell",#"2nd cell",#"3rd cell",#"4th cell",#"5th cell",#"6th cell",#"7th cell",#"8th cell",#"5th cell", nil];
self.medCollection.delegate = self;
self.medCollection.dataSource = self;
}
// collection view delegate methods
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [_medCollectionCells count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CoolCell *cell = (CoolCell *)[_medCollection dequeueReusableCellWithReuseIdentifier:#"MyCustomCell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor blackColor];
return cell;
}
CoolCell.h:
#import <UIKit/UIKit.h>
#interface CoolCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *customLabel;
#property (weak, nonatomic) IBOutlet UIImageView *customImage;
#end
CoolCell.m:
#import "CoolCell.h"
#implementation CoolCell
#end
Screen Shots
Storyboard layout
Collection View Settings 1
Collection View Settings 2
Cell Settings 1
Cell Settings 2
Interface Builder Outlets
Grateful for any assistance/insight. Thank you.
Seems like the delegate and dataSource properties are connected to a View object in Interface Builder. Maybe remove that since you are setting those properties in code.
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;
}
I can't figure out why my UILabels in my custom TableViewCell are nil in CellForRowAtIndexPath. I used the same method as I did for a previous TableView in another view Controller. Here's what I already checked:
Cell Style is Custom
Cell has a unique identifier "profilecell"
Cell's class is of the desired custom type
data source and delegated are connected to the View Controller
Each of the 5 buttons/labels is connected to its respective property in the custom class
Dynamic Prototypes is selected
I am able to change the background color of the cell and populate the textLabel.text -- it's just my UILabels that aren't filled.
Here is CellForRowAtIndexPath. It's the exact same method as my other TableVC, which works. Also, I don't need to actually reuse this custom cell, should I be using a different method?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifierProfile = #"profilecell";
ProfileSection0TableViewCell *profilecell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierProfile];
if (profilecell == nil) {
profilecell = [[ProfileSection0TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifierProfile];
}
if (indexPath.section == 0) {
[profilecell setBackgroundColor:[UIColor colorWithRed:54/255.0f green:61/255.0f blue:147/255.0f alpha:1.0f]];
if (indexPath.row == 0) {
profilecell.labelName.text = _userProfile.fullName;
NSString *test = [NSString stringWithFormat:#"%#", profilecell.labelName.text];
NSLog(#"text %#", test); //shows that label is (null)
profilecell.labelName.textColor = [UIColor whiteColor];
//profilecell.labelSpecialty.text = _userProfile.specialty;
//profilecell.labelSpecialty.textColor = [UIColor whiteColor];
}
}
return profilecell;
}
Thanks so much in advance.
.h file:
#interface ProfileSection0TableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel* labelName;
#property (nonatomic, weak) IBOutlet UILabel* labelSpecialty;
#property (nonatomic, weak ) IBOutlet UILabel* labelCurrentRole;
#property (nonatomic, weak) IBOutlet UILabel* labelPosition;
#property (nonatomic, weak) IBOutlet UIButton* facePicture;
#end
.m file:
#implementation ProfileSection0TableViewCell
#synthesize labelName, labelSpecialty, labelPosition, facePicture, labelCurrentRole;
#end
EDIT:
It looks like ProfileSection0TableViewCell is allocated properly, but the member vars inside the cell are nil. And in outlets, here are the connections:
facePicture - Button
labelName- UILabel "person"
labelPosition - UILabel "position"
List item - UILabel "specialty"
labelCurrentRole - UILabel titled school
Either _userProfile.fullName is nil or profilecell.labelName is nil
If you made the cell in interface builder, did you hook up the outlet to labelName correctly?
I have designed a cell in storyboard, then created a custom UITableViewCell subclass (BasicCell) and assigned it to it. Also set the proper identifiers. I created outlets of the custom cell in that class. Then in my UITableViewController subclass (where I have two types of prototype cells), the cells content won't show up. What am I doing wrong?
BasicCell.h
#interface BasicCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *scorevalue;
#property (strong, nonatomic) IBOutlet UILabel *avgvalue;
#property (strong, nonatomic) IBOutlet UILabel *rankvalue;
#property (strong, nonatomic) IBOutlet UILabel *scorelabel;
#property (strong, nonatomic) IBOutlet UILabel *categorylabel;
#property (strong, nonatomic) IBOutlet UILabel *ranklabel;
#end
TableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifierBasic = #"basic";
static NSString *CellIdentifierDetailed = #"detailed";
UITableViewCell *cell;
if(indexPath.row==0){
// Create first cell
cell = [[BasicCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierBasic];
}
else{
// Create all others
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierDetailed forIndexPath:indexPath];
}
// Configure the cell...
switch ([indexPath row])
{
case 0:
{
BasicCell *basicCell = (BasicCell *)cell;
basicCell.scorelabel.text = #"test";
basicCell.categorylabel.text = #"test";
basicCell.ranklabel.text = #"test";
basicCell.scorevalue.text = #"test";
basicCell.avgvalue.text = #"test";
basicCell.rankvalue.text = #"test";
}
}
In your storyboard,
Create two prototype cell.
Change one of your prototype cell's custom class. Set it BasicCell.
Make sure that you set appropriate cell identifier for each type of cell.
Don't alloc init if it's indexPath.row == 0 but dequeue with appropriate identifier.
It should work.
Note: You should declare your IBOutlets as weak not as strong. Cell's view has already strong pointer to them. You don't have to own them.
I've read quite a few tutorials online about how to create a custom cell subclass, but I'm still a little confused. When I try to follow the instructions found in this question, I end up with errors that the tableView is not a valid property for the object of ViewController.
I've created a new subclass of UITableViewCell, called CustomBookClass. I've hooked up the properties with my CustomBookClass.h file.
#import <UIKit/UIKit.h>
#interface CustomBookCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *bookImage;
#property (weak, nonatomic) IBOutlet UILabel *bookTitle;
#property (weak, nonatomic) IBOutlet UILabel *dateAdded;
#end
I then go into my ViewController.m file to edit the viewDidLoad method.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView.delegate = self];
[self.tableView.dataSource=self];
[self.tableView registerClass:[CustomBookCell class]forCellReuseIdentifier:#"Custom
Cell"];
}
I get an error on the tableView, saying the property doesn't exist, even though in the ViewController.h file, I'm including the table view.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
#end
I'm sure I'm missing something really obvious here, as this is my first time trying this. Can anyone help me out? Thanks!
UIViewController does not have that property. Even if you assign the Delegate and DataSource protocols to it. There are a couple of things you can do however.
Link the table view to the ViewController yourself. That means, create a property/outlet called tableView.
Inherit from UITableViewController instead of UIViewController.
Both should work.
Edit: Oh and the lines:
[self.tableView.delegate = self];
[self.tableView.dataSource=self];
don't make sense. They should be either:
self.tableView.delegate = self; and self.tableView.dataSource = self;
Or [self.tableView setDelegate:self]; and [self.tableView setDataSource:self]
with 1 being preferred. (Edit: option #2 was actually incorrect code, my bad.)
No need to set delegate and datasource in TableViewCell class
simple make a property and synthesize your table view item
#property (weak, nonatomic) IBOutlet UIImageView *bookImage;
#property (weak, nonatomic) IBOutlet UILabel *bookTitle;
#property (weak, nonatomic) IBOutlet UILabel *dateAdded;
now import your cell class in your tableView controller class
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
//If you are using xib for representing your UI then add a nib file.
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.bookTitle.text = [tableData objectAtIndex:indexPath.row];
cell.bookImage.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.dateAdded.text = [prepTime objectAtIndex:indexPath.row];
return cell;
}
for more detail check this link