2
votes

I've read a couple similar questions regarding this topic on StackOverflow, but none of them apply to my case.

I have a UIToolbar on my application. The ToolBar has a layout like the following.

(Button #1) (Button #2) (Button #3) <--- Flex Controller ---> (Button #4)

What is the most efficient way to Show/Hide the Button #3 UIBarButtonItem since it is in the middle of the UIToolbar?

FOLLOW-UP

I am aware of the setItems:Animated method, but this seems like it could be problematic because all of my buttons are wired through IB and they have associated IBActions.

Does this mean that I, therefore, need to find a way to retain my Button #3 when it is hidden (since I am using ARC?) I'm looking for the most optimal/efficient method for adding and removing these objects. If I must recreate this list each time I have to show/hide my #3 button, that's what I will do.

It just seems so inefficient.

5
probably you've tried it already, but can't you just use hidden property of the button? - Novarg
@Novarg: That property isn't available on the UIBarButtonItem because it isn't inherited from UIButton. - RLH
Wire the buttons as IBOutlets and then you can reference them when adjusting the toolbar's items. I've put in an answer which describes the method I use when doing this to simplify matters. - Chad

5 Answers

4
votes

I would recommend building a helper function in the following manner:

- (void) setToolbarItems:(BOOL) button3Shown {
    NSMutableArray *items = [NSMutableArray arrayWithCapacity:5];
    [items addObject:button1];
    [items addObject:button2];
    if(button3Shown) {
        [items addObject:button3];
    }
    [items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
    [items addObject:button4];
    [self.toolbar setItems:[items copy] animated:YES];
}

This then has the benefit of being available whenever you need to update it and then you can easily add/remove the button. In order for this to work, you would need to have the buttons available in your implementation file as IBOutlets and they would be easily referenced for rebuilding the toolbar.

5
votes

Looking in UIToolBar.h, there's the following method:

- (void)setItems:(NSArray *)items animated:(BOOL)animated;   // will fade in or out or reorder and adjust spacing

You should just be able to do something like:

NSMutableArray *items = [toolBar.items mutableCopy];
[items removeObjectAtIndex:2];
[toolBar setItems:items animated:YES];

See if that works the way you're looking for

0
votes

You need to reset the toolbar items, passing in a new array without the button you want to hide. See Hide UIToolbar UIBarButtonItems for exact details.

0
votes

Creating different arrays of UIBarButtonItems and adding/removing to/from the UIToolbar at runtime may increase the complexity of execution.

I've done it using a different approach. Here are the snippets for achieving it.

Step 1 : Either create an IBOutlet or Create the UIToolbar instance.

    UIToolbar *toolBar = [UIToolbar alloc] init];

Set the required styles if you want.

Step 2 : Create UIButton type instances.

    UIButton *button1, *button2;

Step 3: Assign images (if required) to the buttons.

    button1 = [UIButton alloc] initWithFrame:CGRectMake(0.f,0.f,30.f,30.f);
    [button1 setBackgroundImage:[UIImage imageNamed:@"image1.png"] forState:UIControlStateNormal];

    button2 = [UIButton alloc] initWithFrame:CGRectMake(0.f,0.f,30.f,30.f);
    [button2 setBackgroundImage:[UIImage imageNamed:@"image2.png"] forState:UIControlStateNormal];

Step 4: Create UIBarButtonItem instances with above buttons as custom view.

    UIBarButtonItem *toolbarbuttonItem1 = [UIBarButtonItem alloc] initWithCustomView:button1];
    UIBarButtonItem *toolbarbuttonItem2 = [UIBarButtonItem alloc] initWithCustomView:button1];

Step 5: Assign the bar button items to the toolbar.

    toolBar.items = [NSArray arrayWithObjects:toolbarbuttonItem1,toolbarbuttonItem2,nil];

Step 6: Add the Toolbar to the VIEW.

Step 7: Create a UIButton IBOutlet in the VIEW and assign a click event.

Invoke the following helper method int the click event to toggle hiding.

    - (void) toggleToolbarButtons {
           button1.hidden = !button1.hidden;
           button2.hidden = !button2.hidden;
    }

Hope that helps!!

0
votes

With existing references to toolbar items item1, item2 and item3, the most straightforward way is to remove all items and then re-add each item in the order you want it. This code is written from the perspective of being within a UIToolbar subclass:

let flexSpace: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let fixedSpace: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)

self.items?.removeAll()
self.items?.append(flexSpace)
self.items?.append(item1)
self.items?.append(fixedSpace)
self.items?.append(item3)
self.items?.append(fixedSpace)
self.items?.append(item2)

These item references can be from IBOutlets. Change these references to be strong rather than the IB-inserted-default weak references, so that the UIToolbar will maintain references to these items even when they have been removed, thus maintaining the relevant IBAction function relationships.

To remove a specific item from your UIToolbar from within a UIToolbar subclass, without having to re-set all items:

if let index = self.items?.index(of: buttonToRemove) {
    self.items?.remove(at: index)
}

If not within a UIToolbar subclass, simply replace self with a reference to the UIToolbar throughout.