UITabBar reload UIView on touch - iphone

Is it possible to call a method when a tab bar icon is touched, even if its already the selected icon? I want to make it remove a sub view when touched if the subview is showing.
I'm sure there must be a way to do this because I see it in other apps, but I cannot find any documentation on it.

From Apple Documentation for UITabBarDelegate :
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
Sent to the delegate when the user selects a tab bar item. (required)
As you noticed I think, and as stated by Apple docs, this message is sent only when a tab is selected
An important note, there is already a (not-documented?) default UIKit behavior of tapping a selected tab bar button :
If the tab contains a UINavigationViewController it will send to it a popToRootViewControllerAnimated: message. You can check this on any iOS application.
So beware before overriding this default (and user expected) behavior, which is, generally, a bad idea.
Apple has probably hidden what you want to do in its UIKit API, on purpose.
But if you want anyway does this, here are some ideas:
Small, but not easy hack: Once the tabBar has been displayed, recursively browse its .subviews tree to find (I expect, to be confirmed) UIButtons inherited classes (=private UITabBarButtons or something like) to add your target/selector pairs on TouchUp event (you might have to remove default behavior first, which might be tricky)
Worst solution, but might be the only one: Do not use UITabBar, but a custom class. I'm pretty sure there are ready-to-use open source components that mimics UITabBar, but sorry, I never used/searched one.

You can have delegates for the UITabbarcontroller,
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
Also please go through this document: UITabBarController delegate protocol

Related

what's the events of getting and losting focus in a view controller

There are 2 forms in my program. When view controller A gets the focus and be active, view controller B will lost the focus and be inactive. Can anyone show me What the events are?
Thanks
Miken, it depends on what type of objects you are using for your "forms".
The simplest "form" to use is a UITextField, and in that case, events will be sent to your UITextField's delegate. In a lot of simple cases, you will designate the viewController that holds your UITextfield to be the UITextFieldDelegate. For more information on the methods that the delegate has, take a look at this: https://developer.apple.com/library/ios/documentation/uikit/reference/UITextFieldDelegate_Protocol/UITextFieldDelegate/UITextFieldDelegate.html#//apple_ref/occ/intf/UITextFieldDelegate
In this case, when the text field gets the focus (ie the user clicks on the text field to edit it) the delegate methods:
– textFieldShouldBeginEditing:
– textFieldDidBeginEditing:
– textFieldShouldEndEditing:
– textFieldDidEndEditing:
will be called. I'm using this as a basic example, and not assuming too much here, but generally you should be looking into your "forms" delegate methods.

VoiceOver ignores visible views, and speaks accessibilityLabels of hidden views

I have UIView, that can contain one of two views. When I removeFromSuperview first view and addSubview second view I can still hear accessibiliyLabel of hidden view. And only in 1-2 seconds I can hear correct accessibiilityLabel.
I see that it is common situation when hidden state of view is changed, accessibility can be frustrated and still speak hidden views, and does not note visible views.
Also if in UITableViewCell UIButton is hidden and then hidden state changes to NO, VoiceOver ignores it like it is still hidden. Only manual implementation of UIAccessibilityContainer protocol for cell resolves mentioned problem
No Notifications can solve this issue. Even playing with accessibilityElementsHidden did not help. Struggling with this during several days
Please can you recommend is there any way to say Accessibility that hierarhy of views was changed
You can post a UIAccessibilityScreenChangedNotification or UIAccessibilityLayoutChanged to alert UIAccessibility that the view changed. Since you didn't post any code, I can only give you a generic example, e.g.:
UIAccessibilityPostnotification(UIAccessibilityLayoutChanged,accessibilityelement)
...where "accessibilityelement" would be a button or text field or other accessibility element that VoiceOver switches to next.
Reference: UIKIt Reference
Just ran into this myself with a third party side menu library and had to use accessibilityElementsHidden to fix it. I first tried leveraging the accessibilityViewIsModal property, but that only works on sibling views.
#pragma mark - IIViewDeckControllerDelegate
- (void)viewDeckController:(IIViewDeckController *)viewDeckController didOpenViewSide:(IIViewDeckSide)viewDeckSide animated:(BOOL)animated
{
if (viewDeckSide == IIViewDeckLeftSide) {
[self.topViewController.view endEditing:YES];
self.viewDeckController.leftController.view.accessibilityElementsHidden = NO;
}
}
- (void)viewDeckController:(IIViewDeckController *)viewDeckController didCloseViewSide:(IIViewDeckSide)viewDeckSide animated:(BOOL)animated
{
self.viewDeckController.leftController.view.accessibilityElementsHidden = YES;
}

Local notifications and storyboards

I'm wondering what would be the best way to accomplish my goal. I have an iPhone app that is using storyboards and has a tabbar controller as the root view. Under one of the tabs I need to show a view controller that is embedded in a navigation controller and is about 3 slides deep when a local notification is pressed.
Any ideas of the best way to do this? Going to continue with trying to implement this in a clean way and I will post if no one has a response, but some help in the right direction would be appreciated. Thanks.
This was the method I was after:
(void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
And since I wanted to use existing viewcontrollers that had layouts for my view from the storyboard I pulled them in using this and initialized what I need. Help this helps someone else in the future.
(id)instantiateViewControllerWithIdentifier:(NSString *)identifier
I would use the userInfo property on the UILocalNotification class. Setup a string with the name of the controller you want to show.
Catch the notifications with:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
In the AppDelegate. Then search for the string you save on the UILocalNotification and use the next method in the UINavigationController:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
In order to show the appropiate viewcontroller. If you want your app to show always the same view controller you don't need to setup the userInfo, you only need to implement the UINavigationController method above.
Hope it helps.

Make ajax request upon programmatically switching tabBarController viewContoller

I've been reading through forum posts and banging my head for over 2hrs now and hopefully someone can help point me in the right direction.
I am using the UITabBarController and have 4 root views associated to it.
In the first view, the user can take a picture (UIImagePicker), after which the second view is displayed programmatically. Once the second view is displayed I want to make an ajax request to a server.
I am able to sucessfully select/display the second view with the following code:
self.tabBarController.selectedIndex = 1;
However the UITabBarControllerDelegate method (which is successfully called upon user tabBarContoller touches):
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
is not called, as Apple tabBarController:didSelectViewController documentation states:
In versions of iOS prior to version 3.0, this method is called only when the selected view controller actually changes. In other words, it is not called when the same view controller is selected. In addition, the method was called for both programmatic and user-initiated changes to the selected view controller.
So my question is: "How can I execute some code & make a request after programmatically switching to second view?"
I also tried putting traces in:
-(void)viewDidAppear
-(void)ViewWillAppear
-(void)viewDidLoad
but none of those are called when tabBarController.selectedIndex is set.
Many Thanks
viewWillAppear should be called.. I just tested it.
Another solution: use the UITabBarControllerDelegate with
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
for tracking changes.

viewWillAppear not called in UITableViewController?

I have a couple of UITableViewController classes and I just noticed that these methods aren't being called:
-(void)viewWillAppear:(BOOL)animated;
-(void)viewDidAppear:(BOOL)animated;
I read in http://discussions.apple.com/thread.jspa?threadID=1529769&tstart=0 that I would have to call those methods myself when pushing view controllers, but that's strange, since it works for anything but UITableViewController.
Also makes it a bit of an issue when I need to have a UITableViewCell deselected in the UIViewController that pushed the UITableViewController.
I can't find it in the documentation, but I think this might be because you are using a UINavigationController.
How about setting the UINavigationController's delegate property and then implementing UINavigationControllerDelegate? It provides two optional methods:
– navigationController:willShowViewController:animated:
– navigationController:didShowViewController:animated:
For example, navigationController:willShowViewController:animated: might look something like this:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[UITableViewController class]]) {
[viewController viewWillAppear:animated];
}
}
Anyway, this will get you the behavior you want without having to hack calls to viewWillAppear: all over your project.
Did anyone resolve this because the original post is correct - simply using UITableViewController and pushing the table view of that controller onto the navController does NOT trigger these methods despite the fact that it should. I have a series of UITableViewControllers and table views that are pushed and popped to display hierarchical data - nothing fancy, but the "viewWill/Did/Appear/Disappear" methods are never called. Only the viewDidLoad and viewDidUnload are called.
There must be a wiring problem in both our setups, but simply pushing a view into the navigationController should be all that is required (?) - hard to believe that this could have gone unnoticed as a fundamental bug this long.
?
These two methods are called by default to notify for the changes. UITableViewController is a subclass of UIViewController, so there will be the same behavior. You can see more in the View Controller Programming Guide
The viewWillAppear: and viewDidAppear: methods give subclasses a chance to perform any additional actions related to the appearance of the view.
How do you know that these methods are not called? Can you provide some more codes, or at least you test them with a NSLog() to see if there are some messages printed.
I'm seeing the same problem. I have a simple UIView from the IB and I do a addSubview with a class that extends UITableViewController.
I can see the view of the TableViewController without problems in my application, but the viewWillAppear function is never called in this situation.
Well, the discussion linked from the question has the answer right in it. UINavigationController needs to receive the "viewWillAppear" message in order for it to send those messages to the view controllers you push onto it.
So ironically if you don't do what Apple recommends, and you subclass UINavController for your view controller, then everything works great.
However, if you just create a UINavController inside of your view controller, then you need to implement "viewWillAppear", "viewDidAppear" and so on and forward those to your nav controller.
Note that this is especially important if you're using Three20, because its view controller hierarchy expects the "viewWillAppear" message to be received. If its not you can end up with TTTableViews that don't draw.
The same can occur if you use a UITabViewController. You need to force the viewWillAppear call by implementing either the UITabViewControllerDelegate or UINavigationControllerDelegate callbacks
This explanation may help: http://www.mlsite.net/blog/?p=210