0

Having a problem with UIBarButtonItem resizing when returning to VC with different values for frame and image.

var selectedR = 1
var leftFrame = CGRect()
var leftImage = UIImage()

override func viewDidLoad() {
    super.viewDidLoad()

    if selectedR == 0
    {
        leftFrame = CGRect(x: 0, y: 0, width: 33, height: 33)
        leftImage = UIImage(named: “pic-0”)!
    }
    else if selectedR == 1
    {
        leftFrame = CGRect(x: 0, y: 0, width: 79, height: 33)
        leftImage = UIImage(named: "pic-1")!
    }
    else if selectedR == 2
    {
        leftFrame =  CGRect(x: 0, y: 0, width: 34, height: 33)
        leftImage = UIImage(named: "pic-2”)!
    }

    let cButton = UIButton(frame: leftFrame)
    cButton.setImage(leftImage, for: UIControlState())
    cButton.addTarget(self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:)), for: .touchUpInside)
    cButton.contentMode = UIViewContentMode.scaleAspectFit
    let leftItem = UIBarButtonItem(customView: cButton)
    self.navigationItem.leftBarButtonItem = leftItem
}

First time perfect size for selectedR = 1

Coming back into viewDidLoad with different selectedR value and image blows up, distorts and setting the leftFrame size is not honoured.

This all worked perfect in swift 3, but swift 4 it goes all over the place. Any help or suggestions would be much appreciated.

Peter de Vries
  • 780
  • 1
  • 6
  • 14
  • Why is `viewDidLoad` getting called more than once? – beyowulf Sep 13 '17 at 19:53
  • From what I know that is how the framework I use (SWRevealViewController) works. And worked perfect in Swift 3. That said, could very well be the problem indeed. What are your thoughts? – Peter de Vries Sep 13 '17 at 20:29
  • 1
    I just want to make sure that you're not manually calling `viewDidLoad` that is something the system should handle. My guess is one major change between iOS 10 and 11 is now bar button items are laid out by the auto layout engine. That change however should be backward compatible. You could try `cButton.widthAnchor.constraint(equalToConstant: leftFrame.width).isActive = true; cButton.heightAnchor.constraint(equalToConstant: leftFrame.height).isActive = true` You can see more about it here https://developer.apple.com/videos/play/wwdc2017/204/ – beyowulf Sep 13 '17 at 20:34
  • you are awesome, that worked, struggled with this all day! If you put it in an answer, I'll gladly accept it. – Peter de Vries Sep 13 '17 at 20:42

1 Answers1

2

One major change between iOS 10 and 11 is now bar button items are laid out by the auto layout engine. Typically that should be backward compatible. But if you are having problems with laying out bar button items, you should try setting constraints and see if that solves your problem.

In you case you would say:

var selectedR = 1
var leftFrame = CGRect()
var leftImage = UIImage()

override func viewDidLoad() {
    super.viewDidLoad()

    if selectedR == 0
    {
        leftFrame = CGRect(x: 0, y: 0, width: 33, height: 33)
        leftImage = UIImage(named: “pic-0”)!
    }
    else if selectedR == 1
    {
        leftFrame = CGRect(x: 0, y: 0, width: 79, height: 33)
        leftImage = UIImage(named: "pic-1")!
    }
    else if selectedR == 2
    {
        leftFrame =  CGRect(x: 0, y: 0, width: 34, height: 33)
        leftImage = UIImage(named: "pic-2”)!
    }

    let cButton = UIButton(frame: leftFrame)
    cButton.widthAnchor.constraint(equalToConstant: leftFrame.width).isActive = true
    cButton.heightAnchor.constraint(equalToConstant: leftFrame.height).isActive = true
    cButton.setImage(leftImage, for: UIControlState())
    cButton.addTarget(self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:)), for: .touchUpInside)
    cButton.contentMode = UIViewContentMode.scaleAspectFit
    let leftItem = UIBarButtonItem(customView: cButton)
    self.navigationItem.leftBarButtonItem = leftItem
}

This was covered in Apple's WWDC 2017 session Updating Your App for iOS 11.

beyowulf
  • 15,101
  • 2
  • 34
  • 40