首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SwiftUI绑定在项目重新排序后编辑错误的TextField

SwiftUI绑定在项目重新排序后编辑错误的TextField
EN

Stack Overflow用户
提问于 2021-10-12 04:18:05
回答 1查看 142关注 0票数 0

Xcode 13 beta 5,iOS 14,macOS 11.6

我有一个父SwiftUI视图,其中列出了一些子视图。每个孩子都绑定到一个NSViewRepresentable上。一切正常工作,我可以像预期的那样编辑值。但是,一旦我重新排序列表中的项目并编辑一个字段,它就会编辑错误的字段。看来,绑定与上一项订单保持完整。

如下所示:

以下是家长:

代码语言:javascript
运行
复制
struct ParentView: View {
  @StateObject var model = ThingModel.shared
  
  var body: some View {
    VStack{
      ForEach($model.things){ $thing in
        ChildView(thing: $thing)
        //Reorder
        .onDrag{
          model.draggedThing = thing
          return NSItemProvider(object: NSString())
        }
      }
      Text("Value: \(model.value)").font(.title)
    }
    .frame(width:300, height: 200)
  }
}

...and,这是子视图:

代码语言:javascript
运行
复制
struct ChildView: View {
  @Binding var thing: Thing
  @StateObject var model = ThingModel.shared
  
  var body: some View{
    HStack{
      GrowingField(text: $thing.text, submit: {
        model.value = thing.text
        print(thing.text)
      })
      Text(" = ")
        .opacity(0.4)
    }
    .padding(10)
    .onDrop(of: [UTType.text], delegate: ThingReorderDelegate(hoveredThing: thing))
  }
}

最后,这里是NSViewRepresentable,称为GrowingField。为了简单起见,我省略了NSTextField子类。

代码语言:javascript
运行
复制
struct GrowingField: NSViewRepresentable{
  @Binding var text: String
  var submit:(() -> Void)? //Hit enter
  
  func makeNSView(context: Context) -> NSTextField {
    let textField = NSTextField()
    textField.delegate = context.coordinator
    textField.stringValue = text
    
    return textField
  }
  func updateNSView(_ nsView: NSTextField, context: Context) {
    nsView.stringValue = text
    context.coordinator.textBinding = $text
  }

  //Delegates
  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
  class Coordinator: NSObject, NSTextFieldDelegate {
    let parent: GrowingField
    var textBinding : Binding<String>?
    
    init(_ field: GrowingField) {
      self.parent = field
    }
    
    func controlTextDidChange(_ obj: Notification) {
      guard let textField = obj.object as? NSTextField else { return }
      self.textBinding?.wrappedValue = textField.stringValue
    }
    
    //Listen for certain keyboard keys
    func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
      switch commandSelector{
        case #selector(NSStandardKeyBindingResponding.insertNewline(_:)):
        //- Enter -
        parent.submit?()
        textView.window?.makeFirstResponder(nil) //Blur cursor
        return true
      default:
        return false
      }
    }
    
  }
}

为什么到NSViewRepresentable的绑定在重新排序后不跟随字段?

下面是一个示例项目下载并试用它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-12 04:31:54

我相信这个问题(窃听器?)使用ForEach-generated绑定。

如果您放弃了生成的绑定并创建了自己的绑定,那么一切似乎都如期而至。

添加到ThingModel

代码语言:javascript
运行
复制
func bindingForThing(id: String) -> Binding<Thing> {
    .init {
        self.things.first { $0.id == id }!
    } set: { newThing in
        self.things = self.things.map { $0.id == id ? newThing : $0 }
    }
}

ParentView

代码语言:javascript
运行
复制
ForEach(model.things){ thing in
    ChildView(thing: model.bindingForThing(id: thing.id))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69535025

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档