如何在 Swiftui 中根据彼此初始化 @State 变量?

Posted

技术标签:

【中文标题】如何在 Swiftui 中根据彼此初始化 @State 变量?【英文标题】:How to initialise @State variables depending on each other in Swiftui? 【发布时间】:2020-07-14 21:55:51 【问题描述】:

我需要将我的 MultilineTextField 视图(包装的 UITextView)分配给变量 textField,以便以后能够从 ContentView 中的按钮调用其方法 updateTextStyle(该方法获取选定的文本并转动它变成粗体)。问题是 MultilineTextField 依赖于@State var range,因此无法编译。有什么可能的解决方法?

struct ContentView: View 
@State private var range: NSRange?
@State var textField = MultilineTextField(rangeSelected: $range)

var body: some View 
    VStack 
        textField
        Button(action: 
            self.textField.updateTextStyle()
        ) 
            Text("Update text style")
        
    

如果相关,MultilineTextField(我试图删除不必要的 - 希望很清楚)

struct MultilineTextField: UIViewRepresentable 
    let textView = UITextView()

    @Binding var rangeSelected: NSRange?
    @State var attributedNoteText = NSMutableAttributedString(string: "Lorem ipsum")

    func makeUIView(context: Context) -> UITextView 
        // ...
    
        textView.delegate = context.coordinator
        return textView
    
    
    func updateUIView(_ uiView: UITextView, context: Context) 
        uiView.attributedText = attributedNoteText
    
    
    func updateTextStyle() 
        if self.rangeSelected != nil 
            // apply attributes (makes the selected text bold)
         else 
            print("rangeSelected is nil")
        
    
    
    func makeCoordinator() -> Coordinator 
        return Coordinator(parent: self, $attributedNoteText)
    
    
    class Coordinator: NSObject, UITextViewDelegate 
        var parent: MultilineTextField
        var text: Binding<NSMutableAttributedString>
        
        init(parent: MultilineTextField, _ text: Binding<NSMutableAttributedString>) 
            self.parent = parent
            self.text = text
        
        
        func textViewDidChange(_ textView: UITextView) 
            let attributedStringCopy = textView.attributedText?.mutableCopy() as! NSMutableAttributedString
            parent.textView.attributedText = attributedStringCopy
            self.text.wrappedValue = attributedStringCopy
        
        
        func textViewDidChangeSelection(_ textView: UITextView) 
            parent.rangeSelected = textView.selectedRange // not sure about this one
           
    

(我知道这里可能存在一些额外的错误 - 这是我第一次在 SwiftUI 中使用 UIKit。感谢您的帮助)

【问题讨论】:

您是否介意发帖MultilineTextField 以获得进一步的帮助 【参考方案1】:

应该不一样,因为view是struct,所以你在按钮动作中调用updateTextStyle()是没有效果的,因为应用于上面textFieldcopy

取而代之的方法应该是如下(scratchy)

struct ContentView: View 
    @State private var range: NSRange?

    // example of style, on place of color your style
    @State var color: Color = .black
    
    var body: some View 
        VStack 
            MultilineTextField(rangeSelected: $range)
                .foregroundColor(self.color)          // style state dependency
            Button(action: 
                self.color = .red     // specify new style
            ) 
                Text("Update text style")
            
        
    

【讨论】:

我添加了附加信息以阐明所需的行为。我的问题是我试图从 MultilineTextField Coordinator 访问选定的文本并将其传递给 struct 方法以更改视图中的属性文本,因此我不能从 ContentView 设置

以上是关于如何在 Swiftui 中根据彼此初始化 @State 变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在swiftui中的视图之间传递变量?

如何防止 SwiftUI 像使用 @StateObject 一样重新初始化我的包装属性?

切换 swiftUI toggle() 时如何触发操作?

swiftUI核心数据模型

如何在外部类中的事件后更新 SwiftUI 按钮?

Swift:SwiftUI 视图的多个条件的内联评估