У меня есть расширение для UIBarButtonItem для поддержки замыканий вместо цели/действия:
Код: Выделить всё
extension UIBarButtonItem {
typealias Closure = () -> Void
private class UIBarButtonItemClosureWrapper: NSObject {
let closure: Closure
init(_ closure: @escaping Closure) {
self.closure = closure
}
deinit {
print("DEINIT")
}
}
private enum AssociatedKeys {
static var targetClosure = 1
}
convenience init(title: String?, style: UIBarButtonItem.Style, closure: @escaping Closure) {
self.init(title: title, style: style, target: nil, action: #selector(closureAction))
objc_setAssociatedObject(self, &AssociatedKeys.targetClosure, UIBarButtonItemClosureWrapper(closure), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
convenience init(image: UIImage?, style: UIBarButtonItem.Style, closure: @escaping Closure) {
self.init(image: image, style: style, target: nil, action: #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()
}
}
Я использую это в UIViewController в NavigationItem.rightBarButtonItems , и этот контроллер представления является корневым контроллером представления UINavigationController. Все работает нормально, пока я не добавлю TextField в представление SwiftUI, которое содержится в дочернем контроллере представления UIHostingController этого viewcontroller.
Итак, вкратце:
Код: Выделить всё
UINavigationController -> UIViewController -> UIHostingController -> TextField
Это код UIViewController:
Код: Выделить всё
override func viewDidLoad() {
super.viewDidLoad()
let item = UIBarButtonItem(title: "TargetAction", style: .done, target: self, action: #selector(buttonTapped))
let item2 = UIBarButtonItem(title: "ClosureAction", style: .done) {
print("CLOSURE TEST")
}
self.navigationItem.rightBarButtonItems = [item, item2]
}
@objc func buttonTapped() {
print("TARGET TEST")
}
Код: Выделить всё
struct MyView: View {
var body: some View {
Form {
TextField("name", text: .constant("text"))
}
}
Код: Выделить всё
Target Test
Выполняет ли фокус TextField и внешний вид клавиатуры что-то с панелью навигации? за кулисами, о которых я не знаю, тем самым каким-то образом уничтожая связанные объекты? Deinit никогда не выводится, а установка точки останова в ClosureAction показывает, что функция также не вызывается.
Подробнее здесь: https://stackoverflow.com/questions/793 ... -no-reason