我想让我的用户使用
PhotosPicker
和 CoreData
添加/保存照片,但我很挣扎。实际上,我对 ID、日期、值和字符串没问题,但对图像就不是这样了。
我想我需要的一切都在这个页面中:https://www.hackingwithswift.com/forums/swiftui/saving-images-with-core-data-in-swiftui/1241 但我不知道为什么我根本无法处理它。
想知道是否有人可以告诉我我应该写什么来代替下面的评论?谢谢!
// ContentView.swift
import SwiftUI
struct ContentView: View {
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)]) var cars: FetchedResults<Car>
@State var showForm = false
var body: some View {
VStack {
Button("Add a car", action: { showForm = true })
.fullScreenCover(isPresented: $showForm, content: { FormView() })
ForEach(cars) { car in
Text(car.name!)
// Image(car.image) ???
}
}
}
}
// FormView.swift
import SwiftUI
import PhotosUI
struct FormView: View {
@Environment(\.managedObjectContext) var viewContext
@Environment(\.dismiss) var dismiss
@State var name = ""
// @State var image = of type ??? from @Binding ???
var body: some View {
VStack {
if #available(iOS 16.0, *) {
TextField("Name of the car", text: $name)
PhotosView(image: $image) // @Binding an image ???
Button("Add", action: {
DataController.shared.addCar(name: name, /* image: of type ??? */, context: viewContext)
dismiss()
})
} else {
Text("Sorry, you can't add a car!")
}
}
}
}
@available(iOS 16.0, *)
struct PhotosView: View {
@State var selectedImage: PhotosPickerItem? = nil
@State var selectedImageData: Data? = nil
// @Binding var image: of type ???
var body: some View {
if let selectedImageData, let uiImage = UIImage(data: selectedImageData) {
ZStack {
Image(uiImage: uiImage)
// .onAppear { image = something } ???
Button("Close", action: { /* Something = nil ??? */ })
}
} else {
PhotosPicker("Select an image", selection: $selectedImage, matching: .images, photoLibrary: .shared())
.onChange(of: selectedImage) { newImage in
Task {
if let data = try? await newImage?.loadTransferable(type: Data.self) { selectedImageData = data }
}
}
}
}
}
// CarModel.xcdatamodeld
// Entity: Car
// Attributes: id (UUID), name (String) and image (Binary Data + Allows External Storage)
// DataController.swift
import Foundation
import CoreData
struct DataController {
// Some lines of code
func save(context: NSManagedObjectContext) {
try? context.save
}
func addCar(name: String, /* image: of type ??? */, context: NSManagedObjectContext) {
let car = Car(context: context)
car.id = UUID()
car.name = name
// car.image = of type ???
save(context: context)
}
}
我写了一个 package 使这更容易一点:
Mediable
的模型:struct MediaItem: Identifiable, Equatable, Hashable, Mediable {
var id: UUID?
var data: Data
static var empty = MediaItem(id: nil, data: Data())
}
@State var image = MediaItem.empty
MediaImage
代替PhotosPicker
:MediaImage(mediable: $image)
.isResizable()
.placeHolder {
Text("Select an Image")
}
image
所做的更改并根据需要保存它:.onChange(of: image) { newValue in
DataController.shared.addCar(name: name, image: newValue.data, context: viewContext)
}
//Add Car function
func addCar(name: String, image: Data, context: NSManagedObjectContext) {
let car = Car(context: context)
car.id = UUID()
car.name = name
car.image = image
save(context: context)
}