I'm learning to code in Objective-C by developing a simple app.
I'm using a UISplitViewController which has UIBarButtonItem.
When you tap an item on the left UINavigationController, shows up on the right one.
This right one has a button inside which takes you to a web site, controlled by a browser controller; when tapped, up left on the UIBar appears a button to go back/to the previous view.
The problem is that when I tap this button, the app crashes and Xcode tells me the problem is the method viewWillDisappear in the browser controller.
I've checked it up and down dozen times and can't find the error.
Change
[self viewWillDisappear : animated];
to
[super viewWillDisappear : animated];
Your way creates an infinite recursion - method calling itself - visible also in Thread 1 call stack.
Related
I was successfully using SideMenu 2.3.4 in my app, then upgraded to v3.1.4. I made the few mods required to adjust to API changes, then ran my app - it crashed after the following UI actions:
Open the menu by tapping on the nav bar button
Tap on item that loads another view (the menu closes, the new view appears)
Tap on the nav bar button to open the menu again
The menu didn't open in response to that last tap before the app crashed. Under the debugger, I saw that after 2, viewDidLoad then viewWillAppear were called for that new view. After 3, viewWillDisappear, viewDidDisappear and viewWillAppear of that same view were called, all without any change in the display.
The crash happened in viewWillAppear because my code counts on viewDidLoad being the first thing that is called after viewDidDisappear. AFAIK, it is legitimate to count on that, since viewDidDisappear is supposed to mean that the view was closed and thus has to be reloaded and viewDidLoad called before any other life-cycle method can be called, i.e., viewWillAppear should not have been called before viewDidLoad.
Am I misunderstanding the iOS view life-cycle? Is this a bug in SideMenu 3.1.4?
Thanks,
Mark
A closer reading of the docs and articles on the net show that I did misunderstand the life-cycle methods.
There is no opposite of viewDidLoad (e.g., viewDidUnload), but in viewDidDisappear one can do this:
if (isBeingDismissed || isMovingFromParentViewController) {
// Do something - viewWillAppear will NOT be called before viewDidLoad.
}
That eliminates the crash I was seeing.
Mark
Can anyone explain what would cause a call to:
[self.navigationController popToViewController:self animated:YES]
To start, get half-way, then appear to restart, where the popping UIViewController jumps all the way back to the left edge, the animation begins again, and then completes?
It is as if it has been called twice, but to debug I subclassed UINavigationController and placed breakpoints in both popToViewController and popViewControllerAnimated, and only popToViewController is called once.
When I call
[self.navigationController popToViewController:self animated:NO];
It behaves exactly as expected, but obviously without the animation, which I would like to see.
Thanks!
I've seen this on questions before where people added multiple actions for something like "TouchUpInside" and "TouchDownInside".
If you're using storyboards you may want to look at what actions are connected to your buttons.
Or another possibility is doing it through storyboards and code.
I have uncovered the cause - I had an iOS toast UI library that was triggering in the middle of a navigation event that was disruption the transition.
I had issue that every time when I enter a view controller - which is the "MessageListViewController" in the following screen-shot, the keyboard will be automatically popped out.
The thing is I used a UITextView in this MessageListViewController for text input, and when I pop this view controller from navigationController stack, if I leave the keyboard open, then the next time when it was pushed again, this keyboard will be popped out automatically.
If I make the text view resignFirstResponder before I popped out this view controller, then the next time enter it will be fine. However resignFirstResponder manually will make the keyboard dismissing with an ugly animation (manually dismiss keyboard it will make the keyboard always go downing the screen vertically, however the view controller popping transaction is horizontal, so it will look very wired)
I tried to build a simple sample to test the keyboard dismiss behavior - there are two view controllers, one is the rootViewController of the navigationController, and it will push another into the viewController stack, so the pushed view controller contains a UITextView, if I highlight the text view of the pushed one, then go back to the root view controller, the animation works just fine, also the keyboard won't be automatically popped out. So I just don't know why in my project, this keyboard always shows up unexpectedly if I just left the page without manually dismiss the keyboard.
BTW, the following call stack happened between viewWillAppear and viewDidAppear. It looks like triggered by iOS to restore the last state of the UITextView.
- (UIView*)findFirstResponder {
if (self.isFirstResponder) {
return self;
}
for (UIView* subview in self.subviews) {
UIView* ret = [subview findFirstResponder];
if (ret) {
return ret;
}
}
return nil;
}
NSLog(#"%#", [[[UIApplication sharedApplication] keyWindow] findFirstResponder]);
I also tried to track with the key window's first responder when this call stack triggered by keyboard will show notification, and the out put is just "nil".
Thanks guys for helping, I just realized where the problem is, actually I did not declare that the messagelistViewController which I used here is actually a singleton, so it never release even I pop the this out of the viewController stack.
Under that scenario, when the next time this view controller was appear again, the UIKit will be smart enough to restore the previous view state if it's not dealloced.
And in my test sample, I did not keep the test viewcontroller when it was popped out of stack.
so that's why this works fine for my test sample.
Then my final solution is kinda simple, just remove the textview from it's superview when the view did disappear, and then re-add this back when the view will appear.
It turns out my question is a little bit stupid, however it do let me know two things:
1) The view controller will restore to it's previous state every time when it appears if you not delete it
2) The keyboard dismiss animation will always be going down if manually resign the input from the first responder, if we don't want this effect, we shall never dismiss it manually.
I created a demo in iOS 7 as per you said in your question, it was working fine for me even I didn't have to call resignFirstResponder method for resigning keyboard. So you could look in your code as you might have been calling becomeFirstResponder somewhere making the keyboard to be active again or simply post your code here so I could have a look at it.
I just started using the AddThis SDK for iOS in order to share URLs and images from my app.
I have a MainViewController, that calls a Modal View Controller named "SummaryViewController".
This segue is performed after a certain button is pressed on the Main View Controller.
There is a UIButton on "SummaryViewController" that is in charge of sharing on Facebook (or any other, for that matter), and performs:
-(IBAction)shareOnFacebook {
[AddThisSDK shareImage...];
}
The thing is that it works !
So where is the problem? When the user goes back to the Main View Controller, by pressing a "Back" button, opens the SummaryViewController for the second time and presses the "Share" button, the application crashes, with "unrecognized selector sent to instance", and sometime without any message, and the thread is stuck on [ATCoreController topViewController]
Any idea why this happens and how I can fix it? What is different between the first time the VC is shown and the second time?
Thanks a lot !!
in MainViewController.m:
- (IBAction)showSummary:(id)sender {
self.summaryViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Summary ViewController"];
[self presentModalViewController:self.summaryViewController animated:YES];
}
in SummaryViewController.m:
- (IBAction)dismissModalViewController:(id)sender {
[super dismissModalViewControllerAnimated:YES];
}
There is a static method in addthis.h.
+ (void)setRootViewController:(UIViewController *)rootViewController;
You should set rootviewcontroller first time in default it sets your viewcontroller instance, but when you press back and again open summaryviewcontroller it searches for rootviewcontroller or top viewcontroller which was assigned previous one so if that's not available, your application crashes with bad excess.
So use this method to solve your problem before presenting pop-over.
Simplified question: Is there any way to restart the navigationController of an application?. I'm trying to force the application to get his initial appearance.
Long explanation
I've a pet project in iOS and I have a weird problem with the interface that I'd like to solve. I'd like to understand also the mechanics behind this behavior.
I've a simple welcome view, wich shows the splash screen of the application. After that, thread goes to sleep state for 1.5 seconds.
[NSThread sleepForTimeInterval: 1.5];
Then, I'm showing an advertisement view:
AdController *ad = [[AdController alloc] initWithNibName:nil bundle:nil];
[self.navigationController presentModalViewController: ad animated:YES];
[ad release];
And that's all the logic behind. After that, other controllers are pushed without incidence. I want to achieve that, if at any moment the user makes the application go to background (pushing the iPhone/iPad button) then all the controllers must disappear from the stack via pop. In order to get it I'm using applicationDidBecomeActive event from the delegate. The code is the following:
[self.navigationController dismissModalViewControllerAnimated:NO];
[self.navigationController popToRootViewControllerAnimated:YES];
This is driving to some weird visual behaviours. Depending of the moment that the user choose to push de button the transition to the first view is visible. In other cases the ad view is still present, so it is dismissed and then appears the splash screen.
It will be great if there is some way to reset this first controller (splash screen), in order to get all the transitions working as the first time. I've thought about pop it from the navigation controller and the reload another one, allocating again, but it seems a bit complicated.
Is there any simple way to achieve that?
Important Edit: If the user forces repeatedly the application to go background then these exceptions are thrown:
nested pop animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
The easiest way that I've found is to add to the plist file a new row with key "Application does not run in background" and with value YES.
Forces the application to be completely closed and unloaded from memory when the user pushes the button.