[英]Why sometimes my selection doesn't get highlighted in macOS SwiftUI List after I've added an item when List items are stored through @AppStorage
我似乎找不到我做错了什么。
这是设置:
问题如下:
这个问题可能发生在 80% 的时间里,并非总是如此。 当我将新项目添加到列表中时会发生这种情况,并且我选择了该项目而没有先单击列表中的任何其他位置。 如果我先单击另一个项目,或者在列表中没有项目的空间中单击,则在之后选择新项目将正常工作,并且该项目将突出显示。 这让我觉得这可能是一个国家问题? 但我找不到我做错的地方。
这是代码:
import SwiftUI
// to save Sets through AppStorage
extension Set: RawRepresentable where Element: Codable {
public init?(rawValue: String) {
guard let data = rawValue.data(using: .utf8) else { return nil }
guard let result = try? JSONDecoder().decode(Set<Element>.self, from: data) else { return nil}
self = result
}
public var rawValue: String {
guard let data = try? JSONEncoder().encode(self) else { return "[]" }
guard let result = String(data: data, encoding: .utf8) else { return "[]" }
return result
}
}
struct ContentView: View {
@AppStorage("apps") var apps: Set<String> = []
@State private var appsSelection: Set<String> = []
var body: some View {
Form {
List(Array(apps), id: \.self, selection: $appsSelection) { app in
Text(app)
}
.contextMenu {
Button("Delete") {
for selection in appsSelection {
apps.remove(selection)
}
}
.disabled(appsSelection.isEmpty)
}
.onDeleteCommand {
for selection in appsSelection {
apps.remove(selection)
}
}
.listStyle(.bordered(alternatesRowBackgrounds: true))
.onDrop(of: [.fileURL], delegate: AppsDropDelegate(apps: $apps))
}
}
}
// the DropDelegate
private struct AppsDropDelegate: DropDelegate {
@Binding var apps: Set<String>
func validateDrop(info: DropInfo) -> Bool {
guard info.hasItemsConforming(to: [.fileURL]) else { return false }
let providers = info.itemProviders(for: [.fileURL])
var result = false
for provider in providers {
if provider.canLoadObject(ofClass: URL.self) {
let group = DispatchGroup()
group.enter()
_ = provider.loadObject(ofClass: URL.self) { url, _ in
let itemIsAnApplicationBundle = try? url?.resourceValues(forKeys: [.contentTypeKey]).contentType == .applicationBundle
result = result || (itemIsAnApplicationBundle ?? false)
group.leave()
}
_ = group.wait(timeout: .now() + 0.5)
}
}
return result
}
func performDrop(info: DropInfo) -> Bool {
let providers = info.itemProviders(for: [.fileURL])
var result = false
for provider in providers {
if provider.canLoadObject(ofClass: URL.self) {
let group = DispatchGroup()
group.enter()
_ = provider.loadObject(ofClass: URL.self) { url, _ in
let itemIsAnApplicationBundle = (try? url?.resourceValues(forKeys: [.contentTypeKey]).contentType == .applicationBundle) ?? false
if itemIsAnApplicationBundle, let url = url, let app = Bundle(url: url), let bundleIdentifier = app.bundleIdentifier {
DispatchQueue.main.async {
apps.insert(bundleIdentifier)
}
result = result || true
}
group.leave()
}
_ = group.wait(timeout: .now() + 0.5)
}
}
return result
}
}
提前致谢。
好的,经过更多测试,这似乎是一个 SwiftUI 错误。 可能与@AppStorage 的缓存机制有关,因为它不会即时从磁盘写入/读取。 SwiftUI 有时会发布更新,有时不会。 这已向 Apple 报告为 FB10029588。 此处的示例项目: https ://github.com/godbout/ListDrop。
解决这个问题的方法是手动更新选择。 为此,我创建了一个@ObservableObject
,它通过@AppStorage 处理项目列表,并通过@Published 属性处理选择。 删除选择时,我手动将属性设置为空。 这确实解决了问题。 下次添加项目时,它们会在选中时突出显示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.