上传用户图像并保存默认图像

Uploading user image and saving over default image

所以我正在研究用户将图像上传到各种“个人资料图片”的问题。所以我相信我的图像选择器工作正常。问题是它上传了,但最初仍然显示默认图像。

我知道这一点,因为如果我去上传另一张图片,默认图片会在短时间内消失,然后可以看到新上传的图片。我的按钮触发了显示新图像的 showingImagePicker 布尔值,应该 隐藏默认图像,我不明白为什么默认图像仍会显示。

struct RecipeEditorImage: View {
    @State private var showingImagePicker = false
    @State private var inputImage: UIImage?
    @State private var image: Image?
   
    
    var body: some View {
        ZStack (alignment: .trailing){
            if showingImagePicker{
               image?
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width:200, height: 100)
            }
            else{
                Image("ExampleRecipePicture")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width:200, height: 100)
            
            }
                
                Image(systemName:("plus.circle.fill")).renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .offset(x: 20)
                    .foregroundColor(Color("completeGreen"))
                    .frame(width:50, height:10)
            
                    .onTapGesture {
                        showingImagePicker = true
                    }
            
                    .sheet(isPresented: $showingImagePicker){
                        EditorImagePicker(image: $inputImage)
                    }
                    .onChange(of: inputImage){ _ in loadImage() }
            }
        }
    
    func loadImage(){
        guard let inputImage = inputImage else { return }
        image = Image(uiImage: inputImage)
    }
}
    

import PhotosUI
import SwiftUI


struct EditorImagePicker: UIViewControllerRepresentable{
    @Binding var image: UIImage?
    
    class Coordinator: NSObject, PHPickerViewControllerDelegate{
        var parent: EditorImagePicker
        
        init(_ parent: EditorImagePicker){
            self.parent = parent
        }
        
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            picker.dismiss(animated: true)
            
            guard let provider = results.first?.itemProvider else { return }
            
            if provider.canLoadObject(ofClass: UIImage.self){
                provider.loadObject(ofClass: UIImage.self){image, _ in
                    self.parent.image = image as? UIImage
                }
            }
        }
        
    }
    
    func makeUIViewController(context: Context) -> PHPickerViewController {
        //configures ios to just be able to select images
        var config = PHPickerConfiguration()
        config.filter = .images
        
        //the view of picker
        let picker = PHPickerViewController(configuration: config)
        picker.delegate = context.coordinator
        return picker
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
        //leave empty for now
    }
}

有几个问题:

  1. 您的第一个 if 子句保证仅当 sheet 也显示时才会显示所选图像。

  2. 您可能希望避免存储对 Image View 的引用的额外步骤——只需动态使用它。这也摆脱了 onChange

  3. 你的loadObject闭包需要回调主线程。

import SwiftUI
import PhotosUI

struct RecipeEditorImage: View {
    @State private var showingImagePicker = false
    @State private var inputImage: UIImage?
    
    var body: some View {
        ZStack (alignment: .trailing){
            if let inputImage = inputImage {
                Image(uiImage: inputImage)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width:200, height: 100)
            } else{
                Image(systemName: "pencil")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width:200, height: 100)
            
            }
                
                Image(systemName:("plus.circle.fill")).renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .offset(x: 20)
                    .foregroundColor(Color("completeGreen"))
                    .frame(width:50, height:10)
                    .contentShape(Rectangle())
                    .onTapGesture {
                        showingImagePicker = true
                    }
            
                    .sheet(isPresented: $showingImagePicker){
                        EditorImagePicker(image: $inputImage)
                    }
            }
        }
    
}
    
struct EditorImagePicker: UIViewControllerRepresentable{
    @Binding var image: UIImage?
    
    class Coordinator: NSObject, PHPickerViewControllerDelegate{
        var parent: EditorImagePicker
        
        init(_ parent: EditorImagePicker){
            self.parent = parent
        }
        
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            picker.dismiss(animated: true)
            
            guard let provider = results.first?.itemProvider else { return }
            
            if provider.canLoadObject(ofClass: UIImage.self){
                provider.loadObject(ofClass: UIImage.self){image, _ in
                    DispatchQueue.main.async {
                        self.parent.image = image as? UIImage
                    }
                }
            }
        }
        
    }
    
    func makeUIViewController(context: Context) -> PHPickerViewController {
        //configures ios to just be able to select images
        var config = PHPickerConfiguration()
        config.filter = .images
        
        //the view of picker
        let picker = PHPickerViewController(configuration: config)
        picker.delegate = context.coordinator
        return picker
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
        //leave empty for now
    }
}