Present View Controller and Add Child View Controller Cause App Freeze - ios

I have AViewController. Inside A, I have a MapViewController instance. MapViewController is A's Child View Controller.
Now when a button inside A got TouchUpInside, I init a BViewController. and present B.
When init BViewController I pass in the MapViewController to B and stored inside B as an unowned variable.
I need to display the same map for both A and B. Inside B's viewDidLoad, I add MapViewController as Child View Controller for B.
The app freezes when I press the button. No exception, No crash, No error log.
Anyone have any ideas why it happens?
My Attempts:
I tried to use a navigation controller and use pushViewController methods, same result, app freezes
I tried to add MapViewController as child inside B at ViewWillAppear, same result, app freezes
I tried to add MapViewController as child inside B at ViewDidAppear, no more freeze, but map is not there at all.
Instead of present B I tried to add B as childViewController of A, same result, app freezes
I checked all the instructions on running on main threads.
I tried to remove mapViewController as child in A before present B, same result, app freezes.
I tried to add mapViewController as child in completion block when present B, same result, app freezes

This may be a better structure to take. When you switch from A content to B content, you can move / size the elements all you want... And since they will be separate subviews of your "main" view, they can overlap if your interface would benefit from that layout:

Related

preloading viewcontroller for location of barbutton item

I have viewController A
It will present viewController B
I will be layering viewController C over viewController B (tutorial layover)
In order for me to point an arrow image on vc C to an element on vc B I need to know where that element is.
When I try to lay vc C over B to prepare for the animation from vc A to vc B, vc B is not yet laid out because it has not yet been presented. Therefor vc C can't properly place it's arrow image pointing to the element on vc B.
view.setNeedsLayout() and view.layoutIfNeeded() do not work as this only triggers viewDidLoad and viewDidLayout subviews not viewDidAppear. I've tested this and the element I am looking to point to (bar button item) is still not laid out after calling these.
Is there a way to completely layout a viewcontroller in the background before it is presented? I believe this would solve my problem.
update
I want to force draw/layout a view controller
maybe with tbVC.view.setNeedsLayout() and tbVC.view.layoutIfNeeded() ?
Then I want a completion block telling me when this is done.
Then I want to execute some code which accesses the drawn elements (uibuttonbaritem) within completion block.
And I want all of this to be done in the background without presenting the view controller.
Cheers!
To solve this issue you need ViewController C as subview of ViewController B and you need to call ViewController B from ViewContrller A
self.view.addSubView(vcC.view) //instead of vcB use your ViewControler C instance
Hope this will help you

Options for refreshing visible view controller after popping top view controller with UINavigationController

A UINavigationController has two view controllers: A and B.
A is the root view controller. B gets pushed onto A.
The goal is to refresh A's view only when B pops back to A and no other times.
Two options:
Refresh A inside of viewDidAppear. Downside: this may refresh
A other times than when B pops back to A.
Implement a refresh function inside of A, and before popping,
invoke this refresh function from B. Downside: requires iterating
through view controllers to find A (or maintaining a reference to
A inside B) and requires exposing the refresh function publicly.
Any other options? Ideally, UINavigationController would offer some kind of delegate function that gets called whenever B pops to reveal A again.

ViewWillAppear & ViewDidAppear firing when dismissing ViewController

I am making an iOS app where I want to present a flow of pages like this:
Basically I want to achieve is to have this flow of pages:
PageA
PageB
PageC
PageD, dismiss back to:
PageC
PageD
PageE, dismiss back to:
PageA (starting point, start over again)
I am using ShowViewcontroller to present the pages (modal) and DismissViewcontroller to dismiss.
As per Apple's documentation if I dismiss a VC early in the stack all subsequent UIViewCOntroller are dismissed too (Apple doc).
However I experience that ViewWillAppear and ViewDidAppear are fired on the UIViewController that are dismissed even when they do not appear (e.g. in the example when dismissing back to PageA from PageE then ViewWillAppear is called on PageD, PageC, PageB too).
This does not seem logical to me. Can anyone explain why this is happening? And perhaps correct me if I am approaching this the wrong way.
I am using Xamarin.iOS.
Apple doc:
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
The ViewControllers work with a stack. Whenever a new ViewController (of any type) is added to the stack, You lose more and more control of your ViewControllers (especially when using a modal for your ViewControllers). So, say you have 5 ViewControllers in your stack (A, B, C, D, E, as per your example), and assume they are created in the order as stated, in order to return from ViewController E to ViewController A, you'd have to go through the entire stack. That means that every ViewController in your way needs to be displayed first, in order to dismiss is (since you already have ViewController E displayed, this doesn't occur here).
I hope this helps you. Good luck!
Love and regards,
Björn

Is the UIViewController calling the method presentViewController removed from the memory?

Supposedly I have a UIViewController A and a UIViewController B. From A, I call the method presentViewController:B. When B shows up, what happens to A? Is it removed from the memory? If not, what method should I call to delete it?
If my UI flow is like this, A->B->A->B->A->B->... and so on, how to prevent the memory from increasing accordingly?
When you use the presentViewController:animated:completion: method from controller A to present controller B modally, what happens is that the presentedViewController property of A is set to controller B, and the presentingViewController property of B is set to A. Thus, both controllers are kept in memory while the presentation is taking place.
When you go from B to A, you call dismissViewControllerAnimated:completion: on A via the presentingViewController property of B, like this:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
(You can also call [self dismissViewControllerAnimated:YES completion:nil] and the system will automatically forward the request to the presenting view controller.)
After that, the presentedViewController property of A will be set to nil and, consequently, it will be subject to memory deallocation by the system, provided that there isn't any other strong pointer pointing to it.
No, A won't be removed from memory.
And if you want to alternate between A and B you can either:
use a UINavigationController and push B, then pop it off again and you're back at A
or make B the new root controller of your window and then A again and add a proper transition
or use a as the root and present B. Then dismiss B and you're back at A.
The UIViewController will stay in memory unless you popped it.
Use push & pop instead of just pushing new UIViewControllers.
Instead of this A->B->A->B->A->B->
You'll get this A<->B
Have a root view controller when ever A completes it's task let your root view is responsible of removing A and and presenting B. Like wise when B finishes its task alert your root view to remove B and show A again.
It won't be released automatically. You can release it manually by using dismissModalViewControllerAnimated.
Here is a very good tutorial to see this : Link

UIStoryboard popViewController

I'm using a UISegue in my application to automatically transition between viewcontrollers in my application. I'll call them A and B.
It worked as expected, however when I wanted to pop-back to the A from B, I attempted to call
[self.navigationController popViewController] however the B's navigationController property reports null.
As a second attempt I attempted to map a button, to a UISegue back to view controller A.
However this just creates a new ViewController.
As a work around, I ended up doing as a work around was to retrieve the B viewcontroller from the UIStoryboard and calling [A.navigationController pushViewController:B]
At which point, calling [B.navigationController popViewController] worked as expected.
This seems wrong, from a storyboard segue how can I return to the previous view controller?
I don't know about the class of your A and B controllers (whether UIViewController, UITableViewController or UINavigationController), but if you follow the following pattern, it should work.
In an empty storyboard, insert a UINavigationController. This will bring in two windows to the storyboard, linked with an arrow (a segue). The one on the right should be controller A.
In A, let's say, you add a button. The button will push B into the navigation stack.
Then, you add the second controller B, and drag from the button in controller A to controller B, and choose "push" from the popped menu.
If you only use a UIViewController (A) and push B, there is no navigationController to take care of popping.
Hope that help.

Resources