override var navigationItem: UINavigationItem fail in iOS 14

The following code fails since iOS14.x Is this a bug? No depreciation statements found in the SDK. Is there a workaround?

import UIKit

class ViewController: UIViewController {
    
    private lazy var barButtonItem: UIBarButtonItem = {
        UIBarButtonItem(image: .add, style: .plain, target: self, action: #selector(doSomething))
    }()

    override var navigationItem: UINavigationItem {
        let item = super.navigationItem
        item.rightBarButtonItem = barButtonItem // <- Thread 1: EXC_BAD_ACCESS (code=2, address=...)
        item.title = "TestCase"
        return item
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    @objc private func doSomething() {
        print(">>doSomething")
    }
}

We are running a complex software since iOS4 and cannot simply migrate to SwiftUI.

https://stackoverflow.com/questions/64270033/override-var-navigationitem-uinavigationitem-fail-in-ios-14

  • Apple' software depreciation is quite annoying. Apple banned pre-iOS14 apps on the App Store. <string>SDK Version Issue. This app was built with the iOS 13.2 SDK. All iOS apps submitted to the App Store must be built with the iOS 14 SDK or later, included in Xcode 12 or later.</string>

Add a Comment

Replies

Setting a property in UINavigationItem within the navigationItem getter is not supported. This code is effectively running into an infinite loop that is constantly re-querying the UINavigationItem whenever you set rightBarButtonItem.

The recommended way to do this is to set your properties in the UIViewController's initializer (or in the viewDidLoad() method) so that it only happens once, rather than to be set every time it is fetched.

import UIKit

class ViewController: UIViewController {
    private lazy var barButtonItem: UIBarButtonItem = {
        UIBarButtonItem(image: .add, style: .plain, target: self, action: #selector(doSomething))
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.rightBarButtonItem = barButtonItem
        navigationItem.title = "TestCase"
    }
    
    @objc private func doSomething() {
        print(">>doSomething")
    }
}