You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xcode16.2中带闭包的UIBarButtonItem聚焦TextField后失效

UIBarButtonItem闭包扩展在TextField获焦后失效问题

环境:Xcode 16.2、iOS 18 SDK(构建目标为iOS 17)

我为UIBarButtonItem编写了扩展,用闭包替代传统的Target-Action模式,代码如下:

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()
    }
}

出现异常情况:该闭包按钮在UINavigationController根UIViewController的navigationItem.rightBarButtonItems中原本正常工作,但当在UIViewController的子UIHostingController承载的SwiftUI View中添加TextField后,一旦TextField获得焦点,闭包按钮点击仅显示半透明反馈但闭包不执行,而旁边的标准Target-Action按钮仍正常工作。

相关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")
}

SwiftUI View代码:

struct MyView: View {
    var body: some View {
        Form {
            TextField("name", text: .constant("text"))
        }
    }
}

具体现象:点击TargetAction按钮始终打印"TARGET TEST",ClosureAction按钮在TextField获焦前能正常打印"CLOSURE TEST",获焦后不再打印。未触发UIBarButtonItemClosureWrapper的deinit,且closureAction方法也未被调用,怀疑TextField聚焦和键盘弹出影响了导航栏的关联对象,但不确定具体原因。

内容的提问来源于stack exchange,提问作者Joris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:37:37