Swiftui - 从 UIViewRepresentable 访问 UIKit 方法/属性

标签 swiftui uikit uiviewrepresentable

我使用 UIViewRepresentable 基于 UITextView 创建了一个 SwiftUI TextView(如下代码)。在 Swiftui 中显示文本工作正常。

但现在我需要从我的模型访问 UITextView 的内部函数。我如何打电话UITextView.scrollRangeToVisible(_:) 或访问 UITextView.isEditable 等属性?

我的模型需要根据内部模型状态进行这些修改。

有什么想法吗?谢谢

(附:我知道 SwiftUI 中有 TextEditor,但我需要 iOS 13 的支持!)

struct TextView: UIViewRepresentable {
  @ObservedObject var config: ConfigModel = .shared
  @Binding var text: String
  
  @State var isEditable: Bool
  var borderColor: UIColor
  var borderWidth: CGFloat
  
  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
  func makeUIView(context: Context) -> UITextView {
    let myTextView = UITextView()
    myTextView.delegate = context.coordinator
    
    myTextView.isScrollEnabled = true
    myTextView.isEditable = isEditable
    myTextView.isUserInteractionEnabled = true
    myTextView.layer.borderColor = borderColor.cgColor
    myTextView.layer.borderWidth = borderWidth
    myTextView.layer.cornerRadius = 8
    return myTextView
  }
  
  func updateUIView(_ uiView: UITextView, context: Context) {
    uiView.font = uiView.font?.withSize(CGFloat(config.textsize))
    uiView.text = text
  }
  
  class Coordinator : NSObject, UITextViewDelegate {
    
    var parent: TextView
    
    init(_ uiTextView: TextView) {
      self.parent = uiTextView
    }
    
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
      return true
    }
    
    func textViewDidChange(_ textView: UITextView) {
      self.parent.text = textView.text
    }
  }
}

最佳答案

您可以使用诸如配置器回调模式之类的东西,例如

struct TextView: UIViewRepresentable {
  @ObservedObject var config: ConfigModel = .shared
  @Binding var text: String
  
  @State var isEditable: Bool
  var borderColor: UIColor
  var borderWidth: CGFloat
  var configurator: ((UITextView) -> ())?     // << here !!

  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
  func makeUIView(context: Context) -> UITextView {
    let myTextView = UITextView()
    myTextView.delegate = context.coordinator
    
    myTextView.isScrollEnabled = true
    myTextView.isEditable = isEditable
    myTextView.isUserInteractionEnabled = true
    myTextView.layer.borderColor = borderColor.cgColor
    myTextView.layer.borderWidth = borderWidth
    myTextView.layer.cornerRadius = 8
    return myTextView
  }

  func updateUIView(_ uiView: UITextView, context: Context) {
    uiView.font = uiView.font?.withSize(CGFloat(config.textsize))
    uiView.text = text

    // alternat is to call this function in makeUIView, which is called once,
    // and the store externally to send methods directly.
    configurator?(myTextView)                  // << here !!
  }

  // ... other code
}

并在 SwiftUI View 中使用它,例如

TextView(...) { uiText in
   uiText.isEditing = some
}

注意:根据您的情况,可能需要额外的条件来避免更新循环,不确定。

关于Swiftui - 从 UIViewRepresentable 访问 UIKit 方法/属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65181246/

相关文章:

横向模式下的 iOS 8 状态栏背景方向

SwiftUI 从 UITextField 中关闭键盘

swift - 如何在 SwiftUI 中的修剪圆上添加圆尖

ios - 如何从结构 View 数组中提取状态? SwiftUI

SwiftUI:如何将 View 附加到多行文本的结尾?

swift - 删除 SwiftUI 中部分之间的空白

ios - 在 Swift 中设置动画 UITableViewCell 高亮颜色

ios - 编辑表格时的附加选项卡

swift - 在 UIViewRepresentable SwiftUI 中设置自定义 UIView 框架

ios - 在没有 PKCanvasView 的情况下使用 PKToolPicker