【问题标题】:Image Picker in SwiftUI - how do I know when the user has chosen an image in the hosting UIkit based ViewControllerSwiftUI 中的图像选择器 - 我如何知道用户何时在基于 UIkit 的托管 ViewController 中选择了图像
【发布时间】:2021-03-31 04:39:47
【问题描述】:

当我向现有的基于 UIKit 的项目添加新功能时,我正在尝试使用 SwiftUI 编写任何新视图。

但是我遇到了一个问题,我不确定实现我需要做的最佳实践是什么。

我从现有的 ViewController 创建了一个托管在 UIHostingController 中的 SwiftUI 视图。

Swift UI 视图是必不可少的,而 Image 和 Button 则允许用户从 UIPickerViewController 中选择图像

struct PenPicUploader: View {
    @State private var showingImagePicker = false
    @State var inputImage: UIImage?
    @State var image: Image?

    var body: some View {
        GeometryReader { geometry in
            ZStack {
                if let image = image {
                    image
                        .resizable()
                        .scaledToFit()
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .clipShape(Circle())
                        .overlay(
                            Circle().stroke(Color.white, lineWidth: 2))
                        .shadow(radius: 2)
                } else {
                    Image("person")
                        .resizable()
                        .scaledToFit()
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .clipShape(Circle())
                        .overlay(
                            Circle().stroke(Color.white, lineWidth: 2))
                        .shadow(radius: 2)
                }
                Button(action: {
                    self.showingImagePicker = true
                }) {
                    ZStack {
                        Color("accent4")
                            .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
                            .opacity(0.6)
                            .frame(width: 46, height: 46, alignment: .center)
                            .overlay(
                                Circle().stroke(Color.gray, lineWidth: 1))
                        Image(systemName: "camera.fill")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .background(Color.clear)
                            .foregroundColor(Color("accent1"))
                            .frame(width: 24, height: 24, alignment: .center)
                    }.position(x: getWidth(geometry: geometry)-13, y: getHeight(geometry: geometry)-13)
                }
            }.sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
                ImagePicker(image: self.$inputImage)
            }
        }
    }

    func getWidth(geometry: GeometryProxy) -> CGFloat {
        let frame = geometry.frame(in: .global)
        return frame.size.width
    }

    func getHeight(geometry: GeometryProxy) -> CGFloat {
        let frame = geometry.frame(in: .global)
        return frame.size.height
    }

    func loadImage() {
        guard let inputImage = inputImage else { return }
        image = Image(uiImage: inputImage)
    }
}

这是由 ImagePicker UIViewControllerRepresentable 备份的

import SwiftUI

struct ImagePicker: UIViewControllerRepresentable {
    @Environment(\.presentationMode) var presentationMode
    @Binding var image: UIImage?

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

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {

    }
}

class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate, ObservableObject {
    let parent: ImagePicker

    init(_ parent: ImagePicker) {
        self.parent = parent
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        if let uiImage = info[.originalImage] as? UIImage {
            parent.image = uiImage
        }
        parent.presentationMode.wrappedValue.dismiss()
    }
}

我如何知道用户在 UIKit 视图控制器中选择了图像?我需要代理吗?还是其他一些更 SwiftUI 的方法?

【问题讨论】:

  • 我如何知道... - 你为什么需要它?
  • 我需要将图像保存到由另一个类处理的 API。我可以简单地把它放在 UIViewControllerRepresentable 中吗?

标签: ios swift swiftui


【解决方案1】:

你可以用.onChange(of:)修饰符来做到这一点,比如

    }.sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
        ImagePicker(image: self.$inputImage)
    }
    .onChange(of: image) {
        if let img = $0 {
            // call save here with new image `img`
        }
    }

【讨论】:

    【解决方案2】:

    所以它就像在 UIViewControllerRepresentable 中的选择器调用中调用 Api 调用一样简单

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        if let uiImage = info[.originalImage] as? UIImage {
            parent.image = uiImage
            apiHelper.uploadProfileImage(imageToUpload: uiImage) { (success, _) in
                if success {
                    print("IMAGE UPLOADED")
                } else {
                    print("IMAGE UPLOAD FAILED")
                }
            }
    
        }
        parent.presentationMode.wrappedValue.dismiss()
    }
    

    【讨论】:

      猜你喜欢
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 2023-01-24
      • 2023-01-24
      • 1970-01-01
      相关资源
      最近更新 更多