Let's say i have created myTableViewCell class:
#import "MyTableViewCell.h"
#implementation MyTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
UIImageView *imgSponsor=[[UIImageView alloc ] initWithFrame:CGRectMake(0,0,self.bounds.size.width,200)];
imgSponsor.image = [UIImage imageNamed:#"imageFirstCell"];
[self.contentView addSubview:imgSponsor];
}
return self;
}
[...]
#end
Can I set a default height for this cell from within this class apart from running through the associated tableviewcontroller method (heightForRowAtIndexPath..)?
You can use like in MyTableViewCell.h-
-(void)layoutSubviews {
self.frame = //Define your frame;
[super layoutSubviews];
}
Related
I have made a UITableViewCell with xib, inside it I have made a UIView and made IBoutlet in my custom tableViewCell class. I want to set the border color of that UIView.
My code in tableViewCell.h:
#property (weak, nonatomic) IBOutlet UIView *circleView;
In tableViewCell.m:
#import "OUSTProfileTableViewCell.h"
#implementation OUSTProfileTableViewCell
//#synthesize circleView = _circleView;
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
self.circleView.layer.cornerRadius = 3; // this value vary as per your desire
self.circleView.layer.masksToBounds = YES;
self.circleView.layer.borderWidth = 2.0;
self.circleView.layer.borderColor = (__bridge CGColorRef _Nullable)([UIColor lightGrayColor]);
}
return self;
}
#end
But it's not working.
Put code inside
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
self.circleView.layer.cornerRadius = 3; // this value vary as per your desire
self.circleView.layer.masksToBounds = YES;
self.circleView.layer.borderWidth = 2.0;
self.circleView.layer.borderColor = [UIColor lightGrayColor].CGColor;
}
I'm creating a couple of UIButtons programmatically in a UITableViewCell, and setting its frame in layoutSubviews. I am also setting the selected state here as well.
However, it seems this is not the best place to either create, nor initialize the state of the buttons because layoutSubviews is called multiple times. Where can I put the following code such that the frame will be correct, but it will only be initialized once?
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width / 2.0, self.frame.size.height)];
button.selected = YES
One idea I have is to initialize all the one-time setup in awakeFromNib, then do the actual frame setting in layoutSubviews. Is that a good approach?
If you are using NIB file for your custom UITableViewCell class then awakeFromNib is the method where you should initialize your UIElements, class properties and other instance variables of your UITableViewCell class.
Else if you are using a custom UITableViewCell class without a NIB then you should initialize everything in
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialize your frames here
}
return self;
}
Now if you want to update your cell with different button states or data, then you just call a method in your cell from the
- tableView:cellForRowAtIndexPath:
and change whatever you want to for that particular cell.
Ex:
- tableView:(UITableView *)tableView cellForRowAtIndecPath:(NSIndexPath *)indexPath {
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
[cell someMethod];
return cell;
}
I would recommend placing it in the
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
and using Autolayout for button placement. I'll show you how using Masonry for Autolayout to save on lines.
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIButton *button = [UIButton new];
button.selected = YES;
// Add button to self
[self addSubview:button];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_top);
make.left.equalTo(self.mas_left);
make.width.mas_equalTo(self.view.frame.size.width/2);
make.height.equalTo(self.mas_height);
}
}
return self;
}
I have a custom cell that I have made in the iterfacebuilder and connected to my .h file.
And then in my CustomCell.m file I have
#implementation TwoMealsTableViewCell
#synthesize dayLabel, firstMealBtn, secondMealBtn, indexPath;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
dayLabel.textColor = [UIColor orangeColor];
if (self) {
dayLabel.textColor = [UIColor orangeColor];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
And I have the cell all set up in the tableview, and I see the buttons, and labels, but I don't see the color change?
Why is this.
Thanks for the help in advance!!!
This will change the cell color
dayLabel.textColor = [UIColor orangeColor];
I have class hierachy with
ParentCell extends UITableViewCell
ChildCell extends ParentCell
ParentCell have separate XIB, In child cell i was creating and adding only one button to one view at ParentCell XIB. but i cant add action for this button. Because even i was creating a instance for ChildCell, that returns the instance of ParentCell
Because i use loadNibNamed to get the XIB with IBOutlet connections.
# initWithStyle method in ParentCell Class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self = [[NSBundle mainBundle] loadNibNamed:#"ParentCell" owner:self options:nil]
[0];
}
return self;
}
# initWithStyle method in ChildCell Class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.button=[[UIButton alloc] init];
[self.contentView addSubview:button];
}
return self;
}
# View Controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ChildCell ";
ChildCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell=[[ChildCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSLog(#"Cell : %#", cell); //this have instance of ParentCell instead of ChildCell
}
}
Now temporarily solved by this way
# initWithStyle method in ParentCell Class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSBundle *mainBundle = [NSBundle mainBundle];
NSArray *views = [mainBundle loadNibNamed:#"ParentCell"
owner:self
options:nil];
//Here we are linking the view with appropriate IBOutlet by their tag
self.lblTitle=[views[0] viewWithTag:100];
self.lblContent=[views[0] viewWithTag:200];
}
return self;
}
# initWithStyle method in ChildCell Class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.button=[[UIButton alloc] init];
[self.contentView addSubview:button];
}
return self;
}
But i don't know this is right approach to follow, or we have some other better approach then this..
You should use the registerNib:forCellReuseIdentifier: method at the viewDidLoad of you UITableView class.
static NSString *parentCellIdentifier = #"parentCellIdentifier";
static NSString *childCellIdentifier = #"childCellIdentifier";
[self.tableView registerNib:[UINib nibWithNibName:#"ParentCell" bundle:nil] forCellReuseIdentifier:parentCellIdentifier];
[self.tableView registerNib:[UINib nibWithNibName:#"ChildCell" bundle:nil] forCellReuseIdentifier:childCellIdentifier];
(Don't forget to set the appropriate ReuseIdentifier at the XIB file)
This is the best practice, and you can get rid of your initWithStyle implementations.
I am not sure if this is a Storyboard Bug. I have created a project with a custom cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"HomeGameTurnCell";
HomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[HomeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
The custom cell has some image views. One of the image views is a subclass.
#interface HomeTableViewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet RoundedProfilePicture *profilePictureImageView;
#property (strong, nonatomic) IBOutlet UIImageView *turnThumbnailImage;
#property (strong, nonatomic) IBOutlet UILabel *usernameLabel;
#property (strong, nonatomic) IBOutlet UILabel *lastPlayedLabel;
#end
The RoundedProfilePicture subclass simply has the following:
-(id)init {
NSLog(#"%s",__PRETTY_FUNCTION__);
self = [super init];
if (self) {
[self setupView];
}
return self;
}
- (void)setupView
{
NSLog(#"%s",__PRETTY_FUNCTION__);
self.clipsToBounds = YES;
self.layer.cornerRadius = self.bounds.size.width / 2;
self.layer.borderWidth = 3;
self.layer.borderColor = [UIColor darkGrayColor].CGColor;
}
What I am finding is that the RoundedProfilePicture methods are not being called. Within the storyboard I have setup one prototype cell and the correct identifier. I also have the image view set as the correct Custom class. But it doesn't seem to take effect, is there something I am missing/could check?
When you are reusing an element you should override UITableViewCell method:
-(void)prepareForReuse
instead of init. It will called each time.
If you want one time initialization you should do it in: initWithStyle:reuseIdentifier:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//do your stuff here
}
return self;
}
From apple docs:
If you registered a class for the specified identifier and a new cell must be created, this method initializes the cell by calling its initWithStyle:reuseIdentifier: method. For nib-based cells, this method loads the cell object from the provided nib file. If an existing cell was available for reuse, this method calls the cell’s prepareForReuse method instead.
The issue is that when a UIimageView is subclassed and called from the storyboard a different method is called for the init.
-(id)initWithCoder:(NSCoder *)aDecoder {
// As the subclassed UIImageView class is called from storyboard the initWithCoder is overwritten instead of init
NSLog(#"%s",__PRETTY_FUNCTION__);
self = [super initWithCoder:aDecoder];
if (self) {
[self setupView];
}
return self;
}
This resolves the issue of the rounded profile view not being called.