SwiftUI ImagePicker сохраняет (Изображение -> UIImage -> Данные) в основные данные - PullRequest
1 голос
/ 10 июля 2020

Привет всем, я немного расстроен, так что надеюсь получить помощь. Мой проект находится в SwiftUI. Я хочу использовать средство выбора изображений, чтобы сохранить изображение в Core Data. Мне удалось заставить ImagePicker работать, но я изо всех сил пытаюсь преобразовать Image -> UIImage -> Data, чтобы затем сохранить его. Проект работает без ошибок, но изображение не сохраняется. Чтобы узнать, где находится проблема, я реализовал 3 заявления для печати. Изображение = дает значение, UIImage (inputImage) = nil, Data, конечно, равно нулю.

import SwiftUI


struct AddNewBean: View {
    
    @Environment(\.presentationMode) var presentationMode
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: Bean.entity(), sortDescriptors: []) var beans: FetchedResults<Bean>
    @State var BeanRoaster: String = ""
    @State var BeanName: String = ""
    @State var BeanStyle: String = "Dark"
    
    @State private var RoastDate = Date()
        var dateFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        return formatter }
    
    @State private var showImagePicker : Bool = false
    @State private var image : Image?
    @State private var inputImage: UIImage?
    @State var imageAlt: Data = .init(count: 0)
    
    let RStyles = ["Dark", "Medium", "Light"]
    
    func loadImage() {
        guard let inputImage = inputImage else { return }
        image = Image(uiImage: inputImage)
    }
    
    var body: some View {
        
        NavigationView {
            VStack {
                Form {
                    VStack {
                        image?.resizable().scaledToFit().aspectRatio(contentMode: .fit)
                        HStack {
                            Spacer()
                            Button("Open Camera"){
                                self.showImagePicker = true
                            }.padding(5)
                                .foregroundColor(Color.white)
                                .background(Color.accentColor)
                                .cornerRadius(10)
                            Spacer()
                        }.sheet(isPresented: self.$showImagePicker, onDismiss: loadImage){
                            PhotoCaptureView(showImagePicker: self.$showImagePicker, image: self.$image)
                        }
                    }
                    TextField("Röster", text: $BeanRoaster)
                    TextField("Name der Bohne", text: $BeanName)
                    Picker("Roestung", selection: $BeanStyle) {
                        ForEach(RStyles, id: \.self) {
                            Text($0)
                        }
                    }
                    DatePicker(selection: $RoastDate, in: ...Date(), displayedComponents: .date) {Text("Röstdatum")}
   
                    HStack {
                        Spacer()
                        if BeanRoaster != "" && BeanName != "" {
                            Button(action: {
                                //....
                                let pickedImage = self.inputImage?.jpegData(compressionQuality: 1.0)
                                                                print("image, inputimage, pickedImage")
                                print(self.image as Any) // prints:  Optional(SwiftUI.Image(provider: SwiftUI.ImageProviderBox<__C.UIImage>))
                                print(self.inputImage as Any) // prints: nil
                                print(pickedImage as Any) // prints: nil
                                //.....
                                let bean = Bean(context: self.moc)
                                bean.id = UUID()
                                bean.roaster = "\(self.BeanRoaster)"
                                bean.name = "\(self.BeanName)"
                                bean.roastStyle = "\(self.BeanStyle)"
                                bean.roastDate = self.RoastDate
                                bean.active = true
                                bean.img = pickedImage
                                
                                try? self.moc.save()
                                self.presentationMode.wrappedValue.dismiss()
                            }) {
                                Image(systemName: "tray")
                                    .foregroundColor(.blue)
                                    .font(.largeTitle)
                                    .padding(.vertical)
                            }
                            Text("Save").foregroundColor(.blue)
                            Spacer()
                        } else {
                            HStack {
                                Spacer()
                                Text("Trage Bohnendaten ein!")
                                Spacer()
                            }
                        } 
                    } 

                    Section {
                        HStack {
                            Spacer()
                            Button(action: {self.presentationMode.wrappedValue.dismiss()}) {
                                Image(systemName: "")
                                    .foregroundColor(.red)
                                    .font(.largeTitle)
                                    .padding(.vertical)
                            }
                            Text("Dismiss").foregroundColor(.red)
                            Spacer()
                        }
                    }
                }.navigationBarTitle("New Bean")
            }
        }
    }
}

1 Ответ

0 голосов
/ 11 июля 2020

В приведенном выше коде есть несколько ошибок. Я воссоздал решение, которое также содержит изменение ImagePicker.

То, что делает ваш ImagePicker, изменяет @State Image. Вы показываете это изображение, и будет показано выбранное вами изображение. Здесь все нормально. Однако вы не сможете получить UIImage изображения. Это невозможно, если вы посмотрите на интерфейс класса Image.

Пусть ваш Image Picker вернет UIImage

Я не уверен, какой ImagePicker вы использовали. Однако вы можете просто изменить версию здесь , чтобы вернуть UIImage.

. Сохраняет логическое значение, только если отображается imagePicker и UIImage.

@State private var showImagePicker : Bool = false
@State private var image : UIImage?

Каждый раз, когда UIImage изменяется, вы можете обновить свое изображение. Просто используйте:

if (self.image != nil)
{
    Image(uiImage: self.image!).resizable().scaledToFit().aspectRatio(contentMode: .fit)
}

Теперь, когда дело доходит до сохранения вашего UIImage в вашей базе данных, вам необходимо преобразовать его в объект данных. Это просто.

Button(action: {
    
    //Not nil
    print(self.image)

    //PNG Representation as Data
    let imageData = self.image!.pngData()
    
    //Data type here --> Data
    print(type(of: imageData))

Здесь вы видите, что это из объекта Data, и данные можно просто сохранить в CoreData.

Единственное, что вам еще нужно исправить, это то, что вы не передают привязку изображения вашему ImagePicker, вместо этого передайте привязку как UIImage.

Будет выглядеть примерно так:

struct CaptureImageView {
    
    @Binding var isShown: Bool
    @Binding var image: UIImage?
    
    func makeCoordinator() -> Coordinator {
      return Coordinator(isShown: $isShown, image: $image)
    }
}

А в didFinishPickingMediaWithInfo вы просто установите UIImage.

func imagePickerController(_ picker: UIImagePickerController,
            didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
 guard let unwrapImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
 imageInCoordinator = unwrapImage
 isCoordinatorShown = false
}

Опять же, это не мой ImagePicker. Я просто изменил его, чтобы вы прояснили, что не так и что вам нужно исправить. У меня есть рабочее решение, и это возможно. Просто убедитесь, что вы используете, а не изображение, а не UIImage, чтобы ссылаться на него.

...