如何正确设置图像加载器(SwiftUI)?

问题描述 投票:0回答:1

我目前正在开发 ProfilImagePicker,它一切正常,但我还内置了一个存储系统,它也可以工作。 但我的问题是,当我选择一张照片时,它不会立即设置,而是只有当我完全重新加载页面时,或者当我插入新图像时,才会插入第一张图像。

我希望有人能帮助我。

存储系统

class AppStorageHelperProfilImage: ObservableObject {
    @Published var selectedImage: UIImage?

    static func saveProfileImage(_ image: UIImage) {
        if let data = image.jpegData(compressionQuality: 1.0) {
            do {
                try data.write(to: profileImagePath)
            } catch {
                print("Fehler beim Speichern des Profilbilds: \(error.localizedDescription)")
            }
        }
    }

    static func loadProfileImage() -> UIImage? {
        if let data = try? Data(contentsOf: profileImagePath) {
            return UIImage(data: data)
        }
        return nil
    }

    static func deleteProfileImage() {
        do {
            try FileManager.default.removeItem(at: profileImagePath)
        } catch {
            print("Mistake by saving the picture \(error.localizedDescription)")
        }
    }

    private static var profileImagePath: URL {
        FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("profileImage.jpg")
    }
}

我的变量


@StateObject private var appStorageHelper = AppStorageHelperProfilImage()

@State private var selectedImage: UIImage?
   private var profileImage: UIImage? {
       AppStorageHelperProfilImage.loadProfileImage()
    }
@State private var isProfileImagePickerPresented = false

图像


Image(uiImage: profileImage ?? {
                            let symbolImage = UIImage(systemName: "person.circle")?.withRenderingMode(.alwaysOriginal)
                            let imageRenderer = UIGraphicsImageRenderer(size: CGSize(width: 120, height: 120))

                            return imageRenderer.image { _ in
                                symbolImage?.draw(in: CGRect(x: 0, y: 0, width: 120, height: 120))
                            }
                        }())
                        .resizable()
                        .scaledToFill()
                        .frame(width: 120, height: 120)
                        .clipShape(Circle())
                        .onTapGesture {
                            isProfileImagePickerPresented.toggle()
                        }
                        .id(appStorageHelper.selectedImage)
                        .sheet(isPresented: $isProfileImagePickerPresented) {
                            ProfileImagePicker(selectedImage: $appStorageHelper.selectedImage, isImagePickerPresented: $isProfileImagePickerPresented)
                                .onDisappear {
                                    // Aktualisieren Sie die Ansicht, wenn das Bild ausgewählt wurde
                                    appStorageHelper.selectedImage.map { saveProfileImage($0) }
                                }
                        }
                        .padding()

个人资料图像选择器

struct ProfileImagePicker: UIViewControllerRepresentable {
    @Binding var selectedImage: UIImage?
    @Binding var isImagePickerPresented: Bool

    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        var parent: ProfileImagePicker

        init(parent: ProfileImagePicker) {
            self.parent = parent
        }

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let selectedImage = info[.originalImage] as? UIImage {
                parent.selectedImage = selectedImage
            }
            parent.isImagePickerPresented = false
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.isImagePickerPresented = false
        }
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<ProfileImagePicker>) -> UIImagePickerController {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = context.coordinator
        return imagePicker
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ProfileImagePicker>) {
        // Update UI if needed
    }
}

迷你版

Image(uiImage: (selectedImage ?? UIImage(systemName: "person.circle"))!)
                                .resizable()
                                .scaledToFill()
                                .frame(width: 50, height: 50)
                                .clipShape(Circle())
                                .id(appStorageHelper.selectedImage)
                                .onAppear {
                                    if selectedImage == nil {
                                        if let loadedImage = AppStorageHelperProfilImage.loadProfileImage() {
                                            selectedImage = loadedImage
                                        }
                                    }
                                }
                                .padding()
image swiftui storage profile
1个回答
1
投票

快速的解决方案是像这样设置这一行:

Image(uiImage: appStorageHelper.selectedImage ?? // Rest of the code as it was here
.

问题是 profileImage 不会重绘 UI,因为它是计算属性,因此它不能是状态变量。 另一个解决方案是在选择新图像后更新 selectedImage 变量。为此,我向 ProfileImagePicker 结构添加了一个回调,如下所示:

struct ProfileImagePicker: UIViewControllerRepresentable {
    @Binding var selectedImage: UIImage?
    @Binding var isImagePickerPresented: Bool
    
    /// Add this callback
    var onImageChosen: (UIImage?) -> Void
    
    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        var parent: ProfileImagePicker
        
        init(parent: ProfileImagePicker) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let selectedImage = info[.originalImage] as? UIImage {
                parent.selectedImage = selectedImage
                /// Call the callback here and pass it the new chosen image
                parent.onImageChosen(selectedImage)
            }
            parent.isImagePickerPresented = false
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.isImagePickerPresented = false
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<ProfileImagePicker>) -> UIImagePickerController {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = context.coordinator
        return imagePicker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ProfileImagePicker>) {
        // Update UI if needed
    }
}

然后像这样更新其余的代码:

@StateObject private var appStorageHelper = AppStorageHelperProfilImage()

@State private var selectedImage: UIImage?
private var profileImage: UIImage? {
    AppStorageHelperProfilImage.loadProfileImage()
}
@State private var isProfileImagePickerPresented = false

var body: some View {
    VStack {
        Image(uiImage: selectedImage ?? {
            let symbolImage = UIImage(systemName: "person.circle")?.withRenderingMode(.alwaysOriginal)
            let imageRenderer = UIGraphicsImageRenderer(size: CGSize(width: 120, height: 120))
            
            return imageRenderer.image { _ in
                symbolImage?.draw(in: CGRect(x: 0, y: 0, width: 120, height: 120))
            }
        }())
        .resizable()
        .scaledToFill()
        .frame(width: 120, height: 120)
        .clipShape(Circle())
        .onTapGesture {
            isProfileImagePickerPresented.toggle()
        }
        .id(appStorageHelper.selectedImage)
        .sheet(isPresented: $isProfileImagePickerPresented) {
            ProfileImagePicker(selectedImage: $appStorageHelper.selectedImage, isImagePickerPresented: $isProfileImagePickerPresented) { image in
                withAnimation {
                    selectedImage = image
                }
            }
            .onDisappear {
                // Aktualisieren Sie die Ansicht, wenn das Bild ausgewählt wurde
                //appStorageHelper.selectedImage.map { saveProfileImage($0) }
            }
        }
        .padding()
    }
}

让我知道这是否适合您!

© www.soinside.com 2019 - 2024. All rights reserved.