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.