Сохранение изображений в виде двоичных данных в основных данных — Swift

#swift #core-data #swiftui

Вопрос:

Следующий код успешно сохраняет Car сущности в Core Data . Как вы можете видеть Car , у сущности есть атрибут Binary Data , в котором я сохраняю изображение, чтобы использовать его в качестве миниатюры. Моя проблема с приведенным ниже кодом заключается в том, что если пользователь решит не добавлять изображение в некоторые из Car s, мне нужно предоставить изображение по умолчанию, единственный вариант, который я могу придумать defaultCarImage , — это поместить его в Assets папку, а затем вызвать его и сохранить для автомобилей, для которых пользователь не выбрал изображение. Моя проблема с этим подходом заключается в том, что если пользователь решит не использовать изображения для любого из своих автомобилей, я буду сохранять одно и то же изображение в десятках или сотнях автомобилей. Есть ли способ каким-то образом повторно использовать изображение, в котором оно уже сохранено Core Data ?

Каков правильный подход к предоставлению изображения по умолчанию для Car объектов, для которых пользователь не предоставил изображение?

сущность

 Car
 

Атрибут

 carImage    Binary Data (Allows External Storage)
make        String
model       String
 

Менеджер основных данных

 import SwiftUI
import CoreData

class CoreDataManager{
    static let instance = CoreDataManager()
    
    let container: NSPersistentContainer
    let context: NSManagedObjectContext
    
    init(){
        container = NSPersistentContainer(name: "CoreDataContainer")
        container.loadPersistentStores { (description, error) in
            if let error = error{
                print("Error loading Core Data. (error)")
            }
        }
        context = container.viewContext
    }
    
    func save(){
        do{
            try context.save()
            print("Saved successfully!")
        }catch let error{
            print("Error saving Core Data. (error.localizedDescription)")
        }
    }
}
 

Модель Основных Данных

 import Foundation
import CoreData
import UIKit

class CoreDataViewModel: ObservableObject{
    
    let manager = CoreDataManager.instance
    
    @Published var cars: [Car] = []

    func addCar(make: String, model: String, image:UIImage){
        
        let imageData = image.jpegData(compressionQuality: 0.1)
        
        let car = Car(context: manager.context)
        car.make = make
        car.model = model
        car.carImage = imageData
        save()
        getCars()
    }
}
 

Просмотр содержимого

 struct ContentView: View {
    @StateObject var coreDataViewModel = CoreDataViewModel()
    @State private var makeInput:String = ""
    @State private var modelInput:String = ""
    @State private var carImageFromPicker: UIImage?

    var body: some View {
        VStack{
            if let inputImage = carImageFromPicker {
                Image(uiImage: inputImage)
                    .resizable()
                    .onTapGesture {
                        // show camera
                    }
            } else {
                Image(systemName: "car.fill")// default image 
                .onTapGesture {
                    // show camera
                }
            }

            Button(action: {
                saveNewCar()
            }) {
                Text("Save")
            }
        }
    }

    func saveNewCar(){
        coreDataViewModel.addCar(make: makeInput, model: modelInput, image: carImageFromPicker!)
    }
}
 

Комментарии:

1. Ваш код сохранит только изображение, выбранное из средства выбора изображений (возможно, какой-то код отсутствует), поэтому сохраните его таким образом и сделайте свойство изображения необязательным. Затем вы можете использовать одно изображение по умолчанию всякий раз, когда свойство изображения автомобиля равно нулю

2. Я сделал carImage необязательный параметр в Основных данных. Итак, теперь для объектов без изображения я просто предоставляю пустые Data() или Data(count:0) основные данные? Опять же, чего я пытаюсь избежать, так это многократного сохранения одного и того же изображения в основных данных.

3. Кажется, я понял. После внесения carImage необязательных изменений в основные данные я предоставляю пустое Data() поле для объектов без изображений и использую defaultImage папку «Ресурсы» только для визуальных целей. Спасибо, что указали на тот факт, что двоичные данные могут быть необязательными.

4. Если свойство является необязательным, то оно вам не нужно Data() . Оставьте собственность в покое, и она будет равна нулю. Или установите его равным нулю, чтобы было понятно, если вы предпочитаете.