-2.6 C
New York
Thursday, December 26, 2024

ios – BarButtonItem with closure stops working for no motive


The next difficulty occurs in Xcode 16.2, iOS18 SDK with construct goal iOS17

I’ve an extension on UIBarButtonItem to assist closures as an alternative of goal/motion:


extension UIBarButtonItem {
    typealias Closure = () -> Void

    non-public class UIBarButtonItemClosureWrapper: NSObject {
        let closure: Closure
        init(_ closure: @escaping Closure) {
            self.closure = closure
        }
        
        deinit {
            print("DEINIT")
        }
    }
    
    non-public enum AssociatedKeys {
        static var targetClosure = 1
    }
    
    comfort init(title: String?, fashion: UIBarButtonItem.Model, closure: @escaping Closure) {
        self.init(title: title, fashion: fashion, goal: nil, motion: #selector(closureAction))
        objc_setAssociatedObject(self, &AssociatedKeys.targetClosure, UIBarButtonItemClosureWrapper(closure), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }

    comfort init(picture: UIImage?, fashion: UIBarButtonItem.Model, closure: @escaping Closure) {
        self.init(picture: picture, fashion: fashion, goal: nil, motion: #selector(closureAction))
        objc_setAssociatedObject(self, &AssociatedKeys.targetClosure, UIBarButtonItemClosureWrapper(closure), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }

    @objc
    func closureAction() {
        guard let closureWrapper = objc_getAssociatedObject(self, &AssociatedKeys.targetClosure) as? UIBarButtonItemClosureWrapper else { return }
        closureWrapper.closure()
    }
}

Nevertheless one thing actually unusual is occurring and I do not know why.

I take advantage of this in a UIViewController in navigationItem.rightBarButtonItems, and that viewcontroller is the foundation viewcontroller of a UINavigationController. All of it works nice, till I add a TextField to the SwiftUI View that is contained in that viewcontroller’s UIHostingController youngster viewcontroller.

So in abstract:
UINavigationController -> UIViewController -> UIHostingController -> TextField

As quickly as I give the main focus to the TextField, the button now not works. You’ll be able to see it turn into translucent as you faucet it (so it’s registering the faucet), however the closure is now not known as. If I put a button subsequent to it that makes use of the usual goal/motion system, that one retains on working.

That is the UIViewController code:

    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
        let merchandise = UIBarButtonItem(title: "TargetAction", fashion: .achieved, goal: self, motion: #selector(buttonTapped))
        let item2 = UIBarButtonItem(title: "ClosureAction", fashion: .achieved) {
            print("CLOSURE TEST")
        }
        self.navigationItem.rightBarButtonItems = [item, item2]
    }
    
    @objc func buttonTapped() {
        print("TARGET TEST")
    }

and that is the View code:

struct MyView: View {

    var physique: some View {
        Type {
            TextField("identify", textual content: .fixed("textual content"))
        }
    }

Goal Check is printed each time I faucet on the button. Closure Check is printed after I faucet the opposite button, till I focus the TextField by tapping on it. From then on Goal Check nonetheless works, however Closure Check now not prints.

Is the main focus of the TextField and the keyboard look doing one thing with the navigation bar behind the scenes that I’m unaware of, thereby destroying the related objects someway? Deinit is rarely printed, and placing a breakpoint in ClosureAction reveals the operate is not known as both.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles