I am new to iOS development and having a fundamental question as how i can re-use same view controller from two different view controllers to perform a specific function.
Here is my problem.
Say we have three view controllers A, B and C. And C performs a specific function and it's output i want to use in both A and B.
Say A, has two edit box A1 and A2 and a button "Call C",
A1 is edit box that user fills in and to take input for A2, we have to call C by pressing "Call C" button that i have segued in storyboard.
Similarly B, has two edit box B1 and B2 and also a button "Call C".
B1 is edit box that user fills in and to take input for B2, we have to call C by pressing "Call C" button that i have segued in storyboard.
Essentially i want to make use of C for two different view controllers where C will return some string to calling view that i can fill in B2 or C2 edit boxes.
Here are two ways to unwind:
Method - A:
Programmatically you can call performSegueWithIdentifier to caller view controller and return to it, but in this process called view controller (i.e. A or B) gets re-created, so input that may have been done by user on control A1 or C1 is lost as A and B views are re-created.
So i can programmatically unwind but state is lost of calling view controller as it gets re-created.
Method - B:
In both A and B i create unwind methods like:
-(IBAction) receiveDataFromCtoA:(UIStoryboardSegue *)segue
-(IBAction) receiveDataFromCtoB:(UIStoryboardSegue *)segue
respectively.
But in view C, i can only unwind in Exit to either of the two functions however it does allow me to retain value of calling view controller controls A1 / C1.
So unwinding from Exit works as expected, but i can only unwind to either of the two and thus i can't reuse view controller C for both.
So whole point is how you can make use of a view controller which takes some input, performs some calculation and return results and can be used by any calling view.
I did look at following post:
Unwind segues for 2 View Controllers
But it does not answer.
Any help is appreciated.
You should be using delegates in order to achieve this.
Delegates and Data Sources
I would suggest looking here for more info
How do I create delegates in Objective-C?
Related
I working on alarm clock app and Im trying to pass data from B controller (the one in the middle of picture) to the previous one (which is A) . As you can see B view controller contains UIView which is “filled” with static table view controller (C).
I can pass data back from the B to A with delegate , it works fine, but I don’t know how pass data from the C to A (using segue and delegates?). C controller is inside B controller.
I just tried simply with segue (As you can see I created segue between C and A) and delegate, but It didn’t work and I really don’t know if it’s the good idea or practice.
To call protocol method I use this code in C controller (function parameter is just for testing purposes):
override func viewWillDisappear(_ animated: Bool) {
self.delegate?.passAlarmSettings(test: 1)
}
Or maybe I should pass from C to B and then from B to A? Or is any better way to do it?
Thanks for any suggestions
If a view controller A is modally presented and it contains a container view containing a view controller B.
Then if B wishes to dismiss itself (which in effect is also effectively dismissing A because B is contained within A) then should B call self.dismiss() or self.parent?.dismiss()?
Since B is a separate entity and B may not necessarily be contained in A, if B wishes to dismiss itself, it can call self.dismiss().
There will be 2 cases. If B is presented by itself, then it would dismiss as usual. If B is contained, then the OS would see that it's contained within A, then dismiss A.
However, if the only use of B is to be contained in A, then it makes sense to let A handle the navigation. The part where B "wishes" for itself to be dismissed can be done using delegates or blocks.
Assume that we have 3 view controllers: A, B, and C. A is the root view controller, which has presented B, and B has in turn presented C. How can we perform a custom unwind segue from C to A that does not reveal B?
A - B - C
A UIStoryboardSegue has a reference to its source view controller as well as its destination view controller, but what about the view controllers in between (B in our example)? We can perform whatever animations we want on C, but I don't see how we can affect B in any way.
The goal is simply to dismiss all but the root (B and C) to the right while having A come in from the left, so both source and destination are swiping horizontally next to each other. B should not be visible at any point of the animation.
My example dismisses only two views, but I hope to find a solution that would apply to an arbitrary number of views. Furthermore, I am not interested in solving this using a UINavigationController. I have tried simply dismissing B, which does indeed dismiss C as well, but you can still see both B and C during the animation.
You can dissmiss your controller as below :
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil) // you need to track viewcontroller's stack hierarchy
If I have a storyboard that contains 3 views - a root, and two 'child' views that the root view can segue to. Is it possible for the children to segue to the other child, and then when its complete, return back to the root?
In my case, the root view may segue to view 'A' or 'B' depending on some event. However, its possible that some event in 'A' may require view 'B' to be displayed, and when its done it should return back to root. i.e., the steps of naviation would be: Root -> ChildA -> ChildB -> Root.
Currently, I have the app setup to unwind from ChildA back to root, and have it then display 'B'. Two issues arose from this method:
Unable to segue to a new view when the unwind segue is still in operation. I had to hack around this, and currently have a performSegueWithIdentifier being called with a small delay to get around it. Obviously a bad hack.
The root view controller is displayed for a moment until the new segue starts & completes.
I figured I could have A segue to B, but then when B was done, the unwind operation that I want to go back to root would have to unwind two items on the view stack??
I'm sure there has to be an obvious design choice that handles this type of thing right?
I figured I could have A segue to B, but then when B was done, the unwind operation that I want to go back to root would have to unwind two items on the view stack??
Unwind operations are not required. In your case, it might be better to have A segue to B, and when B is done, segue to root. No unwind required.
If, however, you want to stick with unwinding, Craig Phares posts how to perform multiple unwind animations without showing intermediate controllers (i.e. you would pop right back to root).
Hope this helps!
First, I believe you mean "view controller", right?
If that's the case, there are many ways you could navigate from A to B. However, it seems like you're using the NavigationController in an unusual way.
For example, is it necessary to have a segue from the root to B? If not, then maybe you should create a single segue from A to B and, when you're at B, you can use "popToRootViewController" to go back.
Or maybe you could present B modally instead of having a "show"/"push" segue to it. In that case, you would have to go back to A before going to the root.
Anyway, once you're at ViewController B, you can popToRootViewController and you'll get back to your root.
I have three view controllers A, B and C.
C is the target.
From A, I have a segue named showCFromA to view controller C.
From B, I have another segue named showCFromB to view controller C.
Now, when C is displayed (shown from B), I tap on the "Back" button, but at this stage, it shows A, and not B as I expected.
How can I fix that?
Don't mess with Back - it makes for a disjointed app experience. You end up at a place you don't expect to be and navigation just doesn't feel right.
If you have a B on the stack, you can just
popToViewController:animated:
to return to the specific view controller (B) that you want to see.
If you have gone from A directly to C with no intervening stop at B, you can't go there with back. Instead you should just push a B.
If your B should be on the stack - i.e. you went from B to C - then B is where you should end up if you simply go back. If that is currently not the case you need to post some more details to help diagnose the problem.
What is confusing right now is what you actually have on the stack. You mention being at A and going to C, then being at B and going to C, but the order in which you do this (and if these are two separate cases) affects the outcome.
After checking the source again, I found the issue is not properly handling navigation vc stack. When push new VC from B, when viewWillDisapper is called (B), I added "popViewController". Therefore, navigation view controller array has count of 2 (the middle element is removed). This makes strange behavior: From view controller C, I cannot go back.