I have made an extremely simple app using Storyboards (for the first time).
The app's basically a Table View Controller embedded in a Navigation Controller and that segues out to a View Controller which displays an image. But when I click on an row, it gives me a Thread 1 SIGABRT error. Here's the log :
2013-09-03 22:37:16.669 FootballPlayers[7226:c07] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] loaded the "PcV-xW-t12-view-xx8-ac-4rU" nib but didn't get a UITableView.'
* First throw call stack:
(0x1c94012 0x10d1e7e 0x1c93deb 0x245357 0xf6ff8 0xf7232 0xf74da 0x10e8e5 0x10e9cb 0x10ec76 0x10ed71 0x10f89b 0x10fe93 0xc4823f7 0x10fa88 0x46be63 0x45db99 0x45dc14 0xc5249 0xc54ed 0xacf5b3 0x1c53376 0x1c52e06 0x1c3aa82 0x1c39f44 0x1c39e1b 0x1bee7e3 0x1bee668 0x15ffc 0x226d 0x2195 0x1)
libc++abi.dylib: terminate called throwing an exception
Here's the implementation of the TableViewController
#import "PlayersTableViewController.h"
#interface PlayersTableViewController ()
#end
#implementation PlayersTableViewController
NSMutableArray *players;
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
DisplayViewController *dvc = [segue destinationViewController];
NSIndexPath *path = [[self tableView] indexPathForSelectedRow];
[dvc setCurrentPlayer:[players objectAtIndex:[path row]]];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
players = [[NSMutableArray alloc] init];
Player *stevenGerrard = [[Player alloc] init];
[stevenGerrard setName:#"Steven Gerrard"];
[stevenGerrard setFileName:#"Steven Gerrard.jpg"];
[stevenGerrard setInformation:#"International Team : England, Club : Liverpool FC"];
[players addObject:stevenGerrard];
Player *cristianoRonaldo = [[Player alloc] init];
[cristianoRonaldo setName:#"Cristiano Ronaldo"];
[cristianoRonaldo setFileName:#"Cristiano Ronaldo.jpg"];
[cristianoRonaldo setInformation:#"International Team : Portugal, Club : Real Madrid"];
[players addObject:cristianoRonaldo];
// 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)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 [players count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PlayerCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
Player *current = [players objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[current name]];
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
What's wrong ?!
Thank You.
One very handy thing to do is to add an Exception Breakpoint: https://developer.apple.com/library/ios/recipes/xcode_help-breakpoint_navigator/articles/adding_an_exception_breakpoint.html
This way you'll probably see the exact place in your code where it goes wrong.
If the error occurs after tapping on a row, the code of the destination view controller is also interesting.
Your nib file is incorrectly constructed, most likely.
It would appear that you have something other than a table view connected to the table view controller's outlet that should point to the table view.
Make sure you are subclassing UITableViewController and not UIViewController (or anything else) in your .h file.
So it should look like:
#interface PlayersTableViewController : UITableViewController
Related
I created the simple Master Detail application for login.I deleted the MasterViewController, DetailViewController and Main.storyboard according to this tutorial:
Login app to mysql DB [part 1]
In AppDelegate didFinishLaunchingWithOptions function i made the following change
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window=[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]bounds] ];
/*UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;*/
LoginTableViewController *loginTableViewController=[[LoginTableViewController alloc]initWithNibName:#"LoginTableViewController" bundle:nil ];
self.navigationController =[[UINavigationController alloc]initWithRootViewController:loginTableViewController];
self.window.rootViewController=self.navigationController;
[self.window makeKeyWindow];
return YES;
}
I commented this function from App Delegate function
/*
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
.............................
}*/
I created LoginTableTableViewController with xib of subclass UITableViewController.
I created LoginTableTableViewController.h
#import "LoginTableViewController.h"
#interface LoginTableViewController ()
#end
#implementation LoginTableViewController
#synthesize arraylogin,userNameTextField,passwordTextField;
bool isKeyboardVisible=FALSE;
- (void)viewDidLoad {
[super viewDidLoad];
arraylogin=[[NSArray alloc] initWithObjects:#"user name",#"password",nil];
//set title
self.navigationItem.title=#"Best App";
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardAppeared) name:UIKeyboardDidShowNotification object:nil];
// 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) loginAction
{
if([userNameTextField.text isEqualToString:#""] || [passwordTextField.text isEqualToString:#""])
{
// UIAlertView #alert=[[UIAlertView alloc] intitWithTitle:#"alert" messge:#"Please fill in all //the fields" delegate:self cancel]
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"alert" message:#"Please fill in all the fields" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
//i will use a code to connect to DB turorial
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)keyboardAppeared
{
if(isKeyboardVisible==false)
{
isKeyboardVisible=true;
UIBarButtonItem *btnGo=[[UIBarButtonItem alloc] initWithTitle:#"Go" style:UIBarButtonItemStyleBordered target:self action:#selector(loginAction)];
self.navigationItem.rightBarButtonItem=btnGo;
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Incomplete implementation, return the number of sections
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete implementation, return the number of rows
return [arraylogin count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifer=#"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifer];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifer];
}
//cell are not selectable
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
CGRect frame;
frame.origin.x=10;
frame.origin.y=10;
frame.size.height=30 ;
frame.size.width= 200;
UILabel *label=[[UILabel alloc]initWithFrame:frame];
label.font=[UIFont boldSystemFontOfSize:16.0];
label.text=[arraylogin objectAtIndex:indexPath.row];
[cell.contentView addSubview:label];
frame.origin.x=110;
frame.size.height=90 ;
frame.size.width= 180;
// Configure the cell
if(indexPath.row==0)
{//username part
userNameTextField=[[UITextField alloc] initWithFrame:frame];
userNameTextField.returnKeyType=UIReturnKeyDefault;
[cell.contentView addSubview:userNameTextField];
}
else{//password part
passwordTextField=[[UITextField alloc] initWithFrame:frame];
passwordTextField.returnKeyType=UIReturnKeyDefault;
passwordTextField.secureTextEntry=YES;
[cell.contentView addSubview:passwordTextField];
}
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
// In a xib-based application, navigation from a table can be handled in -tableView:didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here, for example:
// Create the next view controller.
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:<##"Nib name"#> bundle:nil];
// Pass the selected object to the new view controller.
// Push the view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
*/
-(void) viewDidUnload
{
[super viewDidUnload];
self.arraylogin=nil;
self.userNameTextField=nil;
self.passwordTextField=nil;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
This program should be executing and show out like in this image
.
Execution stops program on some thread of main class function how i can remove this error and get the required output?You can download sample code from this link for correction.https://drive.google.com/file/d/0B5pNDpbvZ8SnV3Zab3VPM1B0a0k/view?usp=sharing
Your project is still specifying that a "Main" storyboard should be loaded. Edit your Info.plist file to remove the storyboard entry and it will get you past the current error.
(If you include error messages from your debug console when asking a question, it makes it easier on anyone trying to help. For example: "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'Main' in bundle".)
I have two UIViews in my app.
in first view there is a tableveiw with two cells(to select city and country). when user select first cell(to select city), then it goes to anothrview that has a list of cities. then when user select a city(select a tableviecell text), the selected should display in firtview's tableviewcell text.
this is my code in secondview controller(it is a tableview Controller).
- (void)viewDidLoad {
[super viewDidLoad];
detailFlights = #[#"colombo1",#"colombo2",#"colombo3",#"colombo14",#"colombo15",#"colombo16",#"colombo17"];
// 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)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [detailFlights count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"identi" forIndexPath:indexPath];
cell.textLabel.text = [detailFlights objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This kind of problem is solved using the delegate pattern. A pattern widely used in iOS programming. See this question if you don't know how it works.
As deadbeef said, you must implement delegate method to transfer data to first view, but logic for that is to choose objectAtIndex of indexPath.row in didSelect: [detailFlights objectAtIndex:indexPath.row];
As an alternative to the delegate method that others have mentioned, you can use an unwind segue to pass data back to the previous view controller.
Unwind segues give you a way to "unwind" the navigation stack back through push, modal, popover, and other types of segues. You use unwind segues to "go back" one or more steps in your navigation hierarchy. Unlike a normal segue, which create a new instance of their destination view controller and transitions to it, an unwind segue transitions to an existing view controller in your navigation hierarchy. Callbacks are provided to both the source and destination view controller before the transition begins. You can use these callbacks to pass data between the view controllers.
Here's a example where the second (source) view controller presented a list of fonts, and the first (destination) view controller updates its table row to show the selected font:
- (IBAction)unwindFromFontPreference:(UIStoryboardSegue *)segue
{
FontTableViewController *fontTableViewController = segue.sourceViewController;
if (self.currentFontSelection != fontTableViewController.currentFontSelection)
{
self.currentFontSelection = fontTableViewController.currentFontSelection;
[self.tableView reloadRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:0 inSection:LALSettingsTableViewSectionFont]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
#interface FirstViewController ()<UITableViewDelegate, UITableViewDataSource, ViewControllerDelegate>
#property (nonatomic, retain) NSMutableArray* data;
#property (nonatomic, retain) IBOutlet UITableView* tableView;
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.data = [NSMutableArray array];
[self.data addObject:#"country"];
[self.data addObject:#"city"];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
NSString* text = [self.data objectAtIndex:indexPath.row];
cell.textLabel.text = text;
return cell;
}
-(void) updateText:(NSString *)text
{
[self.data replaceObjectAtIndex:1 withObject:text];
[self.tableView reloadData];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"secondView"])
{
UINavigationController* controller = [segue destinationViewController];
NSArray *viewControllers = controller.viewControllers;
SecondViewController* viewController = [viewControllers objectAtIndex:0];
viewController.delegate = self;
}
}
SecondViewController.h
#import <UIKit/UIKit.h>
#protocol ViewControllerDelegate <NSObject>
-(void) updateText:(NSString*)text;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, assign) id<ViewControllerDelegate> delegate;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#property(nonatomic ,retain) NSArray* detailFlights;
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.detailFlights = #[#"colombo1",#"colombo2",#"colombo3",#"colombo14",#"colombo15",#"colombo16",#"colombo17"];
// 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)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.detailFlights count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
cell.textLabel.text = [self.detailFlights objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{ NSString* text = [self.detailFlights objectAtIndex:indexPath.row];
[self.delegate updateText:text];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
whole project is here
In didDeselectRowAtIndexPath method you can get that string using following way
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSString *selectedString = [tableView cellForRowAtIndexPath:indexPath].textLabel.text;
}
now save to pass previous view controller you can store it in UserDefaults OR
make a property in previousViewController and before go back set it value like follow
if you are using navigationController then
ViewController *previousViewController = (ViewController *) self.navigationController.viewControllers[self.navigationController.viewControllers.count-2];
previousViewController.selectedString = selectedString;
or
you can also use block for passing data. example of block
I have a table view that is dynamically created via JSON and I want it to be so when I click on one of those items in the table view that I get transferred to a new screen.
I have this working using a project that I found online, but the project is for a older iOS and uses nibs.
The screen that I want to transfer to also has to be dynamic via the same JSON file. I need to know how to create the dynamic screen to transfer to and how to get the current code to transfer to that screen working.
Here is my current code to transfer to a new screen ( remember it is from a older iOS ) :
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
PeopleDetailsViewController *detailViewController = [[PeopleDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped];
detailViewController.details = self.data[indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
EDIT. This is my current code to create the details view.(view that needs to be dynamic):
#import "PeopleDetailsViewController.h"
#interface PeopleDetailsViewController ()
#end
#implementation PeopleDetailsViewController
#synthesize details;
- (BOOL)prefersStatusBarHidden
{
return YES;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (NSString *)name {
return [NSString stringWithFormat:#"%# %#", self.details[#"Tag"], self.details[#"B"]];
}
- (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;
self.title = [self name];
}
- (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 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
switch (indexPath.row) {
case 0:
cell.textLabel.text = [self name];
cell.detailTextLabel.text = #":Tag";
break;
case 1: {
cell.detailTextLabel.text = #":Value";
cell.textLabel.text = self.details[#"Value"];
break;
default:
break;
}
}
return cell;
}
You have (mostly) everything you need. Your table view data source is for now hardcoded, so you will have to change this part of your code. The method names are pretty self-explanatory.
What you should do :
Add a method in PeopleDetailsViewController called, for example '-(void) setDetails : (type)name which will be used to pass the details to the new controller. At the end of this function you should call [self.tableView reloadData]; - this will tell your table view that the data has changed and it should reload it (calling the methods under #pragma mark - Table view data source)
Change the above mentiod methods, so that they don't return hardcoded values, but rather ones passed in details.
If you want non-standard table cells, you can design them in Interface Bulder and assign a custom class to them with IBOutlets and then populate them with data similarily.
I have a UITableView which contains an array of 3 items. Upon user selection, I need each of these three items to segue to a different UITableView. For example:
First Scene is the table which contains the list: Weather, Intelligence, Fuels Status
Second scene would be:
For when a user selects weather, segue to a table which contains the array "daily maps, fire potential, etc."
For when a user selects intelligence, segue to a table which contains the array "current active fires, new initial attacks, etc."
and so forth.
I have been told I could use different UITableViewCells for each prototype cell but I'm sure there is an easier way that I am simply not grasping. All current segues were done in storyboard. Could someone please elaborate on how I should be segueing from scene to scene (at a beginner-intermediate level of understanding)?
Root
#import "PSMenu_TableViewController.h"
#import "WXMenu_TableViewController.h"
#import "PSTableViewCell.h"
#interface PSMenu_TableViewController ()
#end
#implementation PSMenu_TableViewController
#synthesize PSMenuImage = _PSMenuImage;
#synthesize PSMenuText = _PSMenuText;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.PSMenuText = [[NSArray alloc]
initWithObjects:#"Weather",
#"Intelligence",
#"Fuels Status",
nil];
self.PSMenuImage = [[NSArray alloc]
initWithObjects:#"RMACC_114x114.png",
#"RMACC_114x114.png",
#"RMACC_114x114.png",
nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (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 [_PSMenuText count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"rootTableCell";
PSTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == 0) {
cell = [[PSTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.rootLabel.text = [self.PSMenuText
objectAtIndex: [indexPath row]];
UIImage *rootPhoto = [UIImage imageNamed:
[self.PSMenuImage objectAtIndex: [indexPath row]]];
cell.rootImage.image = rootPhoto;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Use indexPath to retrieve info that needs to be passed along to next view controller
[self performSegueWithIdentifier:#"getWeather" sender:self];
}
#end
One of the .m files I am trying to segue to:
#import "WXMenu_TableViewController.h"
#import "DWO_TableViewController.h"
#interface WXMenu_TableViewController ()
#end
#implementation WXMenu_TableViewController
{
//Define array for weather products list
NSArray *allwx;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Define the weather products list
allwx = [NSArray arrayWithObjects:#"Daily Weather", #"Fire Potential", #"Multi-Media Briefing", #"Sig. Fire Potential",#"Seasonal Outlook", #"Fire Season Broadcast", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Set table size to one section.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//When Weather is clicked on previous VC, the allwx list is displayed
if ([_weathertable isEqualToString:#"Weather"]) {
return [allwx count];
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *pstableID = #"MainCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:pstableID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:pstableID];
}
if ([_weathertable isEqualToString:#"Weather"]) {
cell.textLabel.text = [allwx objectAtIndex:indexPath.row];
}
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:#"showDWODetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DWO_TableViewController *destViewController = segue.destinationViewController;
destViewController.dailywxtable = [allwx objectAtIndex:indexPath.row];
destViewController.title = destViewController.dailywxtable;
}
}
#end
You can segue to a single UITableViewController here and make it display respective contents according to the category chosen. This might help you.
In your Destination View Controller, you can declare a variable and use it in your prepareForSegue method as shown to identify what type of content do you want to see on your destination view controller.
destController.varName = #"setYourTypeHere";
Now you can also set the variable value here based on the Row you are clicking in your tableview.
And in your Destination View controller, you can check this value using switch or if...else cases and bind the appropriate data as per your requirement.
In storyboard you wire up each destination not to the prototype tableview cell, but to the view controller itself (little yellow box on left side of the title bar of the view controller in the storyboard).
Name each segue with a meaningful name, and then in your "didSelect" delegate method you can perform a segue using:
[self performSegueWithIdentifier:#"myNamedSegue" sender:self];
I am trying to embed custom designed TableView Cells (in interface builder). For starters I am trying to add a few text fields in its own section. I am able to show the custom designed tableview however I am doing something incorrect as it looks all messed up. Also not super clear on how to add additional sections. Can someone guide me to right direction? I tried following: http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7-SW20
But got a little lost.
Here is what it looks like:
This is my setup in interface builder:
This is my code:
header file:
#import <UIKit/UIKit.h>
#interface SearchTableViewController : UITableViewController
{
}
#property (nonatomic, retain) IBOutlet UITableViewCell *priceRanceCell;
#end
implementation:
#import "SearchTableViewController.h"
#interface SearchTableViewController ()
#end
#implementation SearchTableViewController
#synthesize priceRanceCell=_priceRanceCell;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Some Search", #"Some Search");
self.tabBarItem.image = [UIImage imageNamed:#"search"];
}
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);
}
#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
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SearchViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
NSInteger section = [indexPath section];
switch (section) {
case 0: // First cell in section 1
return self.priceRanceCell;
break;
default:
// Do something else here if a cell other than 1,2,3 or 4 is requested
return cell;
break;
}
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
You need to implement heightForRowAtIndexPath:. Also, note that when you are dequeueReusableCellWithIdentifier:, the result maybe be nil, in which case you need to create a cell. You should modify your logic so you don't even try if its section 0.
In interface builder, click the custom cell you made, memorise the height; then click on the table view you are going to use, enter the row height from your memory.