Reload / Refresh tab bar items in a ViewController ? - iphone

I am trying to change images of my tabbar in a ViewController, but to display the new images, I must click on each tab bar item.
for (CustomTabBarItem *myItem in self.tabBarController.tabBar.items){
myItem.enabled = YES;
myItem.badgeValue = #"1";
UIImage *myImage = [[UIImage alloc] initWithContentsOfFile:[[DesignManager sharedManager] getPathOfFile:#"test.png"]];
*myItem.imageSelect= *myImage; // change images of each item. don't appear if I dont click on the item
}
Anyone know How can I can display directly these images?
Thanks

You need to replace the old tab bar item with a new one. You can't update the image dynamically otherwise.
The easiest way to do this is to set the tabBarItem property of the view-controller represented by a given tab. If you wanted to do this from within that view controller, just write:
self.tabBarItem = [[UITabBarItem alloc] initWithTitle: #"title" image: myImage: tag: nil];
Or, you could do this from somewhere else, say your app delegate:
UIViewController* vc = [tabBarController.viewControllers objectAtIndex: 3];
vc.tabBarItem = [[UITabBarItem alloc] initWithTitle: #"title" image: myImage: tag: nil];

I know this is an old question. I ran into the same problem when I need to update the badge value from another active tab. Creating another UITabBarItem will solve your current problem but causes potential memory leak when this code is called many times. Plus, when other view controllers access the tab, they do not have reference to newly created UITabBarItem. My trick is
vc.tabBarItem = vc.tabBarItem;
It works for me.

Related

SSCollectionView SSCollectionViewItem - no Items displayed

I ran into difficulties with SSCollectionView and SSCollectionViewItem.
First of all I'd like to get it initialized from IB. But that won't work for me.
I have a SelectFooViewController which is:
#interface SelectFooViewController : SSCollectionViewController { ... }
and am using it as filesOwner of the corresponding XIB.
SelectFooViewController* selectFooVC = [[SelectFooViewController alloc]
initWithNibName:#"SelectFooViewController" bundle:nil];
But since it wont work I had to initialize its properties inside viewDidLoad() myself.
Furthermore I am not able to display anything except the backgroundColor of my SSCollectionViewItems. What I want is a textLabel and an image .
- (SSCollectionViewItem *)collectionView:(SSCollectionView *)aCollectionView itemForIndexPath:(NSIndexPath *)indexPath {
SSCollectionViewItem *item = [[[SSCollectionViewItem alloc] initWithStyle:SSCollectionViewItemStyleImage reuseIdentifier:itemIdentifier] autorelease];
SSLabel* label = [[SSLabel alloc] init];
[label setText:#"foo"];
item.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"foo.png"]];
item.textLabel = label;
[label autorelease];
return item;
}
I can confirm that the delegate methods (for determining the number Of rows, sections and such) are implemented and working as expected. But my items are all empty - but react onclick with the expected popup.
Does anyone see an error in what I did? - Thanks...
EDIT: I was also not able to display a local image by changing SSCatalog project
I just figured out, that I have to set the frame of each property (textLabel, detailTextLabel and imageView) myself. That fixed it.
When you create instance SelectFooViewController just insert this line
selectFooVC.view;
or
selectFooVC.view.hidden = NO;
And then add it to the view.
This is because the view is not initalised until you explicitly access it. Hence your items are loaded only when you click it and not immediately. You can call it a hack but i don't call it one. :-)

UIButton buttonWithType:101, Will they reject my app?

Greetings,
In one of my projects I wanted to create back type button(with pointer) in the navigation bar, I googled around and found that using the following code, it can be achieved.
UIButton *someButton = [UIButton buttonWithType:101];
UIBarButtonItem *someBarButton = [[UIBarButtonItem alloc] initWithCustomView:someButton];
I want to upload this app on Apple's app store.
Is there any chance that this will get my app rejected, since buttonWithType:101 is not documented any where?
Also i m not using this bar button item in its generic way, i.e. it wont pop the view controller.
Please guide.
Regards,
I propose that you generate Image for your need, just by running this code and delete it after you generate the image:
- (void)viewDidLoad {
...
someButton = [UIButton buttonWithType:101];
UIBarButtonItem *someBarButton = [[UIBarButtonItem alloc] initWithCustomView:someButton];
self.navigationItem.leftBarButtonItem = someBarButton;
...
}
and
- (void)viewWillAppear:(BOOL)animated {
....
UIImage *img1 = [someButton backgroundImageForState:UIControlStateNormal];
NSData *newData = UIImagePNGRepresentation(img1);
NSFileManager *fileManager =[NSFileManager defaultManager];
BOOL filecreationSuccess = [fileManager createFileAtPath:#"/Users/macbookmac/Desktop/tester.png" contents:newData attributes:nil];
...
}
most probably yes.. in some cases, few things do slip under the radar, but why take chances..
if you are doing this for your client/company, would you risk having a rejection from app store on your hands..
its safer to create a pointed button image and use it with custom button...
If you are trying to control what text appears in the Navigation controller's back button, you can do that with the UIViewController's UINavigationItem. It can contain both the title for the current view and the text to use for the next view's "back" button. This can be set in XIB as well.

Implementing my own navigation controller?

I have a tab bar app. Under one of the tabs i want a uisegmentedControl in the top navigation view, that controls what view is currently displayed. This is dead easy if i just exchange the view, but i want to do it in a more organized and generic way, by using one uiviewcontroller for each view and exchanging them in the most optimzed way.
i guess step one would be to know exactly what a tabbar controller sends to a navigation controller/view controller when a tab is changed, and work it out from there.
Can any one point me in the right direction?
Some time ago I stumbled upon SegmentsController which I found in this blog entry from red artisan.
I used it in conjunction with a UITabBarController, but without knowing I did it wrong. Not wrong as in "it crashs" or "it doesn't do what i want" but wrong in the sense that I have to forward each UIViewController call (like viewDidAppear, receivedMemoryWarning etc) to the child viewControllers. The app with the wrong code is still in the app store and I never received a complain about it.
But I played around a while and figured out how to use it right. It's a bit of a hassle but imho it's absolutely worth it.
I'll show you the correct version that I have right now, I'm creating the UITabBarController in Interface Builder so I have to change the tab in code. Which introduces another piece of mess, and maybe there is room for improvements. But right now I'm satisfied with this solution.
NSMutableArray *items = [self.tabBarController.viewControllers mutableCopy]; // tabs from tabbar configured in IB
// The two child vc that will appear in the segment control
SomeViewController_iPhone *tvcs = [[[SomeViewController_iPhone alloc] initWithNibName:#"SomeView_iPhone" bundle:nil] autorelease];
SomeOtherViewController_iPhone *tvct = [[[SomeOtherViewController_iPhone alloc] initWithNibName:#"SomeOtherView_iPhone" bundle:nil] autorelease];
NSArray *viewControllers1 = [NSArray arrayWithObjects:tvcs, tvct, nil];
// the nav controller acts as a wrapper around the child viewcontrollers
UINavigationController *navController1 = [[[UINavigationController alloc] init] autorelease];
navController1.tabBarItem.title = NSLocalizedString(#"FirstTab", nil);
navController1.tabBarItem.image = [UIImage imageNamed:#"tabImage1.png"];
navController1.navigationBar.tintColor = [UIColor navBarTintColor];
firstTabSegmentsController = [[SegmentsController alloc] initWithNavigationController:navController1 viewControllers:viewControllers1];
// uses a NSArray category that basically creates a NSArray that has the title properties of the vc in viewControllers1
firstTabSegmentedController = [[UISegmentedControl alloc] initWithItems:[viewControllers1 arrayByPerformingSelector:#selector(title)]];
firstTabSegmentedController.frame = CGRectMake(0, 0, 222, 30);
firstTabSegmentedController.segmentedControlStyle = UISegmentedControlStyleBar;
firstTabSegmentedController.selectedSegmentIndex = 0;
[firstTabSegmentsController indexDidChangeForSegmentedControl:firstTabSegmentedController];
[firstTabSegmentedController addTarget:firstTabSegmentsController action:#selector(indexDidChangeForSegmentedControl:) forControlEvents:UIControlEventValueChanged];
// replace first tab from interface builder with this
[items replaceObjectAtIndex:0 withObject:navController1];
as you see it needs a bit of setup, but in my opinion this solution is better than anything else I've tried throughout the time. I hope I de-NDAed the code correctly.
Edit: Uploaded a sample project: BeautifulColors.zip
Just exchanging the views and keeping up with the current view's viewController is the best way to implement a UISegmentedControl in this regard.
Note: by exchanging the views i mean adding a subview to the current view and removing the old one.
You might be interested in the method below, which is implemented by the UITabBarControllerDelegate
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;

Change title of UItabbaritem in other view?

How do I change the UITabbaritem titles when starting the App?
I got a UITabBar with 4 tabs. I want the user to be able to change between two different languages. If the user chooses a different language I need to set a different title to the UITabbaritems. I know I can use self.title = #"title"; but that only changes the current tabbaritem title. How can I change all the titles at once, on load, and when choosing a different language?
I got the same problem and solved it with.
[[self.tabBarController.viewControllers objectAtIndex:index] setTitle:#"Your title"];
Where index is your UITabBarItem index.
You need to store all your UITabBarItem into an array, when the user tap the button, you need to loop through that array and set the title.
for (UITabBarItem *item in items) {
item.title = #"WHATEVER HERE";
}

navigationItem.prompt & UIImagePickerController

Is it possible to make calls to navigationItem on a UIImagePickerController? Specifically, the image picker? Below I've linked an image of what I'm trying to achieve ( screen shot taken from another app doing the same thing). Once the user selects an image from the picker the navigationItem.prompt is set and, though I think it might be a HIG violation, the right bar button is changed from the standard cancel button. I can set the prompt on a "normal" view no problem with:
self.navigationItem.prompt = myString;
But this does not seem to work when I try to use it in the context of a picker with:
myPicker.navigationItem.prompt = myString;
I've tried using it when the picker is created and also in didFinishPickingMediaWithInfo: which is really where I need to set it as I'm letting the user select multiple images instead of dismissing the picker as soon as one image is selected. Nothing seems to work.
Here's a image of the desired behavior:
http://i51.photobucket.com/albums/f353/zoso5th/after.png
Someone answered this for me on the Apple dev forums:
UINavigationBar *bar = picker.navigationBar;
UINavigationItem *navItem = bar.topItem;
navItem.prompt = #"Some new prompt";
I wasn't correctly accessing the navbar.
Someone answered this for me on the Apple dev forums:
UINavigationBar *bar = picker.navigationBar;
UINavigationItem *navItem = bar.topItem;
navItem.prompt = #"Some new prompt";
I wasn't correctly accessing the navbar.
Use the code after calling 'presentModalViewController'.....like below...
[controller presentModalViewController:imagePickerController animated:YES];
UINavigationBar *bar = picker.navigationBar;
UINavigationItem *navItem = bar.topItem;
navItem.prompt = #"Some new prompt";