Cannot bring up UIView on different tab with Storyboard - ios

I created a storyboard for my app which contains the following:
Initial view controller on my storyboard is a Tab Bar Controller (let's call it myTabCtrlr)
myTabCtrlr has forward segues pointing to several other controllers:
a. First segue points to a custom UIViewController (let's call it vc1) on which I create an interactive UIView (let's call it popview1) which is initially hidden. There's a button (let's call it showPopView1) on vc1's view which when clicked would show popview1
b. Second segue points to a navigation controller, which embeds a view controller with 3 buttons, each pointing to an (end) controller.
c. Third segue points to another navigation controller with a similar setup as (b)
On several of these (end) controllers, there's a button similar to vc1's showPopView1 that when tapped, I'd like to switch back to vc1 and programmatically bring up popview1, which I'm doing as follows (but it's not working):
myTabCtrlr.selectedIndex = 0;
//I get a handle to vc1 then
vc1.popview1.hidden = NO;
When I do that, it goes back to the first tab and shows vc1 view (which is good) but it does not show popview1. I tried many different ways to do it but no luck.
Note that if I'm actually on vc1 and I tap the showPopView1 button, then popview1 comes up normally.
Does anybody know why that is the case? This only started after I transitioned to using storyboard. thanks.

After spending hours looking at various ways to solve this problem, and focusing on reverse segues and similar methods, I was able to solve it using a totally different method.. I wanted to share this with others so nobody has to waste so much of their time (although I noticed slow response to my post. Maybe I didn't make the subject attractive enough :)..
It's a really simple solution, but quite effective. I used a Singleton pattern object. When coming from the rest of the tabs, I set a flag in the singleton that vc1 checks in its viewWillAppear method, shows popview1, and immediately resets the flag.. works like a charm!

Related

Switching between UIViewControllers in story board

As someone who usually used separate xibs in the past I thought I'd give storyboard a go as it seemed a lot simpler to use and much easier to develop with. I've been writing an application where the essential set up is this:
At the top of all this is a UINavigationController (first level). Then I have Multiple UIViewControllers (second level) with buttons in them which you can tap to switch between the second level UIViewControllers.
However a problem occurs when I start switching between the second level UIViewControllers. I first thought this was an initialisation problem with the NSMutableArrays because in my code I have a NSTimer set to loop periodically and found when I set a breakpoint during it, when I went forward to the next timer tick event there appeared to be different instances of the same NSMutableArrays and it seemed a gamble to try and insert new values into these array with it sometimes working, sometimes not (as it may or may not insert into the correct instance).
Then, looking at the memory usage under Debug Navigator I found the issue. Each time I "switched" between the UIViewControllers a new UIViewController was being initiated, along with all new variables.
The code I am using to switch between them is
-(void) perform {
[[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:NO];
}
Or essentially a push segue transition. This also explains why when I tried to switch back to my view, the data on that view was lost as it is a complete new view.
Does anyone know how to switch between multiple ones of these UIViewControllers (say 5) essentially like a UITabViewController would except without the tab bar being present?
First option you can do this: You can use a tabbarcontroller for switching viewcontroller and hidden the tabbar. Then on buttonclick setthe tabbar index.
Second option you can do this: Create one more view controller and in this viewcontroller subview the all switching viewController and when you want to switch viewcontroller just bring that viewcontroller view to front by delegate.
Do you need the navigation bar and other features provided by your top level navigation controller?
If not, you could use a UIPageViewController instead.
You set up all your second level view controllers and then just have to tell the page view controller which one to display.
If you implement the associated delegate methods, it will automatically provide swipe gestures to switch between them and nice animations to get them on and off screen.
You can also get it to put a UIPageControl at the bottom showing a dot for each VC with the dot for the current VC highlighted.

My Navigation Controller Count Keeps Growing

I'm new to iOS dev and am not entirely sure on Storyboards/Segues/Pushing and Popping.
So in my app I have a navigation controller with 5 view controllers leading from one to another.
When it reaches the last view controller i have a segue to the first and I have a few tasks listed in the prepareForSegue method.
Out of curiosity I decided to check what happens to the [self.navigationController.viewControllers count]. I found that it keeps growing and growing which doesn't 'feel' correct.
Am i handling going back to the first screen correctly? The prepareForSegue method is useful as it allows me to send some data back to the first segue. Is it possible to maybe say when you go back clear all views on that navigation controller?
Thanks
You can use an unwind segue. Here's a good tutorial:
pragmaticstudio.com/blog/2013/2/5/unwind-segues
Make sure to create the unwind action method before you wire it up in the storyboard otherwise it won't show up when you drag to 'Exit'. That was the most confusing part for me when I first set one up. The tutorial does it in the correct order so if you follow it you should be fine.
Also, here's a sample I put together showing how to transfer data back in an unwind segue. It uses a modally presented view controller but the technique is the same:
github.com/soleares/AddToTableView
No, you should never go backwards with a segue (other than an unwind). Segues ALWAYS instantiate new controllers, so you're not actually going back to the first controller, you're just creating a new instance, which gets added to the stack. So either go back with an unwind segue or use popToViewController:animated:. Using an unwind segue will allow you to use prepareForSegue, and it does cause all the controllers in between to be deallocated (if you have no other strong pointers to them).

About passing data between view controllers with delegate

FIRST SCENARIO:
I have two view controllers
VC1 has a button, and a label
VC2 has a button, and a text field
theres a modal segue between VC1 -> VC2
when I run this segue, we set VC1, as the delegate for VC2.
We go to VC2, fill out the text field, hit the button, and VC2 is dismissed.
some delegated method is run on VC1, and VC1.label is filled in.
question: is there any way to do this without dismissing VC2.. for example, if VC2.button just modal segues us back, or slides us back to VC1 im assuming it re initializes the viewcontroller and the label wont be changed. do you always have to dismiss the view controller
SCENARIO 2:
again, two view controllers.
this time its reversed.. so i have
VC1 with a textfield and a button
VC2 with a label and a button
soo now we fill out VC1, and we expect it to show up on VC2. But without a segue, they have no relationship. is there any way to pass data between VCs using delegation without one initial segue? Is this segue requirement to use delegation something specific to view controllers? Im assuming it is because in other cases we just instantiate objects, and use their delegate methods. but with view controllers we want to reference one that is already created, and not instantiate a second one.
note: im using story boards
1) You could do it without dismissing VC2, but it's not a good idea. You don't want to segue "back" to one, because, as you surmised, you're actually creating a new instance of VC1, and then if you segue again to VC2, you're creating a new instance of that too. You will keep piling up more and more instance of the two controllers and none will ever be deallocated.
2) Again, your instincts are correct -- you need to somehow get a reference to the instance of VC2 that your putting on screen in order to set yourself as delegate. You don't have to have a segue to do that, you could create the second controller in code and do a manual push or presentViewController, but that's functionally, the same as doing a segue.
Sorry, dont fully understand what you want .. but here is my take.
FIRST SCENARIO:
Why would you need to update the view that isnt on screen ?
Just update in viewWillAppear.
Otherwise you can have the delegate update it when you finish editing that textfield.
SCENARIO 2:
You need a link between the view controllers, use segues makes easy, set as delegate and pass along the info. Why make it harder than it needs to be
Many things have delegates, textfields etc, you are just saying this class / obj will do something for something else.
There are many youTubes about delegates, ie
http://www.youtube.com/watch?v=eNmZEXNQheE
For more info see this stack post - it covers everything you need to know
Passing Data between View Controllers

Trigger action between simultaneous visible View Controllers

after searching, looking and experimenting I continue to fail at a specific problem.
I am a programming novice, so by chance I simply did not use the right search term - so please bear with me in case I created a duplicate.
Here is the situation I'm struggling with.
ViewController 1 has two UIToolBars. The upper Toolbar Button displays a value, the lower Toolbar Button triggers an action in ViewController 2 which happens to be a TableViewController embedded via a container view.
The reason for that is - I need the keep the ToolBars in place while scrolling the TableView.
I use a delegate protocol to send the value from VC2 to the upper Toolbar in VC1, works fine.
But I fail to trigger the action in VC2 using the lower toolbar in VC1.
I kindly want to ask three question:
1.) What is the best practice to trigger the action / solve the problem ?
2.) How would the code look actually like when using a method named "theButtonWasTapped" on VC2 ?
3.) Is the method to embed the TableView via a container view the right way or is there a better way?
I tried to read through various documentations, but I don't even know where to start in this case.
Any help would be greatly appreciated since I'm sitting on this frustrated for days already and don't know where my mental block ends and my absent knowledge starts.
Thank you so much!
If VC2 is embedded in a container view, then it will be a child view controller of VC1. Therefore you can access it from VC1 with self.childViewControllers[0]. So you should be able to do something like this in VC1:
-(IBAction)toolBarButtonTapped:(id) sender {
SecondViewController *vc2 = self.childViewControllers[0];
[vc2 methodInVC2];
}

iOS - pushViewController vs presentModalViewController difference

What is the difference beetween calling presentModalViewController and pushViewController, when :
animation is set to NO (even if yes, that's just an animation style that can be changed).
a navigation controller is defined when presenting the modal view, so it can be navigable too, with a call stack, ....
Is this just to be able to go back from the first pushed view ? Woooaaaaaa.....
I guess the difference is elsewhere and deeper. No ?
Ignoring transitions/animations and how things are structured behind the scenes (which aleph_null's alswer provides a good discussion of), the only user-facing difference is the ability to return to the preceding view automatically using the navigation bar.
If you use pushViewController you will automatically get a "Back" button in the navigation bar. If you use presentModalViewController you do not, and generally will have to implement your own controls and/or callbacks to handle dismissing the controller.
Conceptually the modal presentation style is generally used for atomic tasks that you cannot navigate away from (i.e. you either complete the task, or you cancel, and you cannot do anything else within the app until you do one or the other).
If you're wondering why have the difference in the first place, I can't say. Personally I think frameworks that provide a unified API for moving from one controller to another (like cocos2d, or Android) make a lot more sense.
The most important difference is about semantics. Modal view controllers typically indicate that the user has to provide some information or do something. This link explains it more in depth: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
Here's another, less abstract difference they talk about:
"When you present a modal view controller, the system creates a parent-child relationship between the view controller that did the presenting and the view controller that was presented. Specifically, the view controller that did the presenting updates its modalViewController property to point to its presented (child) view controller. Similarly, the presented view controller updates its parentViewController property to point back to the view controller that presented it."
Also see this thread: why "present modal view controller"?
Take a look into the viewControllers in the image
The top 2 viewControllers(login & submit) at the top left are disconnected from the tabBarController & NavigationController
The rest of the viewControllers are embedded in a NavigationController. They somehow belong to the natural flow of the app.
Now you have to ask yourself
Do I need to always show login + submit page every time? It would be pain in the neck for the user to each time go to login even if they logged in last time. These 2 screen really don't fit the natural flow of the screens. So what do we do? We just add them modally using presentViewController
However for the rest of the viewControllers we want to keep them inside 2 navigation so we can easily go back and forth so we use pushViewController
For more information I recommend you to see this video
The image was also picked from this great answer. It's worthy of a look.
This is what my experience says,if you want to manage a hierarchy of views,better go for pushViewController in the navigation controller. It works like a stack of view-controllers in the navigation controller. If however the requirement is just to show a view on executing some actions on the parent view controller then the best way is presenting it modally.
If you need a complex push pop logic always prefer a pushViewController.
UINavigationController are used when you want to have some sort of hierarchal representation of your data (ie drill down). They work using a stack of UIViewController subclasses. Every time you “drill down”, you simply add another view controller to the stack. Then, the “back” logic is simply a matter of popping view controllers off of a stack.
You can check out this link:
http://www.icodeblog.com/2011/10/11/back-to-basics-an-introduction-to-view-controllers/

Resources