Tom Hammond
Tom Hammond

Reputation: 6090

UIBarButtonItem No Longer Displaying in iOS 11

I just updated my device to iOS to test my app in preparation for iOS 11. I have a toolbar at the top that no longer seems to have buttons working - the images worked fine in iOS 10 and below.

Here's how I initialize the images:

@property (strong, nonatomic) IBOutlet UIToolbar *navBar;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *refreshButton;

    path = [NSString stringWithFormat: @"https://s3.amazonaws.com/myapp/images/refresh.png"];
    url = [NSURL URLWithString:path];
    data = [NSData dataWithContentsOfURL:url];
    refreshButton = [[UIImage alloc] initWithData:data];

    smallerButton = [TRUtils imageWithImage:refreshButton scaledToSize:CGSizeMake(20, 20)];

    //TODO: Check image exists
    self.refreshButton = [[UIBarButtonItem alloc] initWithImage:[smallerButton imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
                                                       style:UIBarButtonItemStylePlain
                                                      target:self
                                                      action: @selector(refreshButtonPushed:)];
    [self.refreshButton setTarget:self];
    self.refreshButton.enabled = YES;
    self.refreshButton.imageInsets = UIEdgeInsetsMake(32, 32, 32, 32);

Then I add them to the navbar here:

self.navBar.items = [NSArray arrayWithObjects:self.backButton, self.forwardButton, self.flex, self.toolbarTitle, self.flex, self.refreshButton, self.flex, self.homeButton, nil];

Any idea why the images would stop showing in iOS 11 but display just fine in iOS 10?

It seems like the buttons still "work" but they just are blank spaces so people wouldn't know they are available.

It seems like this SO has a solution to fix it. But when I set:

self.navigationController.interactivePopGestureRecognizer.delegate = self;

and

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)] &&
        gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
        return NO;
    }
    return YES;
}

The issue still occurs.

Upvotes: 0

Views: 586

Answers (1)

Dave Weston
Dave Weston

Reputation: 6635

The imageInsets you're setting on the UIBarButtonItem are the problem. Get rid of them, and that should let the icon show up on iOS 11. The values there seem bogus, given the size of the image and the normal size of the tab bar. My guess is that iOS 10 simply ignored them, but iOS 11 is trying to do the "right thing".

Here are the contents of the basic playground I used to verify the behavior on iOS 11:

import UIKit
import PlaygroundSupport

extension UIImage {

    func scaledImage(withSize size: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
        return UIGraphicsGetImageFromCurrentImageContext()!
    }    
}

let navbar = UIToolbar(frame: CGRect(origin: .zero, size: CGSize(width: 320, height: 40)))

let imageUrl = URL(string: "http://www.freeiconspng.com/uploads/black-refresh-icon-png-9.png")!
let imageData = try Data(contentsOf: imageUrl)
let image = UIImage(data: imageData)!.withRenderingMode(.alwaysOriginal).scaledImage(withSize: CGSize(width: 20, height: 20))

let shareButton = UIBarButtonItem(barButtonSystemItem: .action, target: nil, action: nil)
let refreshButton = UIBarButtonItem(image: image, style: .plain, target: nil, action: nil)

// Uncomment the line below to reproduce the issue on iOS 11
//refreshButton.imageInsets = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)

navbar.items = [shareButton, refreshButton]

PlaygroundPage.current.liveView = navbar

Upvotes: 1

Related Questions