1

I've got two viewControllers who each need a login button in the top right corner of the navigation bar.

In viewController1#viewDidLoad, I set up the rightBarButtonItem like so (abbreviated):

// set up the login button on the right
UIButton *loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *loginImage = [UIImage imageNamed:@"btn_login.png"];
[loginButton setBackgroundImage:loginImage forState:UIControlStateNormal];
[loginButton setFrame:CGRectMake(0, 0, loginImage.size.width, loginImage.size.height)];
[loginButton setTag:1111111];
UIBarButtonItem *loginItem = [[UIBarButtonItem alloc] initWithCustomView:loginButton];
self.navigationItem.rightBarButtonItem = loginItem;
[loginItem release];

I tag it so that in viewWillAppear, I can use viewWithTag:1111111 to figure out if it needs to be hidden or visible, based on whether or not the user is logged in. Simple.

((UIButton *)[self.navigationController.view viewWithTag:LOGIN_BUTTON_TAG]).hidden = true; 

When viewController2 gets pushed onto the stack, I basically run the same code to set up my rightBarButtonItem, but I give it a different tag (i.e. 222222).

In viewController2#viewWillAppear, when I look for the viewWithTag:222222, it comes back as null, and so I can't hide/show it.

I noticed though that if I use the same tag as I used in viewController1 (1111111), I can get to it.

Why is this? My tags are actually set up at the top of the file as constants, so it seems inelegant to copy the random number from vc1 into vc2 just so I can get this to work. Instead, I'd like to understand why vc2's tag isn't getting applied to the rightBarButtonItem, and why vc1's tag is still preserved even though I'm in a different viewController.

djibouti33
  • 12,102
  • 9
  • 83
  • 116
  • My first guess is that you've put extra or less digits in the `tag` between when you assign the `tag` and when you get a view from the `tag` – tipycalFlow Apr 12 '12 at 15:50
  • My second guess(the serious one) is that 222222 causes some integer overflow and turns it into -123648 or something. Try a smaller tag like 2222 – tipycalFlow Apr 12 '12 at 15:52
  • My tags are actually 34590 for vc1 and 234355 for vc2. I just used 1111111 and 222222 to make it clear for this question which viewController I was in. – djibouti33 Apr 12 '12 at 15:54
  • Notice that the second no has 6 digits. Try a five digit no. I think the limit is 2^16 = 65,536. The 1st no is less than this, the second is more. Better yet, try using 65535. Even better, `NSLog`its value +1 before comparing – tipycalFlow Apr 12 '12 at 15:58

2 Answers2

0

If I understand correctly what you are doing, the first thing I would try is to check, before this line, in both viewcontrollers:

((UIButton *)[self.navigationController.view viewWithTag:LOGIN_BUTTON_TAG]).hidden = true; 

to put a

NSLog("View is %@", self.navigationController.view);

to check if you are sending viewWithTag to the correct view. Not sure about this, but Are you trying to access to a view, controller by an UIViewcontroller, loaded inside an UINavigationcontroller? In this case I would use:

(UIButton *)[[[self.navigationController visibleViewController] view] viewWithTag:LOGIN_BUTTON_TAG];
LombaX
  • 17,265
  • 5
  • 52
  • 77
  • When I log self.navigationController.view in vc1 and vc2, I get the exact same object ( – djibouti33 Apr 12 '12 at 16:08
  • Ok, It's what I was saying :-) (sorry but my english is not very good). From the second viewcontroller, you are accessing to the view of the first viewcontroller, and for this reason you can see only the view with tag 11111 :-). Try to use (UIButton *)[[[self.navigationController visibleViewController] view] viewWithTag:LOGIN_BUTTON_TAG]; – LombaX Apr 12 '12 at 16:41
  • Obviously you can even use an ivar, as written by Paul.s. In my answer I'm trying to focus on what is the error in your code, but there are other ways :-) – LombaX Apr 12 '12 at 16:50
0

The easiest most scalable solution is to avoid using viewWithTag: like the plague.

Make the UIBarButtonItem an ivar and then you have instant access to it without any ambiguities.

Replace

[loginButton setTag:1111111];

with

self.loginButton = loginButton;

Then to retrieve do this

self.loginButton;

instead of

(UIButton *)[[[self.navigationController visibleViewController] view] viewWithTag:LOGIN_BUTTON_TAG];

I know which one looks more elegant and robust to me

Paul.s
  • 38,494
  • 5
  • 70
  • 88
  • Can you elaborate on why `viewWithTag:` is so bad? I looked at it as a more elegant solution than having to instantiate ivar's for elements when you just need to 'get at' those elements. – djibouti33 Apr 12 '12 at 16:15
  • Why go searching through an entire view hierarchy asking each view for it's tag when you can just have a pointer straight to it? You are also relying on a variable which can easily be changed by accident. – Paul.s Apr 12 '12 at 16:18