How to change a button's title when it has already been subview(ed)

Discussion in 'iPhone/iPad Programming' started by mistergreen2011, Apr 20, 2011.

  1. macrumors member

    Joined:
    Mar 23, 2011
    #1
    So I'm trying to change a button's title after it has been added into another view. A gave it a tag so I can call it but it's not working.

    Button code
    Code:
     //button
        CGRect frame = CGRectMake(100.0, 70.0, 100.0, 35.0);
        UIImage *blueImage = [UIImage imageNamed:@"blue_button.png"];
        UIImage *blueButtonImage = [blueImage stretchableImageWithLeftCapWidth:7 topCapHeight:0];
        
        UIButton *btn = [[UIButton alloc] initWithFrame:frame];
        
        [btn setTitle:@"CaSO4" forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor blackColor] forState:UIControlEventTouchDown];
        btn.titleLabel.font = [UIFont boldSystemFontOfSize:12.0];
        [btn setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, 0.0, 10.0)];
        [btn setBackgroundImage:blueButtonImage forState:UIControlStateNormal];
        btn.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
        btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
        [btn addTarget:self action:@selector(slideButton:) forControlEvents:UIControlEventTouchUpInside];
        btn.tag = 102;
        [self.view addSubview:btn];
        [btn release];
    
    Method to change the title
    Code:
    - (void)setButton:(NSString *)label
    {
        [[self.view viewWithTag:102] setTitle:label forState:UIControlStateNormal];
        
    }
    
    The warning is 'UIView' may not respond to 'SetTitle:forState'
    Which is true... I'm trying to target the button and not the view.

    thanks.
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    Assuming that there is only ever one view with tag 102 then you can just case the result to the correct type. Given that you've not done that already I'll assume you don't know what that means (sorry if you do). In general a cast looks like:

    Code:
    ((MyType) var)
    
    This tells the compiler to treat var as type MyType. Note that this does not actually change the type of var. If it's impossible to perform the cast then this will fail. In terms of object pointers you can suppress the compiler warning but still have runtime errors (for example you could cast and id typed var to any NSObject * subtype but it doesn't make var the correct object). So you should only do this when you are 100% sure your cast is correct.

    In this case you want code that looks like this:

    Code:
    - (void)setButton:(NSString *)label
    {
        [((UIButton *) [self.view viewWithTag:102]) setTitle:label forState:UIControlStateNormal];
        
    }
    
    I would note that there are ways to make this less brittle. You could check the class of the returned UIView (using a variable to store the view pointer). Or you could check if the UIView responds to the -setTitle:forState: message and send it via -performSelector:withObject:withObject:
     
  3. dantastic, Apr 21, 2011
    Last edited: Apr 21, 2011

    macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #3
    Sometimes setting a tag with:

    Code:
    myButton.tag = 1;
    
    does not actually set the tag properly but I'd have to do
    Code:
    [myButton setTag:1];
    
    instead.

    you could try
    Code:
    self.myButton.tag = 1;
    
     
  4. thread starter macrumors member

    Joined:
    Mar 23, 2011
    #4
    I tried casting it. That got rid of the warning but the button title doesn't change.

    Code:
    - (void)setButton:(NSString *)label
    {
       
        [((UIButton *)[self.view viewWithTag:102]) setTitle:label forState:UIControlStateNormal];
       
        if([self.view viewWithTag:102]) {
            NSLog(@"I exist");
        }
        
        NSLog(@"%@", label);
    }
    I even checked to see if view tag:102 exists, which it does :)

    I'll try the saving the view to a pointer and performSelector suggestions next.
     
  5. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #5
    That won't make any difference. That was simply a suggestion on style/modularity. You're check that the view with tag 102 is incorrect. You should be doing:

    Code:
     if([self.view viewWithTag:102]!=nil) {
            NSLog(@"I exist");
        }
    
     
  6. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    As well as putting the code that sets the title inside the if. Doesn't make much sense to check the view existence after you've already tried to use it.
     
  7. macrumors 6502

    Joined:
    Jan 20, 2008
    #7
    Also, when dealing with UIButton it's usually best to create one in code using:

    Code:
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    
    You can replace the button type with whichever type you need (e.g. UIButtonTypeRoundedRect). Make sure you set the frame of the button after initializing a new one.
     
  8. mistergreen2011, Apr 21, 2011
    Last edited: Apr 22, 2011

    thread starter macrumors member

    Joined:
    Mar 23, 2011
    #8
    whoa, something really strange...
    I modified it to this..

    Code:
        if([self.view viewWithTag:102] != nil) {
            NSLog(@"I exist");
            UIButton *bttn = (UIButton *)[self.view viewWithTag:102];
            [bttn setTitle:label forState:UIControlStateNormal];
            NSLog(@"%@", [bttn titleForState:UIControlStateNormal]);
        }
    
    I wanted to see what the title of the button is and the title on the button DOES change in code but not visually in the view. Does the view need to be refreshed or something?

    EDIT:

    Thanks for the help guys. I made a simpler project with these exact code and it works.... My bigger project must be breaking this somewhere. I'll have to dig through the code.


    Update:

    I found the problem. I'm calling this method 'setButton' from a pickerview in another view. I made a delegate to call setButton and it working's correctly now. It's weird that the method does get called normally with instantiating, [[myClass alloc] init] setButton] but needed a delegate to work correctly.
     

Share This Page