模态表中的 UITextView 不起作用
Posted
技术标签:
【中文标题】模态表中的 UITextView 不起作用【英文标题】:UITextView in a modal sheet is not working 【发布时间】:2019-09-14 14:22:00 【问题描述】:为了使基于 UI 的 NSAttributedString 属性(在托管对象中)的编辑成为可能,使用 UITextView 代替 SwiftUI TextField 视图。文本视图位于由工作表函数呈现的模式视图中。
.sheet(isPresented: $presentSheet) ...
(为了说明和重现,下面的代码是这个场景的简化版本)
模态视图用于编辑通过 ForEach 构造显示在列表中的选定模型项。选定的模型项作为 @Observable 对象传递给模态视图。
选择项目“A”时,模态视图和 UITextView 正确显示此模型项目。如果选择一个新项目“B”,模态视图会正确显示这个“B”项目。但如果现在正在编辑“B”,则更改将影响“A”对象。
这种行为的原因可能是 UIViewRepresentable 视图(代表 UITextView)只初始化了一次。从这里开始,这似乎是由 SwiftUI 中显示工作表(模态)视图的方式引起的(状态变量仅在工作表第一次出现时初始化,而不是第二次出现)。
我可以通过将所选项目作为@Binding 而不是@Observable 对象传递来解决此故障,尽管我不相信这是处理这种情况的正确方法,特别是因为一切正常,如果使用 SwiftUI TextField 代替 UITextView(在简化的情况下)。
值得一提,我似乎已经弄清楚 UITextView 的情况出了什么问题 - 不用说这解决了问题。
在下面列出的代码(重现问题)中,协调器的 init 函数有一个分配,它用父级初始化协调器。由于这是值而不是引用分配,并且由于 Coordinator 仅初始化一次,因此编辑 UITextView 可能会访问错误的父级。
再次,我不确定我的问题解决方案是否正确,因为使用 SwiftUI TextField 时一切正常。因此,我希望看到一些 cmets 解决这个问题。
struct ContentView: View
var states = [StringState("A"), StringState("B"), StringState("C"), StringState("D"), StringState("E")]
@State var presentSheet = false
@State var state = StringState("A")
var body: some View
VStack
Text("state = \(state.s)")
ForEach(states) s in
Button(action:
self.state = s
self.presentSheet.toggle()
)
Text("\(s.s)")
.sheet(isPresented: $presentSheet)
EditView(state: self.state, presentSheet: self.$presentSheet)
struct EditView: View
@ObservedObject var state: StringState
@Binding var presentSheet: Bool
var body: some View
VStack
Text("\(state.s)")
TextView(string: $state.s) // Edit Not OK
TextField("", text: $state.s ) // Edit OK
Button(action:
self.presentSheet.toggle()
)
Text("Back")
struct TextView: UIViewRepresentable
@Binding var string: String
func makeCoordinator() -> Coordinator
Coordinator(self)
func makeUIView(context: Context) -> UITextView
let textview = UITextView(frame: CGRect.zero)
textview.delegate = context.coordinator
return textview
func updateUIView(_ uiView: UITextView, context: Context)
uiView.text = string
class Coordinator : NSObject, UITextViewDelegate
var parent: TextView
init(_ textView: TextView)
self.parent = textView
func textViewDidChange(_ textView: UITextView)
self.parent.string = textView.text!
class StringState: Identifiable, ObservableObject
let ID = UUID()
var s: String
init(_ s : String)
self.s = s
【问题讨论】:
【参考方案1】:一些更改将解决它:
func updateUIView(_ uiView: UITextView, context: Context)
uiView.text = string
context.coordinator.parent = self
还将@Published 添加到您的 ObservableObject:
class StringState: Identifiable, ObservableObject
let ID = UUID()
@Published var s: String
init(_ s : String)
self.s = s
【讨论】:
非常好的答案。它现在可以工作了,无需使用绑定在视图层次结构中向下传递模型对象。以上是关于模态表中的 UITextView 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
UIAlertview 中的 UITextView 在 iOS 4.x 中不起作用
UITextView setContentSize 不起作用?