Failing to properly declare/implement UITableViewDataSource methods - objective-c

I have a UIViewController that I want to use to implement the methods of UITableViewDataSource on. I have this header, FriendsController.h:
#import <UIKit/UIKit.h>
#interface FriendsController : UIViewController <UITableViewDataSource>
#end
Edit: now updated the #interface declaration to:
#interface FriendsController : UIViewController <UITableViewDataSource, UITableViewDelegate>
and this implementation, FriendsController.m:
#import "FriendsController.h"
#implementation FriendsController
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"CALLED .numberOfRowsInSection()");
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"CALLED cellForRowAtIndexPath()");
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"FriendCell"];
cell.textLabel.text = #"Testing label";
return cell;
}
#end
When run this gives me a '-[UIView tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x81734d0'. Can anyone see if there is something wrong with my implementation/declaration of .numberOfRowsInSection()?
Edit: I've added a technique for method listing from here and run the view 'unconnected', it outputs the following list:
[<timestamp etc>] Method no #0: tableView:numberOfRowsInSection:
[<timestamp etc>] Method no #1: tableView:cellForRowAtIndexPath:
[<timestamp etc>] Method no #2: numberOfSectionsInTableView:
[<timestamp etc>] Method no #3: tableView:didSelectRowAtIndexPath:
[<timestamp etc>] Method no #4: viewDidLoad
Post scriptum: Both #ThisDarkTao and #Pei got it right, as can be seen in my previous question documenting the visual parts, here.

You need to add UITableViewDelegate to the list of protocols in the interface file, like this: <UITableViewDataSource, UITableViewDelegate>
You also need all of the following delegate methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1; // Number of rows
}
- (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];
}
cell.textLabel.text = #"Test Cell";
return cell;
}
In your xib/storyboard view, you also need to connect the tableview's delegate and datasource connections to the viewcontroller.
If you want your cells to 'do something' when you tap them, you also need to implement the following delegate method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Tapped cell %d",indexPath.row);
}

If you use the Storyboard in your project, you have to set the UIViewController's Class field to be your "FriendsController" on Identity Inspector of your storyboard.
So you can present your UIVIewController to be using your correct class (In this case, FriendController for you).
Pei.

Related

Error adding UITableView to ViewController on storyboard

On my storyboard I have a ViewController and I want to add a UITableView with 1 section and 2 static cells. That's all I'm doing right now but I get this error when compiling.
Static table views are only valid when embedded in UITableViewController instances
What am I missing?
Look at This question. Basically the same thing.
Any further questions, just ask! :)
Edited stuff:
UITableViewController *controller = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
[self.view addSubview:controller.tableView];
Then all you need to do is adding the UITableViewDataSource in the header file and you need the datasource methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if([indexPath row] = 0){
do something
}else if([indexPath row] = 1){
do something else
}
I think you just have to set datasource and delegate methods of the tableView in your .h file
#interface viewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
and then link it to your tableView in storyboard.
Please notify if it works..

UICollectionViewCell Subclass issue

I have subclassed a UICollectionViewCell-
#interface ListCell : UICollectionViewCell
#property(nonatomic,strong) IBOutlet UILabel *lblAppName;
#end
I have made an xib for the same ,made all the IBOutlet collection as well as set the class of the XIB , while using this Cell in the Collection view delegate method i get a nill value while trying to access the label instance.
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ListCell *cell = (ListCell *)[cv dequeueReusableCellWithReuseIdentifier:#"ListCell" forIndexPath:indexPath];
AppDetails *temp=[arrApplist objectAtIndex:indexPath.item];
cell.lblAppName.text=temp.strName;
return cell;
}
i have registered the cell to my collection view by:
[collectionView registerClass:[ListCell class] forCellWithReuseIdentifier:#"ListCell"];
is there something else i might be missing??
Thanks in advance.
Instead of registering the class, I think you need to register the xib, using registerNib:forCellWithReuseIdentifier:. Try that, and see if that helps.
if you use ListCell.xib,please use registerNib:forCellWithReuseIdentifier:.
Implement your ListCell initial in awakeFromNib instead of initWithFrame.
And change type like that:
- (ListCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ListCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"ListCell" forIndexPath:indexPath];
cell.lblAppName.text=(NSString *);
return cell;
}

Master Detail Storyboard: Table View not showing cells (Objective-C)

I'm having troubles with the master viewController not showing any cells. This is the situation:
The app uses storyboard.
When the app launches, it goes to the navigationController
A button is pressed and connected to the table ViewController and it's set to "push" to it.
I've added the object and made a cell/detailView or whatever.
For some reason, the cell won't show up!!!
Here's the files:
MasterViewController.h:
#import <UIKit/UIKit.h>
#import "CraftingDetail.h"
#import "Crafting.h"
#class CraftingList;
#interface CraftingMaster : UITableViewController
#property (strong, nonatomic) CraftingDetail *detailViewController;
#property (strong, nonatomic) CraftingList *CL;
#end
MasterViewController.m:
#import "CraftingMaster.h"
#import "CraftingList.h"
#interface CraftingMaster ()
#end
#implementation CraftingMaster
#synthesize detailViewController = _detailViewController;
#synthesize CL;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
self.CL = [[CraftingList alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return self.CL.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.CL.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
cell.textLabel.text = [self.CL craftingAtIndex:indexPath.row].Title;
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface CraftingDetail : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *Image;
#property (strong, nonatomic) IBOutlet UITextView *Description;
#end
This is an old question, but having an unexpectedly empty table view is a common issue when starting to develop with table views so hopefully this answer will be of use to someone.
Here are some things to check when your table view is devoid of cells and you expected otherwise:
Are your data source object(s) (self.CL in this case) valid? (ie. Are they != nil and point to the correct object?)
Does numberOfSectionsInTableView: return an integer value greater than zero?
Does tableView:numberOfRowsInSection: return an integer value greater than zero?
Here are a couple of problems in MasterViewController.m above that need attention:
InitWithStyle: will not be executed when the view controller is instantiated in a storyboard. Instead, initWithCoder: should be used. I suspect this was the source of JomanJi's pain as this resulted in self.CL not being instantiated. (As an aside, the data source object/property: CL should be instantiated by assigning the value to the _CL ivar directly, not to the property. See "Initializing a property, dot notation" to learn why).
Due to returning (what is likely) the same value for numberOfSectionsInTableView: as tableView:numberOfRowsInSection: (ie. "return self.CL.count;"), the table view will display the same number of sections as there are cells in each section with each sections' cells containing the same data as the other sections. I doubt this effect was what the developer intended. (This is of course unless the count accessor method in CraftingList does something really strange).
Without seeing the code for CraftingList it is impossible to determine exactly what the problem is. However, given the age of the question, I suspect JomanJi has since figured it out on his/her own.

Add UITableView to an existing project: crash when adding array to populate rows

I'm adding to a project a TableView populated with countries to choose from. Added the New File (UITableView subclass for iPad+XIB), wrote the trigger IBAction code (editing a textfield if default country is not right), made some connections and the empty table view appears. I have read several tutorials and i cannot make out the problem: when the array with words loads in - (void)viewDidLoad, the app crashes with the following warning:
2012-05-04 12:34:36.740 pruebaF1[4017:f803] * Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:6061
2012-05-04 12:34:36.741 pruebaF1[4017:f803] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'...
CountryVieWController connections:
File Owner's connections
Outlets
dataSource -> File's Owner
delegate ->File's Owner
Referencing Outlets
view -> File's Owner
Code:
// CountryTableVieWController.h
#import <UIKit/UIKit.h>
#interface CountryTableVieWController :
UITableViewController<UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *countriesArray;
NSArray *countryArray;
}
#end
// CountryTableVieWController.m
#import "CountryTableVieWController.h"
#import "pruebaF1SecondViewController.h"
#interface CountryTableVieWController ()
#end
#implementation CountryTableVieWController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
countriesArray = [[NSMutableArray alloc] initWithObjects:#"Austria", #"Italy", #"France",nil];
}
Thanks in advance.
You need to implement delegate methods for the UITableView.
Have a look at this: http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/CreateConfigureTableView/CreateConfigureTableView.html#//apple_ref/doc/uid/TP40007451-CH6-SW10
I find the easiest way to think of it is that your UITableView is asking your code what should go in the cells. You use these methods to configure your table view and the UITableViewCells within it.
You will need something like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
[countriesArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
NSString *country = [countriesArray objectAtIndex:indexPath.row];
cell.textLabel.text = country;
return cell;
}

UITableView not populating from UIView

I have this problem I've been sitting with. My tableView that I put inside my UIView is not populating or sometimes I get an exception.
// .h
#interface List : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableView *mTableView;
}
#property (nonatomic, readonly) IBOutlet UITableView *tableView;
//------------------------------
// .m
#synthesize tableView=mTableView;
//Further I do the normal viewDidUnload stuff = nill
//And the numberOfSectionsInTableView, numberOfRowsInSection and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellForRowAtIndexPath:");
NSLog(#"Table View: %#",[tableView description]);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"Hi";
// Configure the cell...
return cell;
}
I get as output:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<List 0x6a78000> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key tableView.'
or just a list of empty cells, not even "Hi" as a title.
I'm almost sure that this error occurs because you have improperly connected your UITableView . You should delete an ivar mTableView, an IB outlet property tableView and #synthesize . Then DELETE AN OUTLET IN IB. Then, connect it again by dragging it from the interface builder and DO NOT TYPE ANY CODE in your class. Xcode will do all stuff for you (create a property, synthesize it and do MM things)
Make sure that you have set the delegate and the datasource of the table within Interface Builder
If you do not do anything with your IBOutlet why do you have it? The method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
is Called by the nib-File for the tableView instance created in the nib.Your Class as a delegate of this instance receives this call. Being the delegate of the tableView in the nib is all you need.