I'm trying to retrieve the value displaying for a specified tab. It was working before and it stopped for some reason? The int current_badge = line on the code below is where the badge value is fetched and returns zeros no matter what the badge value actually is. I'm in a viewcontroller segued off of a uitabcontroller. Anyone have any thoughts on what I'm doing wrong?
UPDATE: It appears to be because I'm in a viewcontroller off of a tab controller. Move the same code into a tab viewcontroller and it works fine. Is there a better way to determine the badge value in a tabcontroller when segued out of it?
-(void)badgeUpdate:(int)tab:(int)dayspan
{
// getting the current badge amount
int current_badge = [[[super.tabBarController.viewControllers objectAtIndex:tab] tabBarItem].badgeValue intValue];
// testing for badge level
if (current_badge > 0)
{
// testing for updates on tab for dayspan or longer
int updates_waiting = [self updatesWaitingCheck:tab:dayspan];
if (updates_waiting > 0)
{
// setting new badge level on tab
[[[[[self tabBarController] viewControllers] objectAtIndex:tab] tabBarItem] setBadgeValue:[NSString stringWithFormat:#"%d", updates_waiting]];
}
else
{
// turning off badge display
[[[[[self tabBarController] viewControllers] objectAtIndex:tab] tabBarItem] setBadgeValue:nil];
}
}
}
The controller for that tab is likely being deallocated when you switch away. I would suggest moving the logic to determine the current count out of the view layer, and into a higher level controller that persists across all tabs. Otherwise, you'll run into the problem you're seeing.
Most of the time, if you're looking for a data value in a view object, rather than in a controller or model somewhere, you're working against the framework and you'll run into problems like this.
Related
I use in my application, the side bar menu like in facebook, so I have different cells in this menu, what I want is to when click on a cell push me to another view controller. I face a problem here which is: the menu is a table view which I don't have it in storyboard, I use some classes from this site:github
and I've stucked here, in my application I use a storyboard, but this menu is programmed with code, and doesn't have a view in stroyboard,
in the didSelectRowAtIndexPath method: I use like this
for(int j=0; j< 9 ; j++)
{
if(indexPath.row == j)
{
DetailsSidebarViewController *essayView = [[DetailsSidebarViewController alloc] init];
essayView.detailItem = [jsonResults objectAtIndex:j];
NSLog(#"%#=%d",essayView.detailItem,j);
}
}
and I create a DetailsSidebarViewController as the new view controller when I push from menu item. in this class, I create a method to configure the view, and just I echo the result:
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
NSLog(#" %# ", self.detailItem);
}
}
the result is true like I want, but I want to push to another view controller, in fact nothing is happened when I click on an item into the menu.
How can I create the new view controller in storyboard? if the menu has not a storyboard, and how can I connect them with segues?
In fact, I am blue with it, please help!!
You should make an instance of the App Delegate class in the Side Menu view controller, and push it from there. You must have a reference to the Side Menu View and a reference to the Center View! Import your App Delegate into the Side Menu controller, and in the didSelectRowAtIndexPath, use:
DetailsSidebarViewController *essayView = [[DetailsSidebarViewController alloc] init];
essayView.detailItem = [jsonResults objectAtIndex:indexPath.row]; // note that you don't need the for loop to know what object you need
AppDelegate* myAppDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[myAppDelegate.sideMenuViewController toggleSideMenu]; // the idea here is that you have to close the side menu, i.e. it must dissapear
[myAppDelegate.centerViewController.navigationController pushViewController:essayView animated:YES];
This is all the code you need.
If I may, as a piece of advice, use Mike Frederik's MFSideMenu instead of the library you're using. In my opinion, it has a more simple and a more straightforward implementation, just look into the README file, everything is explained pretty simple, and it has exactly the code you need!
Hope this helps, good luck!
What I'm doing with this bit of code is grabbing an image sequence, grabbing it's name. Then setting the view's title as the sequences name playing the sequence then setting the title back to the old title.
Problem is the title doesn't seem to be changing on the navigation bar. The NSLogs are outputting the correct values though.
I remember having this issue before and solving it with some "refresh" method.
Here is the pertinent code.
-(void)playSequence
{
if (([animatorViewController isAnimating] == FALSE) && (btnDisable == FALSE))
{
Sequence *tempSequence;
tempSequence = [fullStepList objectAtIndex:lastPlayedSequence];
self.title = [NSString stringWithFormat:#"Assembly - %#", tempSequence.subName];
NSLog(self.title);
[self startAnimator:tempSequence.imageNameScheme forNumFrames:tempSequence.numberOfFrames playInReverse:FALSE];
tempSequence = nil;
tempSequence = [fullStepList objectAtIndex:queuedSequence];
self.title = [NSString stringWithFormat:#"Assembly - %#", tempSequence.subName];
NSLog(self.title);
tempSequence = nil;
}
}
EDIT: This method of changing the title is working else where in this class. The problem seems to come in when trying to set it twice that is causing the issue.
EDIT2: It's actually running both title changes one after another... Fact that it was setting it back to previous was throwing me off.
A navigation item may contains four things: leftBarButtonItem, rightBarButtonItem, title, and titleView. When you need to change the title you should assign your title to navigationItem's title property, not to your view's title property. So it would look like:
self.navigationItem.title = [NSString stringWithFormat:#"Assembly - %#", tempSequence.subName];
self.title points to your viewControllers title which don't shows up in the navigationBar.
The title won't appear to update until after the main run loop executes. Unless -startAnimator:forNumFrames: invokes the main run loop to execute before it returns, you won't see the change.
If you are hosting the UINavigationController inside another view, you need to do this:
self.yourNavigationController.title = #"title";
instead of
self.title = #"blah"
Otherwise you are just changing the title of the view hosting the view navigator. Just a guess.
I recently found myself in a similar situation. My view's title was comprised of a label with an NSMutableAttributedString. Calling [self reloadInputViews] whenever I updated my title worked for me.
The dreaded P.E.B.K.A.C. error was the cause of this confusion. It's actually running both title changes one after another... Fact that it was setting it back to previous was throwing me off.
I am adding a badge to my UITabBarController's UITabBar as such:
UITabBarItem *tbi = (UITabBarItem *)[stTabBarController.tabBar.items objectAtIndex:1];
tbi.badgeValue = #"2";
However, my UITabBarController is customizeable, so the index may change. How can I make sure the badge gets applied to the correct UITabBarItem?
One suggestion you might consider is setting a tag on each tab bar item. You can do this in Interface Builder or when you create the item by code. You can then loop through the view controllers in the tab bar controller looking for the one with the tab bar item you are interested in. For example:
// #define MyTabBarItemTag 999
for (UIViewController *viewController in stTabBarController.viewControllers) {
if (viewController.tabBarItem.tag == MyTabBarItemTag) {
viewController.tabBarItem.badgeValue = #"2";
}
}
UITabBarItem *tbi = (UITabBarItem *)self.tabController.selectedViewController.tabBarItem;
tbi.badgeValue = #"New";
Also works.
Swift version:
self.tabBarController?.selectedViewController?.tabBarItem.badgeValue="12";
I'd use an NSMutableDictionary property on the class that owns the tab bar controller, associating tab names with positions, and a method to retrieve by name:
-(UITabBarItem*)getTabByName:(NSString*)tabName {
return [stTabBarController.tabBar.items objectAtIndex:[[tabDict valueForKey:tabName] intValue]];
}
Initialize the dictionary in your setup code for each tab, since you know the tab index at that time:
[tabDict setValue:[stTabBarController.tabBar.items objectAtIndex:1] forKey:#"myTabName"];
Keep a reference to the tab bar item that you want to modify.
EDIT as a response to your code request:
I believe that there is a single place in your app where you update the badges on the tab bar items. Just add an array of tab bar items (or separate tab bar items) as a member(s) of that class (+ properties if needed) and update the items directly without fetching from the current tab bar items list ((UITabBarItem *)[stTabBarController.tabBar.items objectAtIndex:1];).
For instance, if you decide to keep references to the tab bar items directly (without an array) then the code might look like that:
// Put the next code right after initiating the tab bar and/or after adding new tab bar items to it...
self.newsTabBarItem = (UITabBarItem *)[stTabBarController.tabBar.items objectAtIndex:1];
self.friendsTabBarItem = (UITabBarItem *)[stTabBarController.tabBar.items objectAtIndex:2];
// etc.
Okay, here is my issue: My app has a display of categories in the tab bar at the bottom of the iPhoneOS screen. This only allows 5 categories before it presents the MORE button. I have over 25 (please do not answer this by saying: "Rethink your application...etc" -- that was rudely said before. They are food, drink, etc categories and cannot be changed). I want to allow the user to put their favorites on the home page. The Apple moreNavigationController editing system only allows 20 tab bar items to be rearranged due to space constraints on the editing page. This is not enough so i need to implement my own Editing screen. I set the rightBarButtonItem to nil and created my own. Using NSLog, i can see the "click" happens when clicking the EDIT button, but I cannot push using pushViewController. Nothing happens. I think it has something to do with the navigationController I am addressing...but i am not sure. ps: This all happens in my App Delegate which DOES act as both UITabBarControllerDelegate & UINavigationControllerDelegate.
I tried to do the following:
- ( void )navigationController:( UINavigationController * )navigationController_local willShowViewController:( UIViewController * )viewController_local animated:( BOOL )animated
{
UIViewController * currentController = navigationController_local.visibleViewController;
UIViewController * nextController = viewController_local;
// Do whatever here.
NSLog(#"Nav contoller willShowViewController fired\n'%#'\n'%#'\nThere are currently: %d views on the stack\n",currentController,nextController,[self.navigationController.viewControllers count]);
if ( [nextController isKindOfClass:NSClassFromString(#"UIMoreListController")])
{
UINavigationBar *morenavbar = navigationController_local.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
morenavitem.rightBarButtonItem = nil;
NSLog(#"Is a UIMoreListController\n");
UIBarButtonItem *editTabBarButton = [[UIBarButtonItem alloc]
initWithTitle:#"Edit"
style:UIBarButtonItemStylePlain
target:self
action:#selector(editTabBar:)];
morenavitem.rightBarButtonItem = editTabBarButton;
[editTabBarButton release];
}
}
This works to place an EDIT button at the top right of the screen -- mimicking Apple's look and feel... but when that button is clicked, you cannot exit the darn moreNavigationController.
I have tried many things. UIAlerts work, etc...but pushing (or popping -- even popping to root view) a view controller on the stack does not.
- (void) editTabBar:(id)sender {
NSLog(#"clicked edit tabbar\n");
NSLog(#"Total count of controllers: %d\n",[self.navigationController.viewControllers count]);
TabBarViewController *tabBarViewController2 = [[TabBarViewController alloc] initWithNibName:#"TabBarView" bundle:nil];
tabBarViewController2.navigationItem.title=#"Edit Tab Bar";
[self.navigationController pushViewController:tabBarViewController2 animated:YES];
[tabBarViewController2 release];
NSLog(#"finished edit tabbar\n");
}
If you click the edit button on the moreNavigationController's display page, you get the log entries like expected AND (this is strange) the views on the stack climbs -- but no page change occurs. I marked it down to not using the correct navigation controller...but I am lost on how to find which one TO use.
this is a weird one too. In the edit function if i just do this:
- (void) editTabBar:(id)sender {
self.tabBarController.selectedIndex = 0;
}
It DOES take me home (to tabbarcontroller 0)
BUT doing this:
- (void) editTabBar:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
does not work.
Does the moreNavigationController have some special quality that screws with the rest of the system?
I would try reimplementing the whole "More" functionality from scratch. In other words, store the four home tabs in your user defaults and add a dummy fifth tab that switches to your own complete reimplementation of the more view controller stack.
You could even write a lightweight subclass of UITabBarController that handled this for you.
UITabBarController is evil, so I wouldn't be at all surprised if MoreController had some special properties, too.
I have had success intercepting the More Controller in shouldSelectViewController to change the data source; you may be able to find some workaround there.
PS I am inclined to agree that you could consider redesigning your app so that you didn't need an unlimited number of viewControllers attached to the tab bar just to select categories; you might have better luck using a tool bar with a single, scrollable, custom view in it. If that's really the best way of picking categories for your app, of course.
I'm trying to figure out programmatically if a particular tab bar item in my app has a badge.
While I'm debugging, visually, I can plainly see that it does. But when I run this code in the viewController in question:
UITabBarItem* thisVCsTabBarItem = self.tabBarItem;
NSString* badgeValue = thisVCsTabBarItem.badgeValue;
...badgeValue is nil. And when I inspect thisVCsTabBarItem in the debugger, its _badgeValue member is nil.
What's going on here? Should I be doing something differently in trying to read this value from the tab bar item?
Thanks.
Looking at some code where I use the UITabBarItem badgeValue property, I see that self.tabBarItem.badgeValue returns nil while self.navigationController.tabBarItem.badgeValue returns the correct value. Could that be it?
The thing is that the auto-completion actually gives me tabBarItem after self. Easy to make a mistake because of that.
I do something like this for a Downloads tab:
for (UITabBarItem* item in self.tabBarController.tabBar.items) {
if (item.tag == 3) {
if (downloadCount > 0) {
item.badgeValue = [NSString stringWithFormat: #"%d", downloadCount];
} else {
item.badgeValue = nil;
}
}
}
I don't think you are supposed to access the tabBarItem directly. It is better find your item in the tabBarController's items array.