How to perfom an action when Tab in a CustomTabBar is pressed? - objective-c

I have a CustomTabBar created working as expected. Apart from selecting tabs, I want to perform an action (refresh some info) on one of my viewcontrollers when this tab is already selected. I mean, I have a tab selected and I press that tab again and fire an action of the ViewController.
Any suggestion?

If your custom tab bar controller is a subclass of UITabBarController then you can provide a delegate that responds to tabBarController:didSelectViewController:. In iOS 3.0 or later this will still fire if the view controller is the same as the one already selected, so you can track this and send your update messages to the correct view controller in this case.
If you don't subclass UITabBarController and have written the tab bar changing code yourself, then implementing a delegate protocol and sending notifications of tab changes and other events is probably a good idea.

Related

Get notified about unsuccessful back swipe gestures in UINavigationController

I have a UINavigationController subclass, which manages a custom navigation bar. This navigation bar's look depends on the top view controller. I ask the top view controller about the type of the bar to be displayed when -pushViewController:animated: or -popViewControllerAnimated: happens.
The problem is, that the navigation bar type change is played when the user starts swiping but I could not find any event which tells me that the swipe was successful or not, so if the user cancels the swipe, I stuck on the previous view controller with the desired navigation bar look of the one below it in the navigation stack.
I have tried UINavigationControllerDelegate, but neither -navigationController:didShowViewController:animated: nor -navigationController:didShowViewController:animated: gets called. My second thought was to use interactiveGestureRecognizer, but it seems it it ends successfully both on successful and cancelled back swipe, and the topViewController is also still the same when the recognizer event is called.
I know, that the top view controller's -viewDidAppear will be called again upon cancelled swipe, but I don't want my users to implement any logic in their controllers to support my navigation implementation.
Any ideas?
Try using the UINavigationControllerDelegate, you can rely on its callbacks to know when a viewController is going to be displayed or not.
Getting interactivePopGestureRecognizer dismiss callback/event

Bar Button Item : IBAction not fired in View COntroller

At the bottom of the Detail View Controller of a Split View Controller, I have added a Toolbar in the Storyboard. I have added three Bar Button Items in this Toolbar. Each Bar Button Item is hooked to its IBOutlet in the private interface of the Details View Controller, and also hooked to its IBAction implementation in the same controller, for example:- (IBAction)shouldPresentView:(UIBarButtonItem *)sender
The main view contains:
A Webview.
A small rectancgle view at the bottom of the screen, below the webview, created and added programmatically, and containing various buttons. All the buttons stay operational.
When touching any of the Bar Button Items, the button is temporary highlighted, but none of the IBAction methods is triggered (a NSLog() statement in every method is never executed).
After searching and reading equivalent topics, I went through several solutions:
I added manually the Details View Controller as the delegate of the Toolbar in the View Did Load method of the Details View Controller.
I emptied the cache of the Derived Data of the Product.
I checked that every IBOutlet has an address and is not nil.
I tried to add an action SEL manually in the View Did Load method for every Bar Button Item.
I removed the rectangle bottom view to be sure that it was not interfering with the responder chain.
I added a Bar Button Item in the Navigation Bar to check if the same problem occurs: no, the Bar Button Item fires the IBAction method.
Any help would be appreciated.
Developing with iOS 7 SDK in Xcode 5.0.2
The issue was coming from a Tap Gesture that I added to the main view to collect touches on the web view. So the touch on the Bar Button Items was probably captured somewhere by the main view before reaching the UIButtonBarItem. I changed the target of the Tap Gesture to the web view – more logical – and the issue has been solved.

Make a view to be the primary one in navigation controller?

I am using a tabbar, each tab having a navigation controller, and this in turn having a stack of views. Each view is having its own view controller but this is not important now.
Lets have a tab 1 with a navigation controller 1 with views A, B, C.
The nature of the application dictates however that the view B is the primary one.
So what I want is that by default (after first or after relaunch of the app), when I tap the tab 1, I will see the B view together with the back button to A view.
How can I achieve this?
You can set up a delegate for your tab bar controller and implement tabBarController:didSelectViewController: to detect when someone taps a tab. If you detect that A is about to be selected and you want B to be displayed instead, you can tell A's controller to use its navigation controller to push B's controller.
Try initializing and pushing view B (without animation) onto the navigation stack in viewDidLoad of view A.
You could use the setViewControllers:animated: of UINavigationController.
Depending on your exact needs you could set this in your app delegate applicationWillEnterForeground: or applicationDidBecomeActive: methods.
I recall there being an Apple sample app that does exactly this. The general idea is to save the last visible view controller (or just hard code the one you want) and then push it to the visible state using something like so:
[myNavigationController pushViewController:viewControllerToBeVisible animate:NO];
You'd want to show the apps tabBarController:didSelectViewController:, and handle the different cases based on which viewController was selected.

NSNotification or Delegate to register for when the visible view changes

I'm developing a project in objective-c for ios, and I have a view with multiple tabs using a subclass of UITabBarController. Each tab has it's own UINavigationController. When a view loads on a tab, the appropriate activation events fire (viewWillAppear, viewDidLoad, etc.). However, once you tap on a different tab, and tap back, not all these events will fire again since the view is already the visible view for that specific tab (viewDidLoad for example).
My question is this: is there a notification or delegate that I can simply register for and get notified when the visible view in the window changes? I've done some research and I didn't find anything specific for this. What I plan on doing is:
Check the visible view when the tab bar index changes: tabBarController:didSelectViewController
Register for this event on each navigation controller: navigationController:didShowViewController:animated:
By doing this, I should be notified whenever the visibleViewController changes by either changing the tab, or navigating within the tab's navigation flow (except for modals, in this case, I don't care about them. They are handled already).
Is this the right approach?
Have you looked at UITabBarControllerDelegate? This method sounds what you are looking for:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
From the documentation:
In iOS v3.0 and later, the tab bar controller calls this method regardless
of whether the selected view controller changed. In addition, it is called only
in response to user taps in the tab bar and is not called when your code
changes the tab bar contents programmatically.
Here's the link: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITabBarControllerDelegate_Protocol/Reference/Reference.html
Hope that helps!
First implement the UITabBarController delegate method "tabBarController:didSelectViewController" and register for it in the app delegate. You can't register for it in each navigation controller. Only one object can be the delegate. In that method, typecast it to a UINavigationController.
Then get the UIViewController by calling "topViewController" on that UINavigationController. Then call the viewWillAppear: method directly on it.

Objective C: How to reload tableview immediately after switching tabs?

I have 2 tabbars in my tabbar controller. I am currently in the second tabbar, after I click on a 'done' button, the tabbar controller needs to switch to the first tab and auto refresh the tableview in it.
I am able to execute on the first part
//Switch to the first tab's view
self.tabBarController.selectedViewController
= [self.tabBarController.viewControllers objectAtIndex:0];
However I need some advise on how to refresh the first view's tableview immediately after the switch is made. Any advise is appreciated.
EDIT: Updated requirement
Note: I do not want the view in the tabbar to reload everytime someone clicks on the tab. The reload should only happen in tab 1's tableview when
1) User is in tab 2
2) User clicks on 'Done button' in tab 2
3) App switches to tab 1 + Reloads the tableview in tab 1
Rationale is that the user will update some information in tab 2 which can only be viewed in tab 1. I want the user to be able to view the updated info immediately after switching to tab 1.
You could just do [tableView reloadData] in the first view's viewDidAppear: method?
EDIT: Editing to add additional data.
General caveat here, Apple tends to frown upon having custom UI Patterns like this. I'm not sure what your app is trying to do here, but you should mostly stick with switching tabs only if the user explicitly clicks on that tab. Have you looked at modal view controllers if you want to present a screen and get some data back, instead of having it in a tab bar?
If not, I guess you could have a solution where the first tab is a delegate of the second tab. When the button is clicked, you could call [delegate doneBtnClicked:] so the control shifts to the first tab. In that function, you could use the setSelectedIndex: to your current tab and call reloadData: on the table view.
You can send NSNotification after
pressing done button on second tab
and handle this notification on first tab controller.
So, create a DONE Button as a UIBarButtonItem, and in it's IBAction, do the following.
For reloading the tableView for the view in the first tab, put that tableView as that class' property , and reference the class like #class class1 , and create an object as a property class1 *object1 for View1 (Tab1) in the class for View2 (Tab2), and access the array1 using object1 like
[class1.object1.array1 reloadData];
And for bringing the view to tab one, use
self.tabBarController.selectedIndex = 0;
Thats pretty much it !
Alternatively you can also use a singleton class for this purpose.