ios: Navigation to another screen using modalTransitionsytle attribute, crashes the app - iphone

I have Navigation interface which I use to pop to setting screen everytime uses presses settings button.
#interface Navigation : UINavigationController
{
}
-(void)popToMainMenuAnimated:(BOOL)animated;
//.m file
-(void)popToMainMenuAnimated:(BOOL)animated
{
UIViewController *element;
for(element in self.viewControllers)
{
if([element isKindOfClass:[MainSettingClass class]]){
self.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:element animated:YES]
}
}
}
App is crashing with below Exception.
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'
* First throw call stack:
NOTE: This not root screen but 3rd sceen of my application.

Base on the debug log you gave I got a reason by searching:
MainSettingClass instance that you pushed before can neither be repushed to the array on navigationController again, nor be presented modally. You should create a new MainSettingClass instance and present it, just like the second code snippet.
HERE is a relate question that mentioned Application tried to present modally an active controller. :)
-(void)popToMainMenuAnimated:(BOOL)animated
{
UIViewController *element;
for(element in self.viewControllers) {
if([element isKindOfClass:[MainSettingClass class]]) {
self.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:element animated:YES];
break;
}
}
}
But why not load the Main Menu instead of pop?
-(void)loadMainMenuAnimated:(BOOL)animated
{
MainSettingClass * mainMenuViewController = [[[MainSettingClass alloc] init] autoreleased];
[mainMenuViewController.view setFrame:CGRectMake(0.0f, 0.0f, 320.0f, 480.0f)];
// ...
self.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:mainMenuViewController animated:YES];
}
And the code you show has some mistakes:
self.modalTransitionStyle= UIModalTransitionStylePartialCurl;
[self popToViewController:element animated:YES];
self.modalTransitionStyle= UIModalTransitionStylePartialCurl; if you set this one, you need use
[self presentModalViewController:yourViewController animated:YES];
not
[self popToViewController:element animated:YES];

It appears that the 'MainSettingsClass' UIViewController you're picking out and attempting to present (modally) is already active. It would help if you put up the code where this view controller may have been previously pushed/presented (and ideally popped/dismissed).
Here are a couple of related questions that might help you.

Related

unable to switch from multiple views

I have a simple app with only location services and 3 (almost empty) different views, and from some reason I can't get from view 1 to view 2 - app crashes and I get an exception. View 1 is the original .xib file, the two others are just views that I added later. It's weird cause I can switch between all of them (1->3, 2->1, 2->3, etc..) just not from 1->2.
I use this code in #1 view controller m. file:
- (IBAction) switchToMaps : (id)sender //this is the one that doesnt work
{
MyMap *mapsView = [[MyMap alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:mapsView animated:YES];
}
- (IBAction) switchToThird : (id)sender
{
ThirdView *third = [[ThirdView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:third animated:YES];
}
and as another example, here is the code from the 2nd view controller (MyMaps.m):
- (IBAction) switchBack : (id)sender
{
LastLocationViewController *firstView = [[LastLocationViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:firstView animated:YES];
}
- (IBAction) switchFront : (id)sender
{
ThirdView *lastView = [[ThirdView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:lastView animated:YES];
}
I know it's super vague, but any ideas what can cause this? I have no idea how to debug this...I even put breakpoints at the beginning of each IBAction method, and when it crashes, it doesnt even stop there....before I added this code, this app (which has only location) worked totally fine.
Any ideas?? Thanks!!
if your view does not load from any nib file then you should do like
MyMap *mapsView = [[MyMap alloc] init];
and
ThirdView *lastView = [[ThirdView alloc] init];
and in your back method
- (IBAction) switchBack : (id)sender
{
// LastLocationViewController *firstView = [[LastLocationViewController alloc] initWithNibName:nil bundle:nil]; // because you are allocating new memory to your last view
// [self presentModalViewController:firstView animated:YES];
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction) switchFront : (id)sender
{
// ThirdView *lastView = [[ThirdView alloc] initWithNibName:nil bundle:nil];
// [self presentModalViewController:lastView animated:YES];
[self dismissModalViewControllerAnimated:YES];
}
My hunch is that you're throwing an exception because
MyMap *mapsView = [[MyMap alloc] initWithNibName:nil bundle:nil];
is failing to load a nib. Without seeing your console output it's impossible to say for sure. So a few things to try:
Comment out [self presentModalViewController:mapsView animated:YES];, see if it still crashes.
Explicitly name the nib you expect to load. The nib loader assumes the nib is named exactly the same as the view controller if you pass in nil. So if you don't have a match, you'll end up with an exception (Like this [[MyMap alloc] initWithNibName:#"NibNameWithoutExtension" bundle:nil];)
Set a breakpoint at [self present... and then hover your mouse over "mapsView" after execution pauses. If the popup thing shows you mapsView is nil, you know your trouble is trying to pass a nil object to -presentModalViewController:animated:. If your breakpoint never hits because you throw an exception first, well, there you go, the trouble is a line above.
edit:
One more thing. If your nib has a button that's wired to an action that no longer exists, that would definitely get you in trouble. Inspect each button and make sure no actions are labeled in yellow, indicating a mismatch between the button's target and the actions it's reporting to IB. This would definitely account for the breakpoint behavior you described.

Presenting a modal view controller when loading another ViewController

Before the user can use my application he has to login. After he logged in, the database is built because I need information from the server to build it.
Therefore my root ViewController is the LoginViewController which presents the actual application (a navigationController stack) modally on successful login.
If the user is already logged in on application launch (I am storing the credentials with NSUserDefaults) the LoginViewController should present the application immediately. Therefore I overwrote the method:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSInteger userId = [[NSUserDefaults standardUserDefaults] integerForKey:#"selfUser"];
if (userId != 0) {
//[self performSelector:#selector(presentMainViewController) withObject:nil afterDelay:2];
[self presentMainViewController];
}
}
- (void)presentMainViewController {
mainViewController = [[MainViewController alloc] init];
mainViewController.managedObjectContext = managedObjectContext;
navigationController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:NO];
}
The [self presentMainViewController]; is executed but the controller does not show up. If I use the line above it does work.
Where do I have to put the code to make it work?
The view stack might not be completely created when viewDidAppear is send. So you should use the perfomSelector:withDelay to queue the call on the run loop. In this way you can ensure that the view stack is build when your code runs.
Cheers!
I had a similar situation and I resolved by moving the code to viewWillAppear (instead of viewDidAppear). It may worth to try.

Problem with info view on iPhone app

I am currently using this code to bring up an info view for an iPhone app.
-(IBAction)showInfo:(id)sender {
InfoView *info = [[InfoView alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];
info.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:info animated:YES];
[info release];
}
And this code go back to my main view
-(IBAction) exitInfo:(id)sender {
[self.parentViewController dismissModalViewControllerAnimated: YES];
}
When I run it on the simulator, it goes fine, however, on the actual iPhone, when I press the button that triggers the exitInfo method, it carries out its animation, but once it is completely off the screen and only my main view is visible, the screen will flicker, quickly showing the info view again. How can I fix this?
In my opinion, your viewController shouldn't even know it is modally viewed.
Try putting the code that send the dismissModalViewController message in your main controller and alert your main controller that the user clicked the dismiss button using a delegate.
something like this in your "parent" viewController
-(IBAction)showInfo:(id)sender {
InfoView *info = [[InfoView alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];
info.modalTransitionStyle = UIModalTransitionStylePartialCurl;
info.delegate = self;
[self presentModalViewController:info animated:YES];
[info release];
}
-(IBAction)closedButtonClicked {
[self dismissModalViewControllerAnimated: YES];
}
and in your "Modal" viewController
-(IBAction) exitInfo:(id)sender {
[delegate closedButtonClicked];
}
Of course you will need a protocol like
#protocol MyCustomDelegate
-(IBAction)closedButtonClicked;
#end
and something like this in your "modal" interface
-id<MyCustomDelegate> delegate;

iPhone - unrecognized selector sent to instance - Trying to open the starting view after viewing several other views

I am just starting with iPhone programming. I used the utility application project template. A button on the main view of the utility application calls another view which shows some data. At the end of the presentation of the data a "end" view is shown. The "end" view contains a button to return to the main view. This all works great, however once you return to the mainview and try either to click the info button or click the button to call the data view the application terminates with the following error:
-[TheEVController startS]: unrecognized selector sent to instance 0x3933d90
EVController.m
- (IBAction)done {
EVController *controller = [[EV alloc] initWithNibName:#"MainView" bundle:nil]; //controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
MainViewController.m
- (IBAction)startS {
SVController *controller = [[SVController alloc] initWithNibName:#"SView" bundle:nil]; controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
Any suggestions?
If you want to call startS, which is a method on a MainViewController object, you can't call it on an EVController object.
[TheEVController startS];
tells the Objective-C runtime that you want to invoke the startS method in the TheEVController's class (or one of its parent classes).
It's not entirely clear from the code you posted (you didn't actually show us the section of code that is causing the exception) but from your description it sounds like you're overwriting a UIView variable that initially points to your MainViewController with a pointer to an EVController, and not resetting that variable when you show your MainViewController again.

How to load subview from the main view?

I am very new to Obj-C and learning iphone development.
My question is how to add subview from app delegate.
Lets say I added subview called "MainView" from "applicationDidFinishLaunching" method.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MainViewController *aViewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = aViewController;
[aViewController release];
[window addSubview:mainViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
"MainView.xib" file has a button to show its child view. When the button is clicked, it calls "showChildView" method.
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.view insertSubview:childViewController.view atIndex:0];
}
From this code, when app launches, it shows "MainView" with a button. But when I clicked the button, the button is still visible as well as the content from the "ChildView.xib" file too.
How can I hide the "MainView" when I pressed the button and show only the contents of the "ChildView"?
Thanks for your help in advance.
well, you have to remove the original view first, before inserting the new subview, do it this way
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.mainViewControlle.view removeFromSuperView];
[self.view insertSubview:childViewController.view atIndex:0];
}
Hope this helps.
You might want to check out the Utility App sample -- it demonstrates switching between two views with animation and adding/removing views from parent views.
you might want to create a navigation controller in the main view and than push the childviewcontroller onto it when invoking showChildView. You'll get the back navigation button for free that way