SwiftUI 通过实现 UIViewRepresentable 来使用 UIKit 组件
Posted
技术标签:
【中文标题】SwiftUI 通过实现 UIViewRepresentable 来使用 UIKit 组件【英文标题】:SwifUI using UIKit components by implementing UIViewRepresentable 【发布时间】:2019-12-17 09:15:20 【问题描述】:好的,我知道如何使用 UIViewRepresentable 和 Coordinator 将 UIKit 组件(如 TextField)与 SwiftUI 一起使用。这一切都运作良好。但是,如何以 SwiftUI 的原生方式(即使用修饰符)从 SwiftUI 的角度自定义这些组件?
我有 UITextField 的示例包装器来启用一些额外的委托方法处理。这与将闭包传递给构造函数的原生方法类似。但是我如何才能使用 SwiftUI 修饰符对这个 UITextField 应用一些样式呢?
struct PasswordField: UIViewRepresentable
@Binding var text: String
@Binding var isSecured: Bool
let onBeginEditing: () -> Void
let onEndEditing: () -> Void
let onEditingChanged: (Bool) -> Void
let onCommit: () -> Void
init(text: Binding<String>, isSecured : Binding<Bool> = .constant(true),
onBeginEditing: @escaping () -> Void = ,
onEndEditing: @escaping () -> Void = ,
onEditingChanged: @escaping (Bool) -> Void = _ in ,
onCommit: @escaping () -> Void = )
self._text = text
self._isSecured = isSecured
self.onBeginEditing = onBeginEditing
self.onEndEditing = onEndEditing
self.onEditingChanged = onEditingChanged
self.onCommit = onCommit
func makeCoordinator() -> Coordinator
Coordinator(onBeginEditing: onBeginEditing, onEndEditing: onEndEditing, onEditingChanged: onEditingChanged, onCommit: onCommit)
func makeUIView(context: UIViewRepresentableContext<PasswordField>) -> UITextField
let textField = UITextField()
textField.delegate = context.coordinator
textField.addTarget(context, action: #selector(Coordinator.valueChanged(sender:)), for: .valueChanged)
return textField
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<PasswordField>)
uiView.text = text
uiView.isSecureTextEntry = isSecured
// MARK: - Coordinator
extension PasswordField
class Coordinator: NSObject, UITextFieldDelegate
let onBeginEditing: () -> Void
let onEndEditing: () -> Void
let onEditingChanged: (Bool) -> Void
let onCommit: () -> Void
init(onBeginEditing: @escaping () -> Void,
onEndEditing: @escaping () -> Void,
onEditingChanged: @escaping (Bool) -> Void,
onCommit: @escaping () -> Void)
self.onBeginEditing = onBeginEditing
self.onEndEditing = onEndEditing
self.onEditingChanged = onEditingChanged
self.onCommit = onCommit
@objc func valueChanged(sender: UITextField)
onEditingChanged(true)
func textFieldShouldReturn(_ textField: UITextField) -> Bool
textField.resignFirstResponder()
onCommit()
return true
func textFieldDidBeginEditing(_ textField: UITextField)
onBeginEditing()
onEditingChanged(true)
func textFieldDidEndEditing(_ textField: UITextField)
onEditingChanged(false)
onEndEditing()
struct PasswordField_Previews: PreviewProvider
static var previews: some View
PasswordField(text: .constant("PaSSword"), isSecured: .constant(true))
现在我想这样使用它:
PasswordField(text: self.$validator.value, onEditingChanged: editing in
self.onEditingChanged?(editing)
self.isEdited = true
, onCommit:
self.validator.validateField()
self.validator.validateFieldAsync()
)
.font(.custom("AvenirNext-Light", size: 13)) // THIS IS IMPORTANT
.foregroundColor(Color("BodyText")) // THIS IS IMPORTANT
.frame(maxHeight: geometry.size.height)
.offset(x: 0, y: 16)
.padding(10)
好的,我知道我可以在包装器中硬编码这种样式,或者通过构造函数传递它。是的,但这不是 SwiftUI 本地执行此操作的方式。
【问题讨论】:
【参考方案1】:您需要实现自己的自定义修饰符。请参阅 ViewModifier 协议的文档,尽管 SwiftUI 文档仍然很薄。
但是,您不必实现自己的 TextField 来处理密码输入,因为 SwiftUI 现在原生支持您想要的:SecureField。
【讨论】:
仅链接答案不被视为良好做法。请看***.com/help/how-to-answer 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review @SuitBoyApps,感谢您指出。我已删除链接,但目前无法提供更完整的答案。以上是关于SwiftUI 通过实现 UIViewRepresentable 来使用 UIKit 组件的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - 与 Microsoft 的 Firebase 身份验证
为 SwiftUI Apple Watch App 实现基于页面的导航
SwiftUI完美弹出UIActivityViewController(通过微信QQ或隔空投送分享)的应用分享窗口
SwiftUI完美弹出UIActivityViewController(通过微信QQ或隔空投送分享)的应用分享窗口