I'm trying to create a simple View : a tableView which takes like 80% of the screen, and a collectionView with 4 rows at the bottom. Everything works fine with my tableView but I can't get things right with my collectionView. I always get the following exception :
Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'could not dequeue a view of kind: UICollectionElementKindCell with
identifier simpleCollectionCell - must register a nib or a class for the
identifier or connect a prototype cell in a storyboard'.
I've been looking in my View Controller : there are 2 refering outlets for my collectionVIew : datasource and delegate. So it's fine. And I'm using the method "withReuseIdentifier" so I don't have to declare an identifier in the nib. I've been trying to create a property for collectionView, but it changes nothing.
So I really don't see what I am missing ...
.h :
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource>
#end
.m :
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController {
NSArray *recipes;
NSArray *images; }
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self; }
- (void)viewDidLoad {
[super viewDidLoad];
recipes = [NSArray arrayWithObjects:#"Label1", #"Label2", #"Label3", #"Label4", #"Label5", #"Label6", #"Label7", #"Label8", #"Label9", #"Label10", #"Label11", #"Label12", #"Label13", #"Label14", #"Label15", nil];
images = [NSArray arrayWithObjects:#"img1", #"img2", #"img3", #"img4", nil];
// Do any additional setup after loading the view. }
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated. }
#pragma mark TableView methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [recipes count]; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
return cell;
}
#pragma mark CollectionView methods
- (NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection: (NSInteger)section {
return [images count];
}
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
return cell;
}
#end
Thanks in advance !
Make sure you have set the proper Custom Class(if any) as well as the Cell Identifier for the Collection View Cells in the Interface builder. Check this Screenshot.
This is for the Custom Class and the one below is for Cell Identifier.
The Identifier in your case is "cell". Make sure you have these set. They might be the problem here. Also the Class name of your CollectionViewCell and the one in your cellForItemAtIndexPath should be same.
Hope this helps.
You have To register your collection view cell
[self.dashBoardCollection registerNib:[UINib nibWithNibName:#"DashBoardCell" bundle:nil] forCellWithReuseIdentifier:#"DashBoardCell"];
may be in identity Inspector your are missing to name the Class
Oky u can try with this, just a simple way,
First create a new file in user interface select view and name as NibCell.
Then select the device (choose any one of them).
Delete what ever the content in the view.
Just drag and drop a new CollectionViewCell that's it.. :)
in the collectinview cell u can add image view (or any other objects u want) and set its tag to access.
for example
in viewDidLoad method
- (void)viewDidLoad
{
[super viewDidLoad];
//....other code
//nib register
UINib *cellNib = [UINib nibWithNibName:#"NibCell" bundle:nil];
[_collectionView registerNib:cellNib forCellWithReuseIdentifier:#"Cell"];
}
and in this method
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell"; //u know the identifier
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; //get the cell
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100]; //for example i put a label and set it's tag to 100 and i an accessing it
[titleLabel setText:cellData];
return cell;
}
Related
I want to create a default static table in my sub-class of UITableViewCintroller, but data doesn't appear. I don't know where is the problem, I think that cellForRowAtIndexPath method not called.
Here is my code:
#import <UIKit/UIKit.h>
#interface S5WebTable : UITableViewController <UITableViewDelegate, UITableViewDataSource>
#end
#import "S5WebTable.h"
#interface S5WebTable ()
#property(assign,nonatomic) BOOL isLoaded;
#end
#implementation S5WebTable
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.tableView sizeToFit];
}
-(void)viewWillAppear:(BOOL)animated{
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 7;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell.textLabel.text =#":)";
return cell;
}
I think you have to use a distinct identifier for each cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [NSString stringWithFormat:#"s%i-r%i", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
//you can customize your cell here because it will be used just for one row.
}
return cell;
}
First of all you have to give identifier to tableview cell then it will displays.
e.g.
NSString *cellIdentifier = [NSString stringWithFormat:#"%d_cell", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]];
}
return cell;
}
1.Drag TableView Controller in StoryBoard
2.Sele ct the TableView and in Right Inspector change number of Prototyes Cell(number of cells) and then Dynamic Prototypes to Static Cell
3.Customise the Cell according to your requirement
Tat's it Static TableView is created.Don't override any of tableview delegate or datasource methods
Below i added the screenshot of Right Inspector
I have a table view controller in which the cells don't show up:
I have added UiViewDataSource and UITableViewDelegate as shown below:
myViewController:UITableViewController<UITableViewDataSource,UITableViewDelegate>
In the storyboard as well as in the code I have set
self.tableView.delegate =self;
self.tableview.datasource = self;
My numberOfRowsInSection returns the value 30 (verified with logs) and numberOfSectionsInTableView returns 1 (verified with logs)
I have also printed the tableView header and footer view frame,height and width and they all have the value 0.0000
NSLog(#"The header frame size is%f" ,self.tableView.tableHeaderView.frame.size.height);
NSLog(#"The header frame size is%f" ,self.tableView.tableHeaderView.frame.size.width);
NSLog(#"The header frame size is%f" ,self.tableView.tableFooterView.frame.size.height);
NSLog(#"The header frame size is%f" ,self.tableView.tableFooterView.frame.size.width);
This is the firstController of a navigation controller.
The numberOfSectionsInTableView method is called first, then the numberOfRowsInSection and then the heightForRowAtIndexPath is called.
The cellForRowAtIndexPath method contains:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *) [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell configureCustomCell:[self.dataSource objectAtIndex:indexPath.row]];
return cell;
}
configureCustomCell configures the different properties in the cell.
I tried all the solutions given in similar questions but none of them seem to be working. What am I missing?
if you have configured UITableViewDataSource and UITableViewDelegate protocols inside your ViewController.h file, then there is no need to use self.tableView.delegate =self;
self.tableview.datasource = self;
if you have configured UITableView inside your storyboard.
you need to configure your CustomTableViewCell with your tableView's cell property.
step - 1
select your tableView Cell and inside identity inspector define your CustomTableViewCell class.
step - 2
now provide cell identifier. (i have used "customCell")
import your CustomCell class inside your ViewController.m file. Just created demo app as per your reference. Hope it solves your query.
#import "ViewController.h"
#import "CustomTableViewCell.h" //CustomTableViewCell class
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 30; //used staticCells 30
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"customCell"; //as defined in cell identifier (as per step -2)
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// configure your custom cell
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Is anyone having a problem with Xcode 6 when adding a Collection View Controller to storyboards and naming the custom class?
-> I drag a Collection View Controller to my scene -> add a new file -> name it "LCCollectionViewController" with a subclass of UICollectionViewController.
Next, I select the Collection View Controller in storyboard, and name the custom class LCCollectionViewController in the identity inspector.
Problem: The document outline still shows the name as Collection View Controller.
Code just in case:
LCCollectionViewController.m
#interface LCCollectionViewController ()
{
NSArray *theImages;
}
#end
#implementation LCCollectionViewController
static NSString * const reuseIdentifier = #"Cell";
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
moonImages = [NSArray arrayWithObjects:#"image1.gif", #"image2.gif", #"image3.gif", #"image4.gif", nil];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [moonImages count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
UIImageView *theImageView = (UIImageView *)[cell viewWithTag:100];
theImageView.image = [theImages objectAtIndex:indexPath.row];
return cell;
}
#end
I encountered same bug in xcode6. What helped me was to change subclass to any other viewcontroller subclass you have set up already (perhaps create temporary one if none is available) and then change it back to LLCollectionViewController.
In XCode 5, when you add a UITableViewController with more than 1 prototype cell which all contain labels etc., the content is displayed because the UITableViewController automatically sets the data source and delegate of the table view and sends a reloadData message to it.
iOS Developer Library - Basics of Table View Creation
But when you drag a UITableView to a UIViewController I believe you have to create instance methods similar to the default ones below in order for the content to be reloaded and made visible.
My question is how can I target a UITableView somewhere within a UIViewController and set its data source and delegate and have it reloaded and its content displayed properly?
Here is the default code for the UITableViewController:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
return cell;
}
Here is my code that works with UITableViewController but not in UIViewController for the UITableView that it contains:
...
#property (nonatomic, strong) NSArray *menuItems;
...
- (void) viewDidLoad
{
[super viewDidLoad];
self.menuItems = #[#"rowOne", #"rowTwo", #"rowThree", #"rowFour"];
}
...
- (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.menuItems count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [self.menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
IN your code where u have created your cell if it not exists? And also make cell identifier as static.
You should create cell if it not exists in cellForRowAtINdexPath like as following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(cell == nil)
{
//Create your cell
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//Configure your cell
return cell;
}
You can set data source and delegate in a few ways. If you add table view to view controller in storyboard just control drag from table view to view controller and select delegate and do it again and select data source.
You can also create outlet and in your view controller in viewDidLoad do it by:
self.tableView.dataSource = self;
self.tableView.delegate = self;
The other way is create table view in code and add it to your view controller view. You can do it in viewDidLoad like that:
tableView = [[UITableView alloc] initWithFrame:CGRectMake(TABLE_VIEW_FRAME) style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
If you want to reload the data just call:
[self.tableView reloadData];
Hope this help.
Make sure you implement UITableViewDelegate and UITableViewDataSource protocols and set these in the initWithNibName or initWithCoder initializers.
This is how your .h file should look like:
#interface TestViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
Here is what you need to do in the .m file:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
return self;
}
if you are using storyboards, please use initWithCode as given below:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
return self;
}
You are only dequeuing the cell but you are not creating one if dequeueReusableCellWithIdentifier returns nil. You should implement in following way.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// here you can configure the cell
return cell
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";