I have an iOS 5 application with a storyboard and two scenes. Scene 1 is a selection list while Scene 2 shows details for each selection
In Scene 1 I need to pass a variable and I do that with:
//Handles the selection
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
Guests *myGuests =[guestList objectAtIndex:[indexPath row]];
selectedGuest = [[NSString alloc] initWithFormat:#"You have selected %#", myGuests.guestID];
[self performSegueWithIdentifier:#"TGG" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"TGG"]){
GuestDetailsViewController *vc = [segue destinationViewController];
[vc setGuestSelected:selectedGuest];
}
}
In Scene 2 (details) I use this to verify that the right variable was received like this
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
NSString *msg = [[NSString alloc] initWithFormat:#"You have selected %#", guestSelected];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Selection" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
nameCell.textLabel.text= msg;
[super viewDidLoad];
}
All of this works fine and the alert box shows the right variable and there is a transition to the new scene. HOWEVER, the alert box displays a total of 5 times over & over and, once completed, the whole window is black. Nothing from my scene (Scene 2) is displayed at that point. So I know I have the right segue, it transitions as desired, I just can't see anything on my screen.
i ran into a situation very similar. i had unintentionally un-commented the method:
-(void)loadView
i believe this method overrides the IB interface and created it from this code instead. check to make sure it is either removed or commented out IMHO.
Related
I am new to iOS development and currently making a sleep tracker application. I want to know if it is possible to put or set up a segue and pass data in one of the buttons that is shown to user after swiping a UITableViewCell like in this screenshot
For reference, here is what I did to the buttons. It works for UIAlertView and changing of ViewControllers, but I don't know if I can apply segues here to pass data from one ViewController to another.
//tableview swipe action iOS8
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *delete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
UIAlertView *confirmDelete = [[UIAlertView alloc] initWithTitle:#"Delete Sleep Record" message:#"Do you want to delete this entry?\n\nWARNING: This action cannot be undone." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Delete", nil];
[confirmDelete show];
}];
delete.backgroundColor = [UIColor redColor];
UITableViewRowAction *edit = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#" Edit " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *evc = [storyboard instantiateViewControllerWithIdentifier:#"edit"];
[evc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:evc animated:YES completion:nil];
}];
edit.backgroundColor = [UIColor colorWithRed:0.188 green:0.514 blue:0.984 alpha:1];
return #[delete, edit]; //array with all the buttons you want. 1,2,3, etc...
}
If it is possible, how can I do it programmatically or through the XIB?
Have u tried
[self performSegueWithIdentifier:#"idSegue" sender:self];
in your delete and edit action handler.
Then implement prepareForSegue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"idSegue"])
{
BViewController *BViewController = [segue destinationViewController];
BViewController.myarray = myarray; // access data and methods of BViewController here using its object
}
}
Hope it helps.. Happy Coding.. :)
So I've been learning iOS for the past couple months and have recently ran into this problem. I have a settings screen inside my app after a log in process that should save some basic information pertaining to the user. The issue is when the view first appears from a tab bar controller, the static grouped table view is blank with none of the information available for the cell.detailLabel.text. I used NSLog to discover that at first when retrieving the objects from keys, they are null. However, when I select a cell to change it's information and push on another view controller, I can then go back and all the values will appear from previous inputs saved to NSUser defaults. I was curious why this happens and for a solution. Thanks
#import "SettingsController.h"
#import <Parse/Parse.h>
#import "LogInViewController.h"
#import "AddSettings.h"
#import "AddUrination.h"
#import "ChooseAlarmController.h"
#interface SettingsController ()
#end
#implementation SettingsController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
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;
UIBarButtonItem *addUrination=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addUrinationView:)];
self.navigationItem.rightBarButtonItem=addUrination;
/*Rename the back button which every pushed on controller will have*/
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
NSLog(#"view loaded");
}
-(void)viewWillAppear:(BOOL)animated
{
/*Everytime view appears, we want to repopulate the table with updated content*/
NSLog(#"Settings View appeared,Load the keys");
/*Load every cell with appropiate details*/
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSIndexPath *path=[NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"FirstNameKey"];
NSLog(#"%#",cell.detailTextLabel.text);
path=[NSIndexPath indexPathForRow:1 inSection:0];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"LastNameKey"];
path=[NSIndexPath indexPathForRow:2 inSection:1];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"NumberOfUrinationsKey"];
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
path=[NSIndexPath indexPathForRow:0 inSection:1];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"StartingAlarmKey"];
path=[NSIndexPath indexPathForRow:1 inSection:1];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"FinalAlarmKey"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)addUrinationView:(id)sender
{
[self performSegueWithIdentifier:#"AddUrinationSegue" sender:self];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// If Log Out Button is selected
if(indexPath.row==0 && indexPath.section==2){
NSLog(#"Log Out selected");
[PFUser logOut];
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Are You Sure?" message:#"If you would like to change your mind, press cancel. Otherwise choose log out" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Log Out", nil];
[alert show];
}
NSLog(#"Selected row is %ld %ld", (long)indexPath.section,(long)indexPath.row);
/*Segue depends on which cell is selected. First section segues to text input (AddSettings.h)*/
if((indexPath.section==0 && indexPath.row<2) || (indexPath.section==1 && indexPath.row==2)){
[self performSegueWithIdentifier:#"AddSettingSegue" sender:self];
}
/*Choose alarm controller is selected*/
if(indexPath.section==1 && indexPath.row<2){
[self performSegueWithIdentifier:#"AddAlarmSegue" sender:self];
}
}
- (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:#"AddSettingSegue"]){
AddSettings *settingsController=[segue destinationViewController];
/*index path contains both the section and row of the selected cell*/
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"Section:%ld Row:%ld",(long)indexPath.section,(long)indexPath.row);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
settingsController.titleOfController=cell.textLabel.text;
}
if([segue.identifier isEqualToString:#"AddUrinationSegue"])
{
AddUrination *addUrinationView=[segue destinationViewController];
}
if([segue.identifier isEqualToString:#"AddAlarmSegue"]){
ChooseAlarmController *alarm=[segue destinationViewController];
NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];
UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
alarm.titleOfController=cell.textLabel.text;
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex==1){
[self performSegueWithIdentifier:#"UnwindToLogIn" sender:self];
}
}
#end
Add [super viewWillAppear:animated] to the top of your viewWillAppear: override. According to Apple's documentation for viewWillAppear:,
"If you override this method, you must call super at some point in your implementation."
While your application generally won't crash or anything if you omit it, important initialization performed by the base class will not occur unless you call [super viewWillAppear:animated], which may result in unexpected behaviour, such as label values not appearing in your table view cells.
As a best practice, you should always call the super method whenever you override one of Apple's methods, unless you explicitly do not want the default behaviour to occur (eg. overriding touchesBegan:withEvent:). Though there are exceptions, generally overridden initialization methods like viewDidLoad and viewWillAppear: should call their super method at the beginning of the method, while overridden teardown methods like viewWillDisappear: should call their super method at the end.
I want to show a specific ViewController (or dismiss) a View after performing an IBAction in my iPhone App. I've tried
[self.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
However this does not appear to do anything once the action has been performed.
A bit more information:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if (selectedCell.tag == 1)
{
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Are you sure you want to delete this project?"
delegate:self cancelButtonTitle:#"No" destructiveButtonTitle:#"Yes, I’m Sure" otherButtonTitles:nil];
[actionSheet showInView:self.view];
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [actionSheet cancelButtonIndex])
{
[self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException
// Delete the project object that was swiped
Project *projectToDelete = self.project;
NSLog(#"Deleting (%#)", projectToDelete.name);
[self.managedObjectContext deleteObject:projectToDelete];
[self.managedObjectContext save:nil];
}
}
I want the current view to disappear when a user presses the Yes button on the actionsheet.
// Assume we are inside a UIViewController (or a subclass)
DestinationController *destinationController = [[DestinationController alloc] init];
[self presentModalViewController:destinationController animated:YES];
...
// Assume we are now in destination controller
// Dismiss
[self dismissModalViewControllerAnimated:YES];
I needed to go all the way back to the first (or, root) view in my navigation stack.
All I need to do was use this method:
[controller.navigationController popToRootViewControllerAnimated:YES];
Another way to show and dismiss a view controller is with pushViewController and popViewController.
To show a viewController:
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
// Uses a horizontal slide transition. Has no effect if the view controller is already in the stack.
And to dismiss:
-(UIViewController *)popViewControllerAnimated:(BOOL)animated; // Returns the popped controller.
I have a table view with a list of strings as follows:
String1
String2
String3
String4
I want to make one of these the default, i.e., when the user taps "String3", an alert view should pop up asking if they want to make that item the default.
How would I implement this alert view in my table view controller?
First you'll want to define an instance variable to keep track of the string that's currently selected. Something like this in your header file will be fine.
NSString *selectedString;
Next, in your tableView:didSelectRowAtIndexPath: delegate method create an alert view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedString = [stringArray objectAtIndex:indexPath.row];
NSString *title = [NSString stringWithFormat:#"Make %# default?", selectedString];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:#"" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[alert show];
[alert release];
}
To save the value after the user taps a button in the alert you should use the UIAlertView delegate.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 2)
{
//Do something with selectedString here
}
}
I don't have enough reputation to comment here. But your if statement should be:
if (buttonIndex == 1)
{
//Do something with selectedString here
}
That is to say if you want to do something when the yes button is clicked. Anyways, thanks for the quick tutorial, and apart from that slight typo it worked perfectly.
I have a problem that I had working in a test but now in a bigger application I can't seem to sort out.
First of I have a view that has six button each loads a different view I am using:
- (IBAction)showInfo2:(id)sender {
InfoViewController *Infocontroller = [[[InfoViewController alloc] initWithNibName:#"InfoView" bundle:nil] autorelease];
Infocontroller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:Infocontroller animated:YES];
}
This seems to be working fine, and loads the next section, in this case 'infoview'.
I then load a tableview and fill it full f data from an xml feed, this again is now working, (although was not an easy task for me!).
The problem comes when I know try and use:
Nothing seems to happen, ie, the new view is not loaded.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here -- for example, create and push another view controller.
SubInfoViewController *subInfoViewController = [[SubInfoViewController alloc] initWithNibName:#"SubInfoView" bundle:nil];
[self.navigationController pushViewController:subInfoViewController animated:YES];
[subInfoViewController release];
}
I know its being called because this works:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *message = [[NSString alloc] initWithFormat:#"You selected a row"];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Row Selected" message:message delegate:nil cancelButtonTitle:#"Yes I did" otherButtonTitles:nil];
[alert show];
[message release];
[alert release];
}
Any help more than welcome, and please be gentle newbie :)
You're view is probably push into navigation stack but you can't see it because your parent view is modal.
You can't try to display your SubInfoViewController like this :
SubInfoViewController *subcontroller=[[SubInfoViewController alloc] initWithNibName:#"SubInfoViewController" withBundle:nil];
[self presentModalViewController:subcontroller animated:YES];
[subcontroller release];
If you want to keep a navigation logic in your app, you should not display your InfoViewController modally but present it in a common way in your navigation stack.
You can try to dismiss your modal view before pushing your SubViewController. In this case you must do something like this :
SubInfoViewController *controller=[[SubInfoViewController alloc] initWithNibName:#"SubInfoViewController" bundle:nil];
[self.parentViewController pushViewController:controller animated:YES];
[self dismissModalViewControllerAnimated:YES];
[controller release];
You'll receive a warning because parentViewController may not respond to pushViewController: animated: but with a NSLog you'll see that your parentViewController is actually a UINavigationController.
Hope this helps !
What exactly is the problem? Your code looks fine at first glance.