Previously to iOS 11, I get a reference to the view of a UIBarButtonItem as follow:
let addBarButtomItemView: UIView = addBarButtomItem.value(forKey: "view") as! UIView
No with iOS 11, I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
How could reference the view of a UIBarButtonItem using iOS 11?
You are right, I was using a private APIs, and it will not pass the apple app store review process.
What I was looking for was a way to hide the UIBarButtonItem under some circustances.
Wrong code:
import UIKit struct User{ let name : String } class WrongViewController: UIViewController { @IBOutlet weak var addBarButtomItem: UIBarButtonItem! @IBAction func add(_ sender: Any) { } @IBAction func createUser(_ sender: Any) { user = User(name: "John") } var user : User?{ didSet{ // iOS 11 fatal error: unexpectedly found nil while unwrapping an Optional value let addBarButtomItemView: UIView = addBarButtomItem.value(forKey: "view") as! UIView if user != nil { addBarButtomItem.isEnabled = true addBarButtomItemView.isHidden = false } else { addBarButtomItem.isEnabled = false addBarButtomItemView.isHidden = true } } } override func viewDidLoad() { super.viewDidLoad() user = nil } }
I finally solve the issue using an strong IBOutlet, instead of weak, and placing it in the ViewController instead of in the Navigation Item and adding or removing it to the Navigation Item instead of hidding it.
Right code:
import UIKit struct User{ let name : String } class RightViewController: UIViewController { @IBOutlet var addBarButtomItem: UIBarButtonItem! @IBAction func add(_ sender: Any) { } @IBAction func createUser(_ sender: Any) { user = User(name: "John") } var user : User?{ didSet{ if user != nil { navigationItem.rightBarButtonItem = addBarButtomItem } else { navigationItem.rightBarButtonItem = nil } } } override func viewDidLoad() { super.viewDidLoad() user = nil } }
I found also another way using a weak IBOutlet, instead of get a reference to the view of the UIBarButtonItem and hide it, using the tintColor property of the UIBarButtonItem, as follow:
import UIKit struct User{ let name : String } class RightViewController: UIViewController { @IBOutlet weak var addBarButtomItem: UIBarButtonItem! @IBAction func add(_ sender: Any) { } @IBAction func createUser(_ sender: Any) { user = User(name: "John") } var user : User?{ didSet{ if user != nil { addBarButtomItem.isEnabled = true addBarButtomItem.tintColor = nil // set a UIBarbutton back to the default tint color } else { addBarButtomItem.isEnabled = false addBarButtomItem.tintColor = .clear } } } override func viewDidLoad() { super.viewDidLoad() user = nil } }