I have custom cell prototype in my storyboard called YesNoTableViewCell. In that cell, I have UITextField.
I want to have the delegate methods of UITextField in my custom cell class.
Here is my code:
MyController
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"YesNoTableViewCell";
YesNoTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[YesNoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
YesNoTableViewCell.m
#interface YesNoTableViewCell : UITableViewCell <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *yesNoInput;
#end
YesNoTableViewCell.h
#import "YesNoTableViewCell.h"
#implementation YesNoTableViewCell
#synthesize yesNoInput = _yesNoInput;
- (id)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_yesNoInput.delegate = self;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
}
But realized this never called:
(id)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)reuseIdentifier
because of:
YesNoTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
never returns nil.
Is there any suggestion for this?
it never return cell nil as you implemented
if (cell == nil){
cell = [[YesNoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
so just remove this code
Related
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'm having a bit confusion with the UITableViewCellStyle. I want to create a custom UITableViewCell like this:
But the text and the image not appear in the cell when I run the app. In Storyboard,I've put the TableView Style to 'Custom'.
What am I doing wrong?
MainTableViewController
#import "MainTableViewController.h"
#import "CustomMainCell.h"
static NSString *CellIdentifier = #"MainCell";
#interface MainTableViewController ()
//
#property(nonatomic, strong) NSArray *dataSource;
//
#property(nonatomic, strong) NSArray *iconsSource;
#end
#implementation MainTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Currículum Vitae";
// Inicializo los arrays con los datos
self.dataSource = #[#"PERFIL",#"EXPERIENCIA",#"EDUCACIÓN",#"HABILIDADES",#"INTERESES"];
self.iconsSource = #[#"perfil.png",#"experiencia.png",#"educacion.png",#"habilidades.png",#"intereses"];
// Register Class for Cell Reuse Identifier
[self.tableView registerClass:[CustomMainCell class] forCellReuseIdentifier:CellIdentifier];
// This will remove extra separators from tableview
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
// Eliminio las líneas que separan las celdas
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomMainCell *cell = (CustomMainCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[CustomMainCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.title.text = self.dataSource[indexPath.row];
cell.icon.image = self.iconsSource[indexPath.row];
return cell;
}
CustomMainCell.h
#interface CustomMainCell : UITableViewCell
//
#property (weak, nonatomic) IBOutlet UILabel *title;
//
#property (weak, nonatomic) IBOutlet UIImageView *icon;
#end
CustomMainCell.m
#import "CustomMainCell.h"
#implementation CustomMainCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.textLabel.textColor = [UIColor brownColor];
}
return self;
}
- (void)awakeFromNib
{
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
You shouldn't have:
// Register Class for Cell Reuse Identifier
[self.tableView registerClass:[CustomMainCell class] forCellReuseIdentifier:CellIdentifier];
because the cell is registered from the storyboard when the view controller is unarchived. By registering the class you are removing the archive (NIB) registration.
Additionally:
if (cell == nil) {
cell = [[CustomMainCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
shouldn't be required as you will always get a valid cell back (because the identifier is registered)
I'm new in iPhone development and have problem with prototype cell.
In my storyboard, I have navigation controller. I pushed it with view controller (as main window), it has a button, when I click it I open tableView controller with custom prototype cell
- (IBAction)searchClick:(id)sender {
CNCarTableController *car = [[CNCarTableController alloc]init];
[self.navigationController pushViewController:car animated:TRUE];
}
But when it opens it has empty rows
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: ( NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TransportCell";
CNTransportCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if(cell == nil){
cell = [[CNTransportCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//cell.textLabel.text = #"bmv";
cell.name = (UILabel*) [cell viewWithTag:100];
[cell.name setText:#"a text"];
cell.number.text = #"number";
cell.car.text = #"car";
return cell;
}
But if will use cell.textLabel.text = #"bmv"; all works ok. But for custom cell way with tags or cell.lbl.text don't work. What is wrong there? Can it be a nuance of navigation controller with view controller?
Custom cell code:
#interface CNTransportCell : UITableViewCell
#property (nonatomic,weak) IBOutlet UILabel *name;
#property (nonatomic,weak) IBOutlet UILabel *number;
#property (nonatomic,weak) IBOutlet UILabel *car;
#end
#implementation CNTransportCell
#synthesize name;
#synthesize number;
#synthesize car;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
you have done small mistake there. Your custom cell class is "CNPlayerCell" & you are allocating new cells from "CNTransportCell" class.
One more thing, have you assigned custom class to your prototype cell in IB? (In identity inspector)
I may be barking up the wrong tree but I'm trying to duplicate functionality I wrote for ios5 in a project thats been updated to ios7.
I've copied and pasted the code across, I get this error
*** Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit/UIKit-2903.23/UITableView.m:5261
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier TableView - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
*** First throw call stack:
(0x30829f4b 0x3ac6a6af 0x30829e25 0x311d1fe3 0x3310891f 0x11bebf 0x330cea5b 0x33076e7d 0x33076699 0x32f9cda3 0x32c23c6b 0x32c1f47b 0x32c1f30d 0x32c1ed1f 0x32c1eb2f 0x32c1885d 0x307f51cd 0x307f2b71 0x307f2eb3 0x3075dc27 0x3075da0b 0x35484283 0x33001049 0x81597 0x7b558)
Everything is the same as another controller where it works except when I examine the xib
Working one:
Crashing one:
The difference being there no Referencing outlet tableCell -> File's Owner
HOW? WHY?
Here's the code just in case
Viewcontroller.h
#import <UIKit/UIKit.h>
#import "blogCellVC.h"
#interface BlogsListingiPhoneVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *blogsListing;
UITableView *tableView;
IBOutlet blogCellVC *tableCell;
}
Viewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIndentifier = #"MyCell";
blogCellVC *cell = (blogCellVC *)[self.tableView dequeueReusableCellWithIdentifier:MyIndentifier forIndexPath:indexPath];
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"blogCellVC" owner:self options:nil];
cell = tableCell;
}
blogsListingModel *info = [_blogsListing objectAtIndex:indexPath.row];
if (info.blogActive == 0)
{
[cell cellHead:info.blogName];
[cell cellHeadCol:[UIColor lightGrayColor]];
[cell cellIcon:#"blank.png"];
}else {
[cell cellHead:info.blogName];
[cell cellHeadCol:[UIColor blackColor]];
[cell cellIcon:#"tick.png"];
}
return cell;
}
Customcell.h
#import <UIKit/UIKit.h>
#interface blogCellVC : UITableViewCell {
IBOutlet UILabel *cellHead;
IBOutlet UIImageView *cellIcon;
}
- (void)cellHead:(NSString *)_text;
- (void)cellIcon:(NSString *)_text;
- (void)cellHeadCol:(UIColor *)aCol;
#end
Customcell.m
#import "blogCellVC.h"
#interface blogCellVC ()
#end
#implementation blogCellVC
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
}
return self;
}
- (void)cellHead:(NSString *)_text {
cellHead.text = _text;
}
- (void)cellHeadCol:(UIColor *)aCol {
cellHead.textColor = aCol;
//cellStandfirst.textColor = aCol;
}
- (void)cellIcon:(NSString *)_text {
cellIcon.image = [UIImage imageNamed:_text];
}
- (void)dealloc {
[super dealloc];
}
#end
PS. I have set the custom class of the File's Owner in the Identity inspector to 'blogCellVC' and the identifier in the attributes inspector to 'MyCell'
I found the solution here:
No Visible View in Custom Table View Cell
In the custom uitableviewcell, in the identity inspector assign the Files Owner's class as the view with the table, and override uitableview cell with your custom class
My mistake as trying to re-use the custom class with a second view.
For completeness' sake, minimum code
parent.h
#import "blogCellVC.h"
#interface BlogsListingiPhoneVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
UITableView *tableView;
IBOutlet blogCellVC *tableCell;
}
parent.m
- (void)viewDidLoad
{
[super viewDidLoad];
[tableView registerClass: [blogCellVC class] forCellReuseIdentifier:#"MyCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIndentifier = #"MyCell";
blogCellVC *cell = (blogCellVC *)[self.tableView dequeueReusableCellWithIdentifier:MyIndentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[blogCellVC alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
[cell cellHead:info.blogName];
[cell cellHeadCol:[UIColor lightGrayColor]];
[cell cellIcon:#"blank.png"];
return cell;
}
blogCellVC.h
#import <UIKit/UIKit.h>
#interface blogCellVC : UITableViewCell {
IBOutlet UILabel *cellHead;
IBOutlet UIImageView *cellIcon;
}
- (void)cellHead:(NSString *)_text;
- (void)cellIcon:(NSString *)_text;
- (void)cellHeadCol:(UIColor *)aCol;
#end
blogCellVC.m
#interface blogCellVC ()
#end
#implementation blogCellVC
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"blogCellVC" owner:self options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
Lastly make sure in the xib/storyboard you've put "MyCell" or whatever in the Identifier field in the Attributes Inspector.
This works in X Code 5, ios7
I would like to programmatically add two text fields to an tableViewCell sub-class (more later) but having difficultly accessing the text-field from the view controller.
My table view sub class is:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
textField = [[UITextField alloc] initWithFrame:CGRectZero];
textField.clearsOnBeginEditing = NO;
textField.textAlignment = UITextAutocapitalizationTypeAllCharacters;
textField.returnKeyType = UIReturnKeyDone;
[self.contentView addSubview:textField];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect rect2 = CGRectMake(100.0, 10.0, 200, 30.0);
textField.text = #"testing";
[textField setFrame:rect2];
}
Within my view controller:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
XTSessionCell_iPad *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[XTSessionCell_iPad alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
// ????
// cell.textField.text = #"enter";
return cell;
}
Any help very much appricatated.
Thanks
As others have mentioned in the comments, make the textView a readonly property in your XTSessionCell_iPad.h file. At a minimum your XTSessionCell_iPad.h file would look like:
#interface XTSessionCell_iPad : UITableViewCell
#property (nonatomic, readonly) UITextField *textField;
#end
And your XTSessionCell_iPad.m file would have a class extension to allow writing to that property:
#interface XTSessionCell_iPad()
#property (nonatomic, readwrite) UITextField *textField;
#end