[英]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.