This is so weird to me. Yesterday I think I had this same crash once on an iPhone4 ios6 device. Today I tried running my app in the simulator and it is reliably crashing on me when I call pushViewController. Here is the code that crashes it.
PFObject *selectedGame = [self.myTurnList objectAtIndex: index];
[self.myTurnList removeObjectAtIndex:index];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
GuessWordController *guessWord = [storyboard instantiateViewControllerWithIdentifier:#"GuessWordController"];
guessWord.game = selectedGame;
//[self performSegueWithIdentifier:#"toGuessWord" sender:self];
[self.navigationController pushViewController:guessWord animated:NO];
return;
I've put a bunch of NSLog's in there and everything seems to look great all the way to the return statement. However I get 'EXC_BAD_ACCESS' thrown and no output to the debugger. I also have NSLog's in my GuessWordController's viewDidLoad and none of them show up.
I have tried changing pushViewController to doing a segue that I set up with the storyboard instead and that seems to work. But I wanted to do it with pushViewController because I don't want the animation.
Is there any reason the way I have this set up would cause the app to crash, specifically ios5.1?
Why not use the segue and create a custom segue with no animation?
It's a lot easier than what you're trying to do.
From the docs here...
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomSegues/CreatingCustomSegues.html#//apple_ref/doc/uid/TP40007457-CH16-SW1
You can use this function...
- (void)perform
{
// Add your own animation code here.
[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:NO];
}
Then delete all that stuff you have and just use [self performSegueWithIdentifier:#"toGuessWord" sender:self]; instead.
Then in prepareForSegue you will need...
GuessWordController *controller = segue.destinationViewController;
controller.game = selectedGame;
This should work.
Related
When I called:
[self.navigationController pushViewController:SOME_VIEW_CONTROLLER animated:YES];
the app randomly stuck (it didn't crash, so no error log). Have tried debugging it with no result.
Note that:
I called this pushViewController from a UIViewController category.
Is there any problem with that?
I am not using storyboard
The problem persist randomly (it doesn't happen all the time)
When it stuck, viewDidAppear won't be called (viewWillAppear, viewWillLayoutSubviews, viewDidLayoutSubviews still
called)
the problem never occured when I use animated:NO
Some code snippets:
- (void)routeToBookingDetailsForCustomer:(BookingModel *)booking {
VTBookingDetailsForCustomerViewController *vc = [VTBookingDetailsForCustomerViewController new];
vc.booking = booking;
[self.navigationController pushViewController:vc animated:YES];
}
Just found another thread with similar case:
pushViewController stuck or viewdidappear fail
I think you have to pass Nib name as well like this
- (void)routeToBookingDetailsForCustomer:(BookingModel *)booking{
VTBookingDetailsForCustomerViewController *vc = [[VTBookingDetailsForCustomerViewController alloc]initWithNibName:#"VTBookingDetailsForCustomerViewController" bundle:nil];
vc.booking = booking;
[self.navigationController pushViewController:vc animated:YES];
}
Nib name means your XIB name whatever XIB name for your VTBookingDetailsForCustomerViewController, you have to pass this in initWithNibName:#"yourXIBname"
Have you tried this approach?
someViewController *someVC = [someViewController alloc] initWithNibName:#"someViewController " bundle:NULL];
someVC.someVariable = someValue;
[self.navigationController pushViewController:someVC animated:YES];
Edit : Just saw 'Dipen Chudasama' already answered!
Are you using custom transition animations by implementing UINavigationProtocolDelegate combined with UIViewControllerInteractiveTransitioning?
I struggled with this issue in my own application and it turned out that I was incorrectly starting an interactive transition which I never finished. In this case all debugging showed me that the controller was pushed but UI was not updated until my app changed states.
Please try pushViewController code in main queue.
dispatch_async (dispatch_get_main_queue(), ^{
VTBookingDetailsForCustomerViewController *vc = [VTBookingDetailsForCustomerViewController new];
vc.booking = booking;
[self.navigationController pushViewController:vc animated:YES];
});
EDIT
After some more digging around it has become apparent that if i try to call a segue from the view controller class after a fast application switch to/from Safari i get an exception stating that the segue does not exist. It definitely does, in the VC that is loaded on screen, and i have checked the spelling and it's 100% correct.
What makes it even weirder is that if i call that exact same method from an IBAction it works fine.
Here's the code i am using:
-(void)goToPhotoPage{
[self performSegueWithIdentifier:#"twitterAuthComplete" sender:self];
}
If i call this when the app resumes i get an exception, however if i call it from this IBAction, attached to a UIButton, with doing nothing different the segue works as expected and no exception.
- (IBAction)twitterToPhoto:(id)sender
{
[self goToPhotoPage];
}
Arrrrgrghrhhgrgrg!
ORIGINAL QUESTION
I am working on an iPad application that uploads user photos to Facebook/Twitter.
As part of the process i have to jump to Safari to do OAuth for twitter, the app then jumps back via a specific URL and get's the tokens e.t.c
However for some reason when the application re-awakes i cannot trigger any segue's or manually load any VC's.
I have a success block in my AppDelegae which get's called when the upload is complete which calls a method in the VC to close a spinner and segue to the success view.
The spinner stops as expected, but no matter what i try i cannot get the segue to work.
Everything is hooked up, the segue has an ID and i get no error or exceptions in the console, just nothing happens. The only way i can get code triggered segue to work after this point is to use a user trigger one connect to a UIButton, after that one complete they start to work again.
Here is the code with callback in my AppDelegate:
- (void)postToTwitter:(NSString*)postText image:(UIImage*)image
{
NSData *data = UIImageJPEGRepresentation(image, 0.5);
[_twitter postStatusUpdate:postText
mediaDataArray:#[data]
possiblySensitive:nil
inReplyToStatusID:nil
latitude:nil
longitude:nil
placeID:nil
displayCoordinates:nil
uploadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
} successBlock:^(NSDictionary *status) {
ViewController * vc = [[ViewController alloc]init];
[vc triggerSuccess];
} errorBlock:^(NSError *error) {
ViewController * vc = [[ViewController alloc]init];
[vc uploadFail:error];
}];
}
in the VC i have tried the following:
- (void)triggerSuccess
{
[self segueToSuccess];
}
- (void)segueToSuccess
{
[self hideMessage];
[self.navigationController performSegueWithIdentifier:#"approveSegue" sender:self];
}
As well as:
- (void)triggerSuccess
{
[self segueToSuccess];
}
- (void)segueToSuccess
{
[self hideMessage];
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"done"];
[self.navigationController pushViewController:controller animated:YES];
}
In a moment of pure desperation i even tried:
- (void)triggerSuccess
{
[self segueToSuccess];
}
- (void)segueToSuccess
{
[self hideMessage];
//[self.navigationController performSegueWithIdentifier:#"approveSegue" sender:self];
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popToRootViewControllerAnimated:NO];
[self performSelector:#selector(segueToSuccessPart2) withObject:nil afterDelay:0.25];
}
- (void)segueToSuccessPart2
{
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"done"];
[self.navigationController pushViewController:controller animated:YES];
}
I've obviously missed something, and i'm guessing it's to do with the application going into the background and the VC being "unloaded" from memory, and needing re-instatiating, but i'm not sure where to begin with that.
Any help would be greatly appreciated as i'm about to throw the computer out of the window . .
Thanks
Gareth
Edit 1
After doing some more troubleshooting it appears that during this call in the VC:
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController popToRootViewControllerAnimated:NO];
self.navigationController is nil . . .
I'm guessing that is likely the cause of the issues i'm seeing?
Edit 2
So as suggested by Kelin, i am trying to make sure i retain the Navigation Controller.
I have done the following in AppDelegte:
#property (nonatomic, strong) UINavigationController *navController;
and
#synthesize navController;
But when i try to access this from the VC using the below code, it's still nil . .
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
UINavigationController *navController = appDelegate.navController;
[self dismissViewControllerAnimated:NO completion:nil];
[navController popToRootViewControllerAnimated:NO];
Edit 3
I have also added this to the AppDelegate, which means the Navigation Controller is no longer nil. But still nothing happens . . .
if (!self.navController)
{
self.navController = [[UINavigationController alloc]initWithNibName:#"Main" bundle:nil];
}
The problem is you trying to perform segue from storyboard using programmatically created View Controller.
You use -performSegueWithIdentifier: sender: completely wrong. In this method "sender" is a button, or any other control which action initialises segue, but not the view controller to be pushed.
Usually segue is created with storyboard. But if you really need to create it manually, call:
-[UIStoryboardSegue initWithIdentifier:source:destination:]
where source and destination are view controllers.
Read this: https://developer.apple.com/library/ios/recipes/xcode_help-interface_builder/articles-storyboard/StoryboardSegue.html
or this (about custom segues):
You can not do both dismiss and pop together either you have to pop or dismiss the view controller and
Every ViewController have it's own NavigationController which is default point out to navigation controller you added to AppDelegate.
So, You also can access it by self.navigationController (Edit 3)
Also check whether you initialised navigation controller in
AppDelegate
self.navController = [[UINavigationController alloc] initWithRootViewController:firstVC];
I use the following code to switch between view controllers..(works fine) I have many view controllers too by the way Im not just switching back and forth between 2
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
MyTableViewVC *detailView = (MyTableViewVC *)[storyboard instantiateViewControllerWithIdentifier:#"MyTableViewVC"];
//pass data through to VC
[self presentViewController:detailView animated:NO completion:nil];
I see the memory use climbing as I transition between view controllers
So i did some research and realized Im not dismissing the previous view controller. I use the following code [self dismissViewControllerAnimated:NO completion:nil]; before I call presentViewcontroller: (I also tried using it after) and it doesn't work. If i use it after nothing happens.. using it before I get the following warning
Thread 1:EXC_BAD_ACCESS(code=1.... blah blah let me know if you need the rest
Ive also tried to do something like this..
[detailView presentViewController:detailView animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
What am I doing wrong?
Below is the code to remove VC from the navigation stack.
NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray: self.navigationController.viewControllers];
// [navigationArray removeAllObjects]; // This is just for remove all view controller from navigation stack.
[navigationArray removeObjectAtIndex: 2]; // You can pass your index here
self.navigationController.viewControllers = navigationArray;
[navigationArray release];
However note, by doing this you will have problem to go to previous VC as you are removng the previous VC from the stack.
As you are complaining about memory, I would say DOUBLE CHECK code once again and investigate where memory is getting used more. Incase if that object is not needed, release that object so that memory issue would not be there.
If you want to back to root view controller, you must use this code.
[self.navigationController popToRootViewControllerAnimated:YES];
When i tap my tableview this code gets executed:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
ViewController *vc =[storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
vc.currentCategory = indexPath.row ;
[self presentViewController: vc animated:YES completion:nil];
}
Everything seems to load and it breaks on the breakpoints in the new viewcontroller. But it doesnt get presented. If i tap a second time it does'nt execute the code but it presents the viewcontroller. If i go animated: NO, everything works on the first tap, but not with animated: YES. Any ideas what might be wrong?
I just had the exact same problem and it turned out to be a threading issue. You need to call your presentViewController inside of the following:
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(controller, animated: true, completion: nil)
})
Keep in mind, my answer is using Swift, it should be a simple translate back to objective-c though, but I'm pretty sure your running into a threading issue like I was. Hope this helps people.
Give this a go:
UIView *containerView = self.view.window;
[containerView.layer addAnimation:NO forKey:nil];
UIViewController * otherViewCon = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[self presentViewController:otherViewCon animated:NO completion:nil];
I red nearly all the help which is provided, and i'm still confused. I have simple project in Xcode4.2 with sotoryboard. There i have Navigationcontroller and two Viewcontroler (one, two). If i'm trying to get from one to two with pushViewController its break down. Where is my problem. If i have the Navigationcontroler in my storyboard i shouldn't have problem to access it and use it, is it right? I don't won modal window application i use something like story board where the user can move back and front without lose the controls data. How should i do it right.
thanks for any help I'm new to apple developing :)
The only code :
- (IBAction)Next:(id)sender{
two* myNext = [[two alloc] initWithNibName:#"two" bundle:nil];
NSLog(#"%#", [self navigationController]);
NSLog(#"%d", [[[self navigationController] viewControllers] count]);
[[self navigationController] pushViewController:myNext animated:YES];
// [[self navigationController] pushViewController:myNext animated:YES];
// [myNext release];
}
The solution is to change the initialize UIViewController because of using storyboard you can't use initWithNibName. You have to use instantiateViewControllerWithIdentifier which use identifier property of UIViewController. The identifier property can by set in the sotryboard.
ViewController* myNext = [self.storyboard instantiateViewControllerWithIdentifier:#"Next"];