有什么方法可以将从 imagePicker 中选择的图像与在编辑模式下保存的字段相关联吗?

Is there any way I can associate the image selected from imagePicker with the field that it’s saved when in Edit mode?

我有下面的详细信息视图,它显示了上一个 listView 中选定记录的生日贺卡,当单击“编辑”按钮时,会显示字段,我们可以编辑个人数据,包括个人资料图片。关键是编辑后单击“完成”时所有字段都正确 updated/saved 除了图像。我相信这是因为编辑模式跟踪 viewContext 的变化,而 imagePicker 正在将图像处理成一个单独的 var (pic)。有什么方法可以将 imagePicker 中的图像 (var pic) 与完成编辑后保存的 birthday.pic 字段相关联?

详细视图:

import SwiftUI

struct BirthdaysDetailView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @Environment(\.editMode) private var editMode
    @Environment(\.dismiss) private var dismiss
    
    @ObservedObject var birthday: Nivers
    
    @State private var isEditing: Bool = false
    @State private var isShowPhotoLibrary = false
    @State private var pic: Data = Data(count: 0)
    
    var body: some View {
        VStack {
            if editMode?.wrappedValue.isEditing == true {
                VStack {
                    ScrollView {
                        VStack {
                            if pic.count != 0 {
                                ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
                                    Image(uiImage: UIImage(data: pic)!)
                                        .resizable()
                                        .aspectRatio(contentMode: .fill)
                                        .mask(Circle())
                                        .overlay(Circle().stroke(Color.text, lineWidth: 2))
                                        .frame(width: 150, height: 150)
                                        .padding(.bottom, 5)
                                    
                                    // Cancel Button...
                                    Button(action: { birthday.pic = Data(count: 0) }) {
                                        Image(systemName: "xmark.circle")
                                            .foregroundColor(Color.red)
                                            .padding(6)
                                            .clipShape(Circle())
                                    }
                                }
                                .padding(.bottom)
                                .opacity(1)
                            } else {
                                Image(systemName: "person.crop.circle")
                                    .font(.system(size: 50).weight(.ultraLight))
                                    .foregroundColor(Color.text)
                                    .clipped()
                            }
                            Button(action: {
                                self.isShowPhotoLibrary = true
                            }) {
                                HStack {
                                    Image(systemName: "photo")
                                        .font(.system(size: 10))
                                    Text("Photo library")
                                        .font(.caption2)
                                }
                                .frame(minWidth: 100, minHeight: 20)
                                .background(Color.text)
                                .foregroundColor(.white)
                                .cornerRadius(5)
                            }
                            .padding(.bottom, 10)
                            HStack {
                                TextField("Name", text: $birthday.name, onEditingChanged: { self.isEditing = [=10=] })
                                TextField("Last Name", text: $birthday.lastName, onEditingChanged: { self.isEditing = [=10=] })
                                Button {
                                    birthday.isFavorite = true
                                } label: {
                                    VStack {
                                        if birthday.isFavorite {
                                            Image(systemName: "star.fill")
                                                .foregroundColor(Color.yellow)
                                                .font(Font.system(.caption2, design: .default).weight(.light))
                                        } else {
                                            Image(systemName: "star")
                                                .foregroundColor(Color.yellow)
                                                .font(Font.system(.caption2, design: .default).weight(.light))
                                        }
                                    }
                                    .padding(5)
                                }
                            }
                            .font(.title)
                            VStack {
                                DatePicker(selection: $birthday.birthDate, displayedComponents: [.date], label: { Text("Date") })
                                    .labelsHidden()
                                    .datePickerStyle(.graphical)
                                    .frame(width: 250)
                                TextField("Phone", text: $birthday.phone, onEditingChanged: { self.isEditing = [=10=] })
                                    .textFieldStyle(.roundedBorder)
                                    .padding(.bottom, 5)
                                TextField("Email", text: $birthday.email, onEditingChanged: { self.isEditing = [=10=] })
                                    .textFieldStyle(.roundedBorder)
                                    .padding(.bottom, 50)
                            }
                            .foregroundColor(Color.text)
                            Spacer()
                        }
                        .padding()
                        .background(Color.background)
                    }
                    .sheet(isPresented: $isShowPhotoLibrary) {
                        ImagePicker(sourceType: .photoLibrary, selectedImage: $pic)
                    }
                }
                .navigationBarColor(.systemGray5)
            } else {
                ZStack {
                    LottieView(name: "confetti", loopMode: .loop)
                        .frame(width: 230, height: 250)
                    VStack {
                        if let image = birthday.image {
                            ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
                                image
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .mask(Circle())
                                    .frame(width: 150, height: 150)
                                    .clipped()
                                    .padding(.bottom, 5)
                            }
                            .padding(.bottom)
                            .opacity(1)
                        }
                        HStack {
                            Text("\(birthday.name) \(birthday.lastName)")
                                .font(Font.system(.title, design: .rounded).weight(.heavy))
                                .padding()
                                .foregroundColor(Color.primary)
                            if birthday.isFavorite {
                                Image(systemName: "star.fill")
                                    .foregroundColor(Color.yellow)
                                    .font(Font.system(.callout, design: .default).weight(.medium))
                            }
                        }
                        Text("\(age(date: birthday.birthDate)) years old")
                            .font(Font.system(.body, design: .rounded).weight(.ultraLight))
                            .padding(.bottom, 5)
                            .foregroundColor(Color.primary)
                        RoundedRectangle(cornerRadius: 30, style: .continuous)
                            .fill(Color.black.opacity(0.5))
                            .frame(height: 40)
                            .clipped()
                            .padding(.horizontal)
                            .overlay(Text("\(birthday.birthDate, formatter: itemFormatter)")
                                        .font(Font.system(.body, design: .rounded).weight(.semibold))
                                        .foregroundColor(Color.white), alignment: .center)
                        if checkBirthdayDates(date: birthday.birthDate) {
                            Text("TODAY")
                                .font(Font.system(.caption, design: .rounded).weight(.bold))
                                .padding()
                                .foregroundColor(Color.primary)
                        } else {
                            Text("\((relativeBirthDate(date: birthday.birthDate)))")
                                .font(Font.system(.caption, design: .rounded).weight(.light))
                                .padding()
                                .foregroundColor(Color.primary)
                        }
                    }
                }
                .padding()
                .background(Color.background)
                .cornerRadius(20)
                .padding(10)
                .navigationBarColor(.systemGray5)
            }
        }
        .navigationBarBackButtonHidden(true)
        .edgesIgnoringSafeArea(.bottom)
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                Button(action: {
                    dismiss()
                }) {
                    Image(systemName: "arrow.backward.square.fill")
                        .font(.body)
                        .foregroundColor(Color.text)
                }
            }
            ToolbarItem(placement: .navigationBarTrailing) {
                EditButton()
                    .font(.body)
                    .foregroundColor(Color.text)
            }
        }
        .onReceive(birthday.objectWillChange) { _ in
            if viewContext.hasChanges {
                try?  viewContext.save()
            }
        }
    }
}

上面的代码正确显示了创建记录时保存的数据和图像,它在编辑模式下通过选择另一个图像更改了图片,但是当单击完成时,除了新图像之外所有更改的数据都被保存。 我进行了大量研究并尝试了许多其他方法,但还没有解决这个问题。

有什么想法吗?

图片选择器:

import UIKit
import SwiftUI

struct ImagePicker: UIViewControllerRepresentable {
    var sourceType: UIImagePickerController.SourceType = .photoLibrary
    
    @Binding var selectedImage: Data
    @Environment(\.presentationMode) private var presentationMode
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        
        let imagePicker = UIImagePickerController()
        imagePicker.allowsEditing = false
        imagePicker.sourceType = sourceType
        imagePicker.delegate = context.coordinator
        
        return imagePicker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
        
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        
        var parent: ImagePicker
        
        init(_ parent: ImagePicker) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            
            if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                parent.selectedImage = image.jpegData(compressionQuality: 0.1)!
            }
            parent.presentationMode.wrappedValue.dismiss()
        }
    }
}

所以我会这样做而不是绑定:

      import UIKit
  import SwiftUI

  struct ImagePicker: UIViewControllerRepresentable {
     var sourceType: UIImagePickerController.SourceType = .photoLibrary
     
     // @Binding var selectedImage: Data
     let completion: (_ selectedImage: UIImage?) -> Void
     @Environment(\.presentationMode) private var presentationMode
     
     func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        
        let imagePicker = UIImagePickerController()
        imagePicker.allowsEditing = false
        imagePicker.sourceType = sourceType
        imagePicker.delegate = context.coordinator
        
        return imagePicker
     }
     
     func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
        
     }
     
     func makeCoordinator() -> Coordinator {
        Coordinator(self)
     }
     
     final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        
        var parent: ImagePicker
        
        init(_ parent: ImagePicker) {
              self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
              
              if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                    self.parent.completion(image.jpegData(compressionQuality: 0.1)!)
              }
              parent.presentationMode.wrappedValue.dismiss()
        }
     }
  }

在视图中你可以这样使用它:

    ImagePicker(sourceType: .photoLibrary) {newPicture in
                                
                                //Do what you want here
                                self.pic = newPicture
                            }