I want to display a list of data on "UITableView".
When I run the code I get the following error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:
'unable to dequeue a cell with identifier Cell - must register a nib or a class for the
identifier or connect a prototype cell in a storyboard'
I get the error given above when I run the code below. The error is thrown at the
cellForRowAtIndexPath function. How can I solve this error?
#interface TheViewController ()
#property (strong, nonatomic) NSMutableArray *myTData;
#property (weak, nonatomic) IBOutlet UITableView *tableViewOutlet;
#end
#implementation TheViewController
- (void)viewDidLoad
{
self.tableViewOutlet.delegate = self;
self.tableViewOutlet.dataSource = self;
self.tableViewOutlet.scrollEnabled = YES;
self.myData = [[NSMutableArray alloc] initWithObjects:#"obj1", #"obj2", nil];
[self.tableViewOutlet reloadData];
[super viewDidLoad];
}
#pragma mark UITableViewDataSource methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return myData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"hede"];
}
[cell.textLabel setText: [myData objectAtIndex:indexPath.row]];
[cell.detailTextLabel setText:#"hede hodo"];
//
// Configure the cell..
return cell;
}
#pragma mark UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
#end
The exception is exactly what it says it is.
In iOS 5, you would call [tableView dequeueReusableCellWithIdentifier:CellIdentifier] and if it didn't return one, you would create one. The new call -dequeueReusableCellWithIdentifier:forIndexPath: should have a NIB or cell class registered and it will then always succeed.
You should call either
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
or
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier
in your -viewDidLoad method.
In your storyboard, select the prototype cell, go to inspector and give the cell the identifier "Cell" or whatever you want as long as you have the same here : static NSString *CellIdentifier = #"Cell";
Related
My UITableViewCell is giving a -[UITableViewCell nameTeam]: unrecognized selector sent to instance.
I created a PlayerStatsTableViewCell.xib with a UITableViewCell and UILabel. Set the Custom Class to "PlayerStatsTableViewCell" and its Table View Cell identifier to "playerStats"
PlayerStatsTableViewCell.h
#interface PlayerStatsTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *nameTeam;
#end
PlayerStatsTableViewCell.m
#implementation PlayerStatsTableViewCell
#synthesize nameTeam;
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
In my PlayerStatsTableViewController, cell.nameTeam is throwing the error
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PlayerStatsTableViewCell *cell = (PlayerStatsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"playerStats"];
[tableView registerNib:[UINib nibWithNibName:#"PlayerStatsTableViewCell" bundle:nil] forCellReuseIdentifier:#"playerStats"];
cell.nameTeam.text = #"PLEASE";
return cell;
}
PlayerStatsTableViewCell.xib showing Custom Class and Identifier
The error message
PlayerStatsTableViewController from Storyboard
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PlayerStatsTableViewCell *cell = (PlayerStatsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"playerStats"];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PlayerStatsTableViewCell" owner:self options:nil];
cell = (PlayerStatsTableViewCell *)[nib objectAtIndex:0];
}
cell.nameTeam.text = #"PLEASE";
return cell;
}
So I've used this tutorial to populate a UITableView with custom cells that represent balances. When stepping through the code, I witness the correct amount of cells get created (only 4 with the current test data) and their labels' text set correspondingly.
My problem is when the table is displayed on the screen, only the first row/cell is displayed.
Any insight as to why this could be occurring would be greatly appreciated!
Removed old code.
BalanceCell.h:
#import <UIKit/UIKit.h>
#interface BalanceCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *nameLabel;
#property (weak, nonatomic) IBOutlet UILabel *amountLabel;
#property (weak, nonatomic) IBOutlet UILabel *modifiedLabel;
#end
EDIT:
My TableView delegate methods are now as follows:
- (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 [_balances count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
BalanceCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[BalanceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [_hex colorWithHexString:_themeColourString];
return cell;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(BalanceCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
Balance *item = [_balances objectAtIndex:indexPath.row];
cell.nameLabel.textColor = _themeColour;
cell.nameLabel.text = item.name;
cell.amountLabel.textColor = _themeColour;
cell.amountLabel.text = [NSString stringWithFormat:#"%#%#", item.symbol, item.value];
cell.modifiedLabel.textColor = _themeColour;
cell.modifiedLabel.text = [NSString stringWithFormat:#"%#", item.modified];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 94;
}
As #Sebyddd suggested, I now register the NIB in the viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"BalanceCell" bundle:nil] forCellReuseIdentifier:#"Cell"];
}
These changes may make my code more correct but still only the first cell is displayed.
If cells are getting created and returned properly I guess height is not being set propery. By default I beleive all cells have a height of 44. If your cell exceeds this height it might not get displayed.
You can tell the tableview to adjust height for every cell using (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath delegate
In that delegate just return your cells height.
EDIT:
You are using dequeueReusableCellWithIdentifier: which will return A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue.
Instead use dequeueReusableCellWithIdentifier:forIndexPath: which will return A UITableViewCell object with the associated reuse identifier. This method always returns a valid cell.
You need to register the nib/class for that custom cell in viewDidLoad
Try this:
if (cell == nil) {
[tableView registerNib:[UINib nibWithNibName:#"BalanceCell" bundle:nil] forCellReuseIdentifier:#"Cell"];
cell = [[BalanceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
Use this tuto : http://www.appcoda.com/uitableview-tutorial-storyboard-xcode5/ , your tuto is a bit outdated, and hard to follow !
Can anybody tell me why am I getting this error?
Here's my .m file:
#import "ListaParticipantesViewController.h"
#import "Participantes.h"
#import "ModParticipantesViewController.h"
#implementation ListaParticipantesViewController
#synthesize dao;
#synthesize participantes;
- (void)viewDidLoad
{
dao = [[ParticipantesDAO alloc] init];
participantes = [[NSMutableArray alloc] init];
participantes = [dao getDatos];
[super viewDidLoad];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [participantes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"celda";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = [[participantes objectAtIndex:[indexPath row]] valueForKey:#"nombre"];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ModParticipantesViewController *destino = [self.storyboard instantiateViewControllerWithIdentifier:#"visualizacion"];
Participantes *tmp = [participantes objectAtIndex:[indexPath row]];
destino.participante = tmp;
[self.navigationController pushViewController:destino animated:YES];
}
#end
and the error displayed is:
2013-04-13 17:40:20.235 Registro[5314:c07] *** Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:5471
2013-04-13 17:40:20.237 Registro[5314:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
*** First throw call stack:
(0x209d012 0x11aae7e 0x209ce78 0xc40665 0x1a4c1b 0x13940c 0x1a4a7b 0x1a9919 0x1a99cf 0x1921bb 0x1a2b4b 0x13f2dd 0x11be6b0 0x2699fc0 0x268e33c 0x2699eaf 0x1de2bd 0x126b56 0x12566f 0x125589 0x1247e4 0x12461e 0x1253d9 0x1282d2 0x1d299c 0x11f574 0x11f76f 0x11f905 0x128917 0xec96c 0xed94b 0xfecb5 0xffbeb 0xf1698 0x1ff8df9 0x1ff8ad0 0x2012bf5 0x2012962 0x2043bb6 0x2042f44 0x2042e1b 0xed17a 0xeeffc 0x306d 0x1ef5)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Thanks in advance!
The storyboard or XIB does not have a cell defined with the cell identifier you specified.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return cell; // at the end of your method
}
You need to set delegate and datasource of tableview in header.
Objecitve c
<UITableViewDataSource, UITableViewDelegate>
Swift
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
}
Have you subclassed your ListaParticipantesViewController with the classes UITableViewDelegate, UITableViewDataSource? They are needed to be able to use delegate and data source methods.
In Swift:
class ListaParticipantesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
}
I got the very same error. It turns out it was the same problem, that it couldn't find my cell identifier, but for a different reason - I was subclassing UITableViewCell, but hadn't registered my .XIB file with my UITableView for a reuseIdentifier.
I solved it by resgitering in the viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
//LOAD XIB
UINib *nib = [UINib nibWithNibName:#"NAME_OF_NIB_FILE"
bundle:nil];
//REGISTER XIB, CONTAINING THE CELL (IDENTIFIER NAME USUALLY SAME AS NIB NAME)
[[self tableView] registerNib:nib
forCellReuseIdentifier:#"IDENTIFIER_NAME"];
}
And then creating the cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//GET THE RECYCLED CELL
TableCellSubclass *cell = [tableView dequeueReusableCellWithIdentifier:#"IDENTIFIER_NAME"];
//CONFIGURE THE CELL
return cell;
}
Hope this helps someone!
In my case I had a simple mistake..
My number of rows was defined by array.count.
When I refreshed this array I was removing all the objects, initiating the connection, adding the objects to the array and then reloading the tableview.
I put the objects removal once the connection was completed and it solved my issue.
I'm doing this iPhone project where I need to have a (dynamic) table view inside a normal view controller. I didn't choose a Table View Controller because I need to put other stuff in the page. Imagine a page with text fields, buttons and my small table view of about 4-5 cells.
When I run the app, I need to touch a button to segue to this view. The I click the button, the app crashes and tells me that:
2012-07-22 14:40:57.304 How Many?[3055:f803] * Assertion failure in
-[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:6061
This is my .H file:
#import <UIKit/UIKit.h>
#interface ProjectViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#end
This is my .M file:
#import "ProjectViewController.h"
#interface ProjectViewController ()
#end
#implementation ProjectViewController
//MyViewController.m
#pragma mark - Table View Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"numberOfSectionsInTableView");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"numberOfRowsInSection");
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
NSLog(#"cellForRowAtIndexPath");
cell.textLabel.text = #"Test";
return cell;
}
#end
I control-dragged from the table view to my controller to set the delegate and the datasource.
What did I do wrong??
Thanks for your help.
Try to make an outlet in your .h file and wire it to the tableView in your storyboard
ProjectViewController.h
#property (nonatomic, strong) IBOutlet UITableView *myTableView;
ProjectViewController.m
#synthesize myTableView;
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
UITableViewCell *cell = [self.myTableView dequeueReusableCellWithIdentifier:#"cell"];
NSLog(#"cellForRowAtIndexPath");
cell.textLabel.text = #"Test";
return cell;
}
In your -cellForRowAtIndexPath, if you do this, you will be fine.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
}
NSLog(#"cellForRowAtIndexPath");
cell.textLabel.text = #"Test";
return cell;
}
The problem is your cell never got memory allocated and initialized. That's why you get the error.
Newbie question here ...
I've created a Master-Detail Application project in Xcode 4.2 using ARC and Storyboard. I've modified the template to be:
MasterViewController.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#interface MasterViewController : UITableViewController
{
NSMutableArray *items;
}
#property (strong, nonatomic) DetailViewController *detailViewController;
#property (strong, nonatomic) NSMutableArray *items;
#end
MasterViewController.m (snipits)
....
#synthesize items;
....
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.detailViewController = (DetailViewController)[[self.splitViewController.viewControllers lastObject] topViewController];
items = [[NSMutableArray alloc] initWithObjects:#"item 1", #"item 2", nil];
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
....
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [items count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return #"Test Section";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
cell.textLabel.text = [items objectAtIndex:indexPath.row];
return cell;
}
This code will fail on this line when the program runs:
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionMiddle];
with this exception:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
If I cut the list(items) down to a single item, the MasterViewController will load without errors. I'm obviously doing something wrong, but I can't for the life of me figure out what it is. Anyone care to point out the obvious for me?
The template includes a UITableView that is set up for static cells. And it's actually one static cell. (this is why making your array one item long happens to kind of work)
But it seems you don't want static content here. So you just have to go into the storyboard, select the UITableView, go to the Attributes Inspector, and change the Content type to Dynamic Prototypes.
That should get you past this issue.
EDIT
A somewhat related issue is that you probably also want to use the prototype cell in the storyboard. To do that, just set the cell identifier of that prototype to the cell identifier you are using in your tableView:cellForRowAtIndexPath:.
And then omit the whole 'if (cell==nil)' part. The cell won't be nil.
So that method will look like this now:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell"; // <-- Make sure this matches what you have in the storyboard
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell.
cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
return cell;
}
Hope that helps.