SwiftUI:拖入空列表时崩溃

3
在Xcode 12.1中,无论是在iOS还是macOS上,使用SwiftUI将对象拖动到空列表时,在[UITableViewRowData numberOfRowsInSection:]()中出现内部崩溃,并且没有命令行输出。
即使我尝试使用List的.onInsert(...)处理拖放,它仍会崩溃。(onInsert闭包从未被调用)
这是一个最小的可重现示例:
struct ContentView: View {
    let string = "Hello World"
    
    var body: some View {
        HStack {
            Text(string) // Object to drag
                .onDrag({NSItemProvider(object: string as NSString)})
            
            List {} // When dragging object onto here, there's a crash
        }
    }
}

我做错了什么?

1个回答

3
是的,通过崩溃分析,看起来是SwiftUI的缺陷,值得向Apple报告反馈。
以下是处理此场景的可能方法,即使/在Apple修复崩溃后仍然安全并继续工作。
使用Xcode 12 / iOS 14进行测试(为演示添加了列表边框) 演示
import SwiftUI
import UniformTypeIdentifiers

struct ContentView: View {
    let string = "Hello World"
    @State private var items: [String] = []

    // border with highlight added just for better visibility
    @State private var dragOver = false
    
    var body: some View {
        HStack {
            Text(string) // Object to drag
                .onDrag({NSItemProvider(object: string as NSString)})
            
            List {
                ForEach(items, id: \.self) {
                    Text($0)
                }
                .onInsert(of: [.text]) { index, providers in
                    self.handle(providers: providers, index: index)
                }
            }
            .overlay(helperOverlay()) // << helper to handle empty list
            .border(dragOver ? Color.red : Color.green, width: 4) // << just for demo
        }
    }
    
    private func helperOverlay() -> some View {
        Group {
            if items.isEmpty {
                Color.white.opacity(0.0001)  // << should be something opaque
                    .onDrop(of: [.text], isTargeted: $dragOver) { providers -> Bool in
                        self.handle(providers: providers)
                        return true
                    }
            }
        }
    }
    
    private func handle(providers: [NSItemProvider], index: Int? = nil) {
        guard let provider = providers.first else { return }
        provider.loadDataRepresentation(forTypeIdentifier: "public.text") { (data, _) in
            guard let data = data, let value = String(data: data, encoding: .utf8) else { return }
            if let index = index {
                items.insert(value, at: index)
            } else {
                items.append(value)
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接