webentwicklung-frage-antwort-db.com.de

Wie öffne ich den ImagePicker in SwiftUI?

Ich muss den ImagePicker in meiner App mit SwiftUI öffnen. Wie kann ich das tun?

Ich habe über die Verwendung des UIImagePickerController nachgedacht, weiß aber nicht, wie das in SwiftUI geht.

23
Shahar

Ich habe eine Version implementiert, die meiner Meinung nach allgemeiner und erweiterbarer ist. Ich habe ein Subject anstelle eines Binding verwendet, um das Problem zu lösen, bei dem es nicht rückgängig gemacht/unangemessen ist, Ihrer Ansicht eine weitere Bindung hinzuzufügen.

Sie haben beispielsweise ein List erstellt, das eine Reihe von Bildern zeigt, die im zugrunde liegenden Speicher gespeichert sind, und Sie wollten mit der Bildauswahl ein Bild hinzufügen. In diesem Fall ist es sehr schwierig/hässlich, dies zu haben Bild zu Ihrem zugrunde liegenden Speicher hinzugefügt.

Ich habe also ein Motiv verwendet, um das Bild zu übertragen, und Sie können es einfach beobachten und die neuen Bilder einem Speicher hinzufügen. Wenn Sie möchten, dass es sich wie eine Bindung verhält, ist es auch eine Codezeile. (Ändern Sie Ihren Zustand in Ihrer Beobachtung)

Dann habe ich die Einstellungen in ein ViewModel verpackt, damit es nicht unübersichtlich wird, wenn Sie mehr Themen oder Konfigurationen haben möchten.

import SwiftUI
import Combine

struct ImagePickerView : UIViewControllerRepresentable {

    @Binding var model: ImagePickerViewModel

    typealias UIViewControllerType = UIImagePickerController

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

    func makeUIViewController(context: UIViewControllerRepresentableContext<Self>) -> UIImagePickerController {

        let controller = UIImagePickerController()
        controller.delegate = context.coordinator
        controller.allowsEditing = false
        controller.mediaTypes = ["public.image"]
        controller.sourceType = .photoLibrary
        return controller

    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePickerView>) {
        // run right after making

    }

    class Coordinator : NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

        var parentView: ImagePickerView

        init(_ parentView: ImagePickerView) {
            self.parentView = parentView
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parentView.model.isPresented = false
        }

        func imagePickerController(_ picker: UIImagePickerController,
                                          didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {

            guard let uiImage = info[.originalImage] as? UIImage else { return }

            let image = Image(uiImage: uiImage)
            parentView.model.pickedImagesSubject?.send([image])
            parentView.model.isPresented = false

        }

    }

}

struct ImagePickerViewModel {
    var isPresented: Bool = false
    let pickedImagesSubject: PassthroughSubject<[Image], Never>! = PassthroughSubject<[Image], Never>()
}

Verwendung:

struct SomeView : View {

    @EnvironmentObject var storage: Storage
    @State var imagePickerViewModel = ImagePickerViewModel()

    var body: some View {
        Button(action: { self.imagePickerViewModel.isPresented.toggle() }) { ... }
            .sheet(isPresented: $imagePickerViewModel.isPresented) {
                ImagePickerView(model: self.$imagePickerViewModel)
            }
            .onReceive(imagePickerViewModel.pickedImagesSubject) { (images: [Image]) -> Void in
                withAnimation {
                    // modify your storage here
                    self.storage.images += images
                }
            }
    }
}
0
cayZ

Ich habe es so implementiert:

    import SwiftUI

    final class ImagePickerCoordinator: NSObject {

        @Binding var image: UIImage?
        @Binding var takePhoto: Bool

        init(image: Binding<UIImage?>, takePhoto: Binding<Bool>) {
            _image = image
            _takePhoto = takePhoto
        }
    }

    struct ShowImagePicker: UIViewControllerRepresentable {

        @Binding var image: UIImage?
        @Binding var takePhoto: Bool

        func makeCoordinator() -> ImagePickerCoordinator {
            ImagePickerCoordinator(image: $image, takePhoto: $takePhoto)
        }

        func makeUIViewController(context: Context) -> UIImagePickerController {

            let pickerController = UIImagePickerController()
            pickerController.delegate = context.coordinator

            guard UIImagePickerController.isSourceTypeAvailable(.camera) else { return pickerController }

            switch self.takePhoto {
            case true:
                pickerController.sourceType = .camera
            case false:
                pickerController.sourceType = .photoLibrary
            }

            pickerController.allowsEditing = true
            return pickerController
        }

        func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
    }

    extension ImagePickerCoordinator: UINavigationControllerDelegate, UIImagePickerControllerDelegate {

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

            guard let uiImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }

            self.image = uiImage
            picker.dismiss(animated: true, completion: nil)
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            picker.dismiss(animated: true, completion: nil)
        }

}

Fügen Sie Ihrer Ansicht die Logik von nur zwei Schaltflächen hinzu, die ausreicht ...))

0
Dim Novo

Ich bin sehr neu bei Swift, aber ich konnte es mit den folgenden bekommen.

Dadurch wird ein Bildauswahlmodal geladen und Sie können ein Foto auswählen. Anschließend wird eine @State - Variable eines übergeordneten Elements aktualisiert.

Wenn dies für Sie funktioniert, können Sie @State Durch etwas ersetzen, das sich über mehrere Komponenten erstrecken kann, z. B. @EnvironmentObject, Damit auch andere Komponenten aktualisiert werden können.

Hoffe das hilft!

// ImagePicker.Swift

struct ImagePicker : View {   
    @State var image: UIImage? = nil

    var body: some View {
        ImagePickerViewController(image: $image)
    }
}
// ImagePickerViewController.Swift

import UIKit
import AVFoundation
import SwiftUI


struct ImagePickerViewController: UIViewControllerRepresentable {
    @Binding var image: UIImage?

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

    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePickerViewController>) -> UIImagePickerController {
        let imagePicker = UIImagePickerController()
        imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
        imagePicker.allowsEditing = false
        imagePicker.delegate = context.coordinator
        return imagePicker
    }

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

    class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate, AVCapturePhotoCaptureDelegate {

        var parent: ImagePickerViewController

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

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            let imagePicked = info[.originalImage] as! UIImage            
            parent.image = imagePicked
            picker.dismiss(animated: true, completion: nil)
        }
    }
}

Verwendung:

// SampleView.Swift

struct SampleView : View {
    var body: some View {
        PresentationLink(destination: ImagePicker().environmentObject(self.userData), label: {
           Text("Import Photo")
       })
    }
}

Ich bin wieder einmal frisch in Swift). Wenn also jemand Kommentare hat, lass es mich wissen! Freut mich, mehr zu erfahren.

0
jkusachi