I have multiple tabs that each does something that may interfere with stuff going on the other tabs if not stopped. In case a user forgets to turn off function in one tab before going to the next tab, I want to know if there is a way to run a block of code from the UIViewController when the user clicks the other tab in the UITabBarController.
You should implement UITabBarControllerDelegate protocol in the view controller that has access to the business logic of your stuff. So you can do something when a user tries to click another tab.
It is very likely that you need to implement:
– tabBarController:shouldSelectViewController:
– tabBarController:didSelectViewController:
See documentations for UITabBarControllerDelegate.
Related
Is there a way to prevent the user from dismissing a modal controller?
I think it is pretty common to want to "block" the main Watch App interface while asking the user to open the iPhone counterpart or to perform some action there.
My current solution is to present again the controller when it gets dismissed but its clunky.
There's a somewhat kludgy way to get around this issue using reloadRootControllers. When you call reloadRootControllers(withNamesAndContexts:) with the name of a WKInterfaceController that you've named in your storyboard, it has a similar effect to presenting that controller modally. However, since it's now the root controller, it doesn't have a cancel button. I don't really like this, but it does get the job done.
Note this method is deprecated since watchOS 4.
Apple Documentation on reloadRootControllers(withNamesAndContexts:)
The trick is to make the modal screen fullscreen and change the inset top value for your main group.
You can't prevent a modal interface controller from being dismissed, as the system automatically dismisses it when the title is tapped.
Since your code isn't asked if it should happen, but only knows that it is happening, there's no way to intercept or cancel that action. The WKInterfaceController documentation briefly touches on this.
When the user taps the title string, WatchKit automatically dismisses the modal interface without taking any further actions.
What can you do?
While you don't know when the Cancel title is tapped, there is a hack which "hides" the Cancel title.
This may confuse users who might wonder how to dismiss the modal, or mislead others into thinking the modal couldn't be dismissed.
What does the HIG recommend?
Circumventing a Human Interface Guideline would likely degrade the entire user experience.
The top-left corner of the modal sheet is reserved for the Close button, which dismisses the interface.
Some users might be frustrated or annoyed if
there is no apparent way to cancel, or
the modal presents itself again after repeatedly being cancelled.
Since the user expects to be able to dismiss the modal, perhaps you could allow them to do just that, then simply display some form of reminder in the presenting interface controller (to log in, or enable permissions).
I'm subclassing UINavigationController and want to in order to add the ability to add previously popped view controllers back onto the stack, akin to a forward button in a web browser.
When the user presses a button, I want to add the most recently popped off view controller back onto the stack. I do this by getting the view controller at the top of my custom stack, and calling pushViewController:animated: with it.
In the case where taps on a table view cell or something to go forward a new way into the view hierarchy, I want to clear my "popped view controllers" stack. Similar to how if the user clicks on a new link in a web browser the "forward" history is cleared.
This is where my issue lies. I don't know how to differentiate between when I call pushViewController:animated: in order to restore a view controller, and when the user taps a cell to push one. In the latter case, I want to clear my stack, but in the former I don't want to.
I can't figure out what to do here. In a perfect world pushViewController:animated: would have userOptions: parameter or something on it that would allow me to distinguish between how it's being used, but unfortunately that parameter doesn't exist.
Such an issue must come up rather frequently. How would I deal with it in this case? How would I differentiate between the circumstances in which the method is being called?
If I follow you correctly one common approach to doing this is:
Your "goForward" method should call your superclass' pushViewController:animated:
Override pushViewController:animated: to call both your superclass' pushViewController:animated: and your "clearStack" method.
It seems to me that you need two different methods in your subclass. One for the case where you want to restore a view controller, and one where you want to clear the stack. Both will perform some custom logic and call pushViewController:animated: on super.
I have five tabs in my tab Bar Application. I have give access to 3rd tab on if user enters correct password in popOverController. I wanted to present that pop Over Controller when user taps(selects) that 3rd tab. How should i do it.
Thanks in advance.
Take a look at the UITabBarControllerDelegate Protocol Reference.
In particular consider implementig the tabBarController:didSelectViewController: method of the beforementioned protocol, or even better the tabBarController:shouldSelectViewController: method.
Use UIPopovercontroller to present the login form on ebtering into the tabbarcontrollerview which mean first action in viewdidload. Then verify credentials and remove the login popover. Thats it.
I have a UITabBarController based application. I want to launch a configuration guide - a series of views - the first time the application is launched. That of course have nothing to do with with the normal tab navigation and I want the configuration views to cover the entire screen.
I have a class that supports the UIApplicationDelegate protocol and I tried to launch my configuration view from the application:didFinishLaunchingWithOptions method with the following code:
UIViewController *vc = [[self.mainViewController storyboard] instantiateViewControllerWithIdentifier:#"StartupWelcomeViewController"];
[self.mainViewController presentModalViewController:vc animated:YES];
(the mainViewController is a reference to the UITabBarController)
Apparently application:didFinishLaunchingWithOptions is called before the viewDidLoad for the tab bar views. If I move my code above to a function that is called after the viewDidLoad it works.
I cannot find a method in the UIApplicationDelegate protocol or the UITabBarController class that is called after the viewDidLoad methods in the tab bar views.
Where is a good place to launch my configuration guide and how do I do it?
(Old question, but for the sake of archives...)
If you want your startup wizard to appear on top of the tab view controller, then the tab view controller should present it; you would do that from somewhere like viewDidLoad. If you don't like having that code in the tab bar controller then put it in e.g. the application delegate and just have the tab bar controller call it.
An arguably cleaner alternative is to have no automatically appearing view in your app, instead orchestrating everything from the application delegate - it checks to see if the configuration wizard has been run and chooses to show either that wizard, or the tab bar controller & thus the related UI. In either case, the instantiation code would retrieve the relevant named object from the storyboard in the manner shown in your question. The startup wizard would call back to the application delegate when it was finished using a very simple delegate protocol you'd design yourself, which would give you the cue needed to show the tab bar presumably by calling the same show-tabs method that'd be invoked whether the tab bar was shown immediately, or shown after configuration completed.
This second approach does mean your storyboard is doing less of the work and your code is doing more. In my experience so far, this seems to happen with a certain inevitability as an application matures and its functionality starts to extend beyond the relatively basic flow options provided by automated storyboard behaviour.
Footnote
You prevent a storyboard from showing any view at startup by turning off the Is Initial View Controller option in XCode's storyboard editor's attributes inspector (Command-Option-4) shown when you select whichever controller is currently used for this purpose. It'll be on the leftmost side of the storyboard editor area and have an arrow pointing to it that "fades in from nowhere" left-to-right. Once you do this you'll get a build warning, which is rather annoying; you may decide to add a dummy, blank view controller and set this as an initial view purely to avoid the warning.
which method will be called when i switch between tabs in tabBarController
i know at first time it will call viewDidLoad method ,i want to know is there any method that come in action when i switch to a particular tab (second time or third time ) .
regards
You can use the UITabBarControllerDelegate method tabBarController:didSelectViewController::
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
//do something
}
The method viewWillDisappear: is triggered each time you are about to leave the current view controller (and hence the current tab) and viewWillAppear: is triggered each time a view is about to be displayed.
A full reference for these methods can be found in the UIViewController docs.
This is pretty old, but it does come up on Google and is linked to from another answer. So, I thought I'd update it.
If your UITableBarController is displaying a UIViewController (i.e. its view) then you have to check the ViewController methods that fire when a view disappears and appears. You could use viewWillDisappear to find out if your view is about to be switched away from, and viewWillAppear to test if your view just got switched back to. Notice, the TabBarController typically keeps the ViewControllers loaded, just their views are moved out and in. The problem with using the TabBarDelegate method is that you need to know the name of your viewController, which makes that a dependency. Change the name and it will probably break with xcode's poor ability to rename Class String representations. Avoid it. Besides you don't want a bunch of conditional junk checking to see if your tabbar just loaded a particular tab unless you cannot avoid it. The other thing to notice is that if a particular tab presents a TableViewController you may have to resort to other techniques if you need data in the cells to change in response to being switched away from. I'm using willMoveToWindow:(UIWindow *)newWindow to get notified in the UITableViewCell case when the view goes away. There's probably a better way.