Error adding UITableView to ViewController on storyboard - objective-c

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..

Related

Push to viewcontroller and parse data

I have a simple UITableView which is suppose to push to a new Viewcontroller. When the Cell is pressed it should push to the new viewcontroller and send what number of row has been pushed. Is there a way to obtain this?
This is what i have at the moment, which dosent do anything.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
YoutubeViewController *youtubeViewController = [[YoutubeViewController alloc] initWithNibName:#"YoutubeViewController" bundle:nil];
[self.navigationController pushViewController:youtubeViewController animated:YES];
}
Do like this
This method is the delegate that will be called when a the user selects a cell in tableview
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//Write code here to push your viewcontroller
YourViewController *controller=[[YourViewController alloc]initWithNibName:#"YourViewController" bundle:[NSBundle mainBundle]];
controller.selectedRowValue = indexPath.row;
[self presentViewController:controller animated:YES completion:NULL];
}
In YourViewController.h
#interface YourViewController : UIViewController
#property int selectedRowValue;
#end
In YourViewController.m
#implementation YourViewController
#synthesize selectedRowValue;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Selected Row %d",selectedRowValue);
}
Check protocol of UITableViewController delegate https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDelegate_Protocol/Reference/Reference.html.
Method You are looking for
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
yes do one thing
create property of integer type in your YoutubeViewController
like this
#property int selectedRowValue;
after that syntsize it in YoutubeViewController.m class
// YoutubeViewController.m
#implementation YoutubeViewController
#synthesize selectedRowValue
now you come class where ur table is and make some changes to it as shown bellow
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
YoutubeViewController *youtubeViewController = [[YoutubeViewController alloc] initWithNibName:#"YoutubeViewController" bundle:nil];
youtubeViewController.selectedRowValue=indexPath.row;
[self.navigationController pushViewController:youtubeViewController animated:YES];
}
now every thing done to check index value selected in youtube class NSLogout the value
//YoutubeViewController.m
- (void)viewDidLoad
{
// nslogout the value to check
NSLog(#"yours data selected from table%d",selectedRowValue);
}
now every thing done .
enjoy coding
Even you dont want this you can go by creating Constructor or by storing the value to NSUserDefaults

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.

Failing to properly declare/implement UITableViewDataSource methods

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.

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 with multiple datasource

I have a ViewController that needs to use 2 UITableViews.
1 is always showing, while the other will show up as a popup after you click on a button on the view.
Typically I set the delegate and datasource to the File's Owner. However, since 1 of the UITableViews is in a popup, I'm not sure how to best tackle this.
e.g how do I tackle this part -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Please advice.
You should have instance variables for both table views declared in your controller:
#interface MyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
UITableView *mainTableView;
UITableView *popupTableView;
}
In each data source or delegate method, you can check which table view is being passed by the caller:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView == mainTableView)
{
// Code to create and return a main table view cell
}
else if(tableView == popupTableView)
{
// Code to create and return a popup table view cell
}
}