I have two UIViewControllers, both of which are embedded in UINavigationControllers. UIViewController A contains a button that, when clicked, presents UIViewController B which contains a MKMapView. UIViewController also contains a button that dismisses the view to go back to UIViewController A. But, the issue is that when I dismiss UIViewController B, UIViewController shows up but is frozen. Nothing is interactable and user interaction is disabled. However, I do see a semaphore_wait_trap when I pause the program in the debugger after the app freezes. But the weirdest thing is that the app works fine and does not freeze when I disconnect from XCode and use it then. So is this an XCode issue or am I doing something wrong? Any help is greatly appreciated!
Related
I have a navigation controller with 4 child views: vc1, vc2, vc3, and vc4. I have them all connected to one another using storyboards and not programmatically. I have a button in each scene that has the segue connected to it that pushes on the following scene and I get the built in back button with it.
This weird bug that happened to me today has only happened to me once before and that was about 2-3 months ago. I tried to reproduce it but since it's so random I can't.
Anyhow when I pressed the back button in vc3 to get back to vc2, vc3 kept showing itself (vc3) several times. It was as if it was going back to itself. After about 3-4 times of it showing itself it eventually went back to vc2.
I don't have any code to show only because this is in IB. When it first happened I found a blog post on it that said it was a common back button problem but the post didn't say anything about a fix. I dismissed as a 1 time error but today it happened again on the same exact scene which means it can happen again.
1 thing to note is I had an iPhone 5 and I saw it happen a once or twice inside the Settings menu. It never happened again.
Anyone know anything about this issue?
I use UITabBarController as the root controller, each TabBarItem has its own UINavigationController, the first UITabBar (0) refers to the UIViewController which displays the results from the server. The fifth UITabBar (4) includes the MoreFormViewController (it is the successor of the FormViewController from the Eureka framework) it has several cells (two are currently implemented). Clicking on one of them opens SettingsFormViewController (this is the successor from FormViewController from the Eureka framework), the first cell contains UISlider, which changes the settings for getting data from the server (which are displayed in UITabBar (0)). If this parameter changes, then when we return back to the MoreFormViewController, we automatically make the transition to UITabBar (0). If you quickly switch from UITabBar (0) again to the MoreFormViewController and open the SettingsFormViewController, the application is frozen. Found out the following that at this point SettingsFormViewController is initialized and all life cycle methods are triggered (viewDidLoad, viewWillAppear, viewDidAppear and so on). But the screen is not visible, then I looked at UI View hierarchical in Xcode, and it shows that the very first controller is SettingsFormViewController as it should be. All this time I checked on a real iPhone 7, then I decided to check on the simulator and iPhone 5, they did not find such a bug on it, everything works correctly. During the next test, when the application "froze" on the iPhone 7, I accidentally folded it and unfolded it and I saw this screen and it completely works. But if you repeat the same action, then again the application "freezes."
I was looking for information on this, but at the most I found that people simply "frozen" the application because they were pushing the controller out of the main thread. So I do not know what to do. Can you tell me how to solve this problem?
Also I tried to replace the SettingsFormViewController with a regular UIViewController with a slider, the result is the same. Removed everywhere isUserInteractionEnabled = false even in third-party frameworks to know exactly what is not the problem.
I've updated my custom alert class (which is a UIWindow subclass) in iOS8 to set its rootViewController to the UIViewController it is being presented on. This enables the app to automatically rotate my custom alert instead of having to do it manually.
It works well but I'm finding one situation where it doesn't rotate: when I'm on the UIViewController that appears when the app is first launched (which also happens to be the rootViewController of my app delegates window property).
Is this because UIViewController can't be the rootViewController of two UIWindows or is it a bug? Does anyone have a work around for this? It works perfectly on every other UIViewController that I display an alert.
I have a UITabBarController that has four UIViewControllers. These are set up in the app delegate and everything behaves as expected.
I have set the first UIViewController as the UITabBarControllerDelegate and that works fine too; as tabs are pressed shouldShowViewController fires as expected.
Inside the first UIViewController, the first tab, are buttons. One pushes another UIViewController using the standard:
[self.navigationController pushViewController:vc animated:YES];
This works just fine: the new UIViewController and it's view appear as expected.
However, when I press the tab button the shouldShowViewController function is called (as expected) and passes a reference to the first tab (as expected) but the child UIViewController is nowhere to be found. That is, viewController.navigationController.viewControllers is an empty array (count == 0).
To debug I implemented the UINavigationControllerDelegate and assigned the navigationController to the same class from the UIViewController and tab controller. It fires when called from the tab controller but not the view controller.
I've tried everything I can think of to find a reference to the topmost visible view controller but I'm stumped; it seems to vanish into a black hole. I"m ready to try to keep the stack manually but trying to keep a parallel array with system functionality built into it seems like a setup for a maintenance mess. I am using iOS6.
I changed navigation in my application from using UITabBarController to u UINavigationController. I.e. former solution (1st version) was based only on the TabBarController - 4 ViewControllers (one simple TableView, one simple custom view and one MapView with many overlays). The second version is based only on the UINavigationController.
In case of TabBarController it was clear and simple, everything worked fine, especially MapView. I mean: the MapView was loaded once (with a significant number of overlays) and when I went to another view and back to the MapView the MapView was still there with its overlays already loaded and displayed (simple check: MapView`s viewDidLoad was called just once per app run, I had some debug messages there).
Now I changed navigation logic to the UINavigationController. Everything works fine for the first look - but: the viewDidLoad (for each view) is called everytime I navigate to the view. It is annoying especially in the case of the MapView - the loading of overlays is performed everytime, it takes some time and it causes app crash in some cases.
OK, my questions:
Is it some kind of "common" behavior of NavigationController?
Can I change this behavior so viewDidLoad will be called just once?
And more - How can I influence the "display sequence" of some view?
I understand the logic is probably more complicated but I appreciate any answer or hint ;)
Some related circumstances:
TabBar and Navigation controllers are not combined.
I use storyboards, segues are designed in the UIB, no manual calling like perfomSegue or prepareForSegue in my code. One button triggers segue to MapView.
I use push segues.
I also tried to use modal segues but without any change of that behavior.
any of viewDidUnload is never called during segues among the views.
No memory warning received.
No memory leaks measured both on simulator and iPhone 4.
I tried to build a very simple temporary project / app that is concerned just about the Nav. Controller and other views without ANY coding, just storyboard. It was the same behavior.
There was an issue that causes app crash when I fast and periodically tapped to navigation button and back button between one view and the MapView. In most cases the app crashed when I tapped the back button on the MapView before it was fully displayed (i.e. its overlays). It was fixed when I added a 1 sec. delay method call in the viewDidDisappeared in the MapView. It is not a fair fix, I know ;)
A UITabBarController and UINavigationController are based on fundamentally different paradigms.
The UITabBarController is intended for the UIViewController on each tab to exist independently of each other and for the user to choose which they want to view. viewDidLoad only gets called once for each UIViewController because it is intended that each tab still exists in memory even as the user switches to a different tab.
The UINavigationController is a stack of UIViewControllers where each is related to the one above and beneath itself. The top UIViewController in the stack is always the one that is visible to the user. When a UIViewController is pushed to the stack, its viewDidLoad gets called because it is being loaded into memory. When the top UIViewControllergets poped off the stack, it is unloaded from memory, and viewDidUnload gets called on the way out (viewDidUnload is deprecated in iOS6 and won't get called, but the controller will still get dumped from memory). This is why viewDidLoad gets called every time that the user pushes a particular UIViewController onto the UINavigationController stack.