Reputation: 1823
I have a NavigationBar app with two views: a parent and a sub view. In the sub view I'm adding a button to the right corner as follows:
- (void)viewDidLoad {
UIBarButtonItem *tempButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"lock-unlocked.png"] style:UIBarButtonItemStylePlain target:self action:@selector(lockScreen)];
self.navigationItem.rightBarButtonItem = tempButton;
[tempButton release];
}
When that button is clicked I want to change the image of this rightBarButtonItem and disable the leftBarButtonItem (which was added automatically by the controller). Basically have two states of a button, locked and unlocked.
Question 1: The only way I can find how to change the image is to create a new UIButtonItem with a new image and replace rightBarButtonItem with that new one. But I'm wondering if there's a way to just change the image without creating a new UIBarButtonItem. Am I creating a memory leak if I keep creating new UIBarButtonItem?
Question 2: How can I get a hold of self.navigationItem.leftBarButtonItem and disable/enable it? I don't create that one manually, it's created automatically for me by the controller. I don't see any method/property on UIBarButtonItem to enable/disable user interaction with it.
Upvotes: 9
Views: 47281
Reputation: 1607
In regard to question 2, use the 'enabled' property:
self.navigationItem.leftBarButtonItem.enabled = NO;
Upvotes: 7
Reputation: 11
Shouldn't the above have release the UILabel *l after the [self.window addSubView:l] call? That way it gets retained +1 when added to the Subview, but released -1 in the same branch. Otherwise, you must call disableLeftBarButtonItemOnNavbar:NO to release it. And while, you'll end up in the same place in the end, you aren't leaking, I think the static analysis tools they've built into XCode wouldn't like that being in a separate branch. Small detail :-)
- (void) disableLeftBarButtonItemOnNavbar:(BOOL)disable
{
static UILabel *l = nil;
if (disable) {
if (l != nil)
return;
l = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 160, 44)];
l.backgroundColor = [UIColor clearColor];
l.userInteractionEnabled = YES;
[self.window addSubview:l];
[l release];
}
else {
if (l == nil)
return;
[l removeFromSuperview];
l = nil;
}
}
Upvotes: 1
Reputation: 9192
I think this code helps you,
UIButton *m_objbtnFlip= [[UIButton alloc] initWithFrame:CGRectMake(0,0,89, 37)];
[m_objbtnFlip setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"btn_purchased"
ofType:IMAGETYPE]]
forState:UIControlStateNormal];
[m_objbtnFlip setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"btn_allavailable"
ofType:IMAGETYPE]]
forState:UIControlStateSelected];
[m_objbtnFlip addTarget:self action:@selector(flipViews) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *objBarButtonItemRight = [[UIBarButtonItem alloc] initWithCustomView:m_objbtnFlip];
self.navigationItem.rightBarButtonItem=objBarButtonItemRight;
[objBarButtonItemRight release];
objBarButtonItemRight = nil;
And write action here,
-(void)flipViews {
// put action code here
}
Upvotes: 0
Reputation: 1172
Using "hidesBackButton=YES" is really not an elegant solution, cause it HIDES the button which is not what we want. An acceptable work-around would be adding a UILabel to the window just over the back button at least disabling the touches on the button.
Add this method to your AppDelegate class:
- (void) disableLeftBarButtonItemOnNavbar:(BOOL)disable
{
static UILabel *l = nil;
if (disable) {
if (l != nil)
return;
l = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 160, 44)];
l.backgroundColor = [UIColor clearColor];
l.userInteractionEnabled = YES;
[self.window addSubview:l];
}
else {
if (l == nil)
return;
[l removeFromSuperview];
[l release];
l = nil;
}
}
You can call it like this from any view controller to disable:
MyAppDelegate *appDeleg = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDeleg disableLeftBarButtonItemOnNavbar:YES];
To enable:
MyAppDelegate *appDeleg = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDeleg disableLeftBarButtonItemOnNavbar:NO];
Upvotes: 0
Reputation: 1158
I was not able to disable/grey out a NavBar button with:
self.navigationItem.leftBarButtonItem.enabled = NO;
...but hiding the back button works well!
self.navigationItem.hidesBackButton = YES;
Thanks Dzamir!
Upvotes: 0
Reputation: 145
I can't understand if you have a navigationController, but in this case to disable the back button you need to call:
self.navigationItem.hidesBackButton = YES;
Upvotes: 5
Reputation: 3382
Question 1: Declare UIBarButtonItem *tempButton in the interface
@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
UIBarButtonItem *tempButton;
}
@property (nonatomic, retain) UIBarButtonItem *tempButton;
and synthesize it in the implementation.
@synthesize tempButton;
Create the object in viewDidLoad similiar to how you are now.
- (void)viewDidLoad {
tempButtom = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"lock-unlocked.png"] style:UIBarButtonItemStylePlain target:self action:@selector(lockScreen)];
self.navigationItem.rightBarButtonItem = tempButton;
}
But don't release it here, release it in the dealloc method normally found at the bottom.
Then when lockScreen is called do
tempButton.image = [UIImage imageNamed:@"myImage.png"]
I don't have an answer for question 2, im afraid!
Upvotes: 18