我有下面的视图,我想使用 PhotosPicker 从图库加载图像并将其显示给用户。我还想将图像转换为数据,以便我可以将其存储在 SwiftData 数据库中。
更新到 iOS 18、xcode 16.0 beta 并将严格并发从最小更改为完整,并将 swift 版本从 5 更改为 6 后,我在
Sending main actor-isolated value of type 'PhotosPickerItem' with later accesses to nonisolated context risks causing data races
线上收到错误 if let data = try? await selectedPhoto?.loadTransferable(type: Data.self)
。
我还有很多错误,但我设法改掉了它们。该应用程序按预期工作,但我不知道如何解决此错误。
任何帮助将不胜感激。
注意:为了简单起见,我从下面的代码中删除了
Model
的所有其他属性。
struct AddModel: View {
@Environment(ViewModel.self) private var viewModel
@Environment(\.dismiss) private var dismiss
@State private var showPhotosPicker: Bool = false
@State private var selectedPhoto: PhotosPickerItem?
@State private var selectedPhotoData: Data?
var body: some View {
Form {
photoSection
}
.toolbar {
toolbarItems
}
}
}
// MARK: - View Components
extension AddShoeView {
@ViewBuilder
private var photoSection: some View {
Section {
VStack(spacing: 12) {
ZStack {
if let selectedPhotoData, let uiImage = UIImage(data: selectedPhotoData) {
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.frame(width: 150, height: 150)
.clipShape(RoundedRectangle(cornerRadius: 12))
} else {
Image(systemName: "square.fill")
.resizable()
.foregroundStyle(.secondary)
.frame(width: 150, height: 150)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
Text("Add Photo")
.font(.callout)
.fontWeight(.semibold)
.foregroundStyle(.white)
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background(Color(uiColor: .secondarySystemBackground))
.cornerRadius(20)
}
.frame(maxWidth: .infinity)
.photosPicker(isPresented: $showPhotosPicker, selection: $selectedPhoto, photoLibrary: .shared())
.onTapGesture {
showPhotosPicker.toggle()
}
.task(id: selectedPhoto) {
if let data = try? await selectedPhoto?.loadTransferable(type: Data.self) {
selectedPhotoData = data
}
}
}
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets())
}
@ToolbarContentBuilder
private var toolbarItems: some ToolbarContent {
ToolbarItem(placement: .confirmationAction) {
Button {
viewiewModel.addModel(image: selectedPhotoData)
dismiss()
} label: {
Text("Save")
}
}
}
}
@Observable
final class ViewModel: {
@ObservationIgnored private var modelContext: ModelContext
private(set) var models: [Model] = []
init(modelContext: ModelContext) {
self.modelContext = modelContext
fetchModels()
}
func addModel(image: Data?) {
let model = Model(image: image)
modelContext.insert(shoe)
save()
}
private func fetchModels() {
do {
let descriptor = FetchDescriptor<Model>()
self.models = try modelContext.fetch(descriptor)
} catch {
print("Fetching shoes failed, \(error.localizedDescription)")
}
}
private func save() {
do {
try modelContext.save()
} catch {
print("Saving context failed, \(error.localizedDescription)")
}
fetchModels()
}
}
将
MainActor
添加到 View
@MainActor
struct AddModel: View {
这是 iOS 18+ 中的标准配置,但必须添加到早期版本的
View
中。