Swift如何通过按钮点击触发TextField长按唤起的Scan Text功能
实现方案
iOS 15.4以上系统完全可以实现,直接复用长按唤起的同款原生Scan Text能力,不需要自己编写OCR识别逻辑,具体做法如下:
- 系统给所有文本输入控件默认内置了扫描文本的触发动作,长按弹出的菜单选项本质就是调用的这个内置动作,只需要在按钮点击时主动触发该动作即可,不涉及私有API,可正常通过App Store审核。
- 实现时通过视图层级找到当前激活的TextField实例,主动调用对应扫描方法即可,最终弹出的扫描界面、识别逻辑、文本填充效果和长按唤起的完全一致,没有体验差异。
完整代码
首先编写一个查找当前激活输入框的扩展:
import SwiftUI import UIKit extension UIApplication { func getActiveTextField() -> UITextField? { guard let windowScene = connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene, let rootVC = windowScene.windows.first(where: \.isKeyWindow)?.rootViewController else { return nil } return findTextField(in: rootVC.view) } private func findTextField(in view: UIView) -> UITextField? { if let textField = view as? UITextField, textField.isFirstResponder { return textField } for subview in view.subviews { if let target = findTextField(in: subview) { return target } } return nil } }
替换原有布局代码,补充按钮点击逻辑:
HStack{ TextField("Service Name", text: $serviceFieldName) Button("Scan"){ guard let activeTF = UIApplication.shared.getActiveTextField() else { return } activeTF.becomeFirstResponder() // 延迟0.1秒触发,等待响应链状态稳定 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { activeTF.perform(Selector(("scanText:"))) } } } .padding()
注意事项:
- 低于iOS 15.4的系统没有内置该扫描功能,需要自行接入Vision框架实现文字识别
- 记得在Info.plist中添加相机权限描述
NSCameraUsageDescription,否则调用扫描时会直接崩溃- iOS 16及以上版本可以直接使用官方公开的
UIScanTextInteraction类主动触发扫描,稳定性更强,上述写法是兼容更低版本的最简实现
- 如果触发无响应,优先检查TextField是否正常成为第一响应者,必须进入输入状态才能正常调出扫描面板
内容的提问来源于stack exchange,提问作者fs_tigre
相关产品推荐
相关产品推荐

