Skip to content

Instantly share code, notes, and snippets.

@mdb1
Created January 30, 2024 22:54
Show Gist options
  • Select an option

  • Save mdb1/e7eb3b43942a8087a1c22ff1c59da733 to your computer and use it in GitHub Desktop.

Select an option

Save mdb1/e7eb3b43942a8087a1c22ff1c59da733 to your computer and use it in GitHub Desktop.

Revisions

  1. mdb1 created this gist Jan 30, 2024.
    91 changes: 91 additions & 0 deletions ImageSelectorOptionsModifier.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,91 @@
    import Foundation
    import SwiftUI

    struct ImageSelectorOptionsModifier: ViewModifier {
    var title: String
    var titleVisibility: Visibility
    var galleryOptionTitle: String
    var takePictureOptionTitle: String
    @Binding var isPresentingSourceSelector: Bool
    @Binding var selectedImage: UIImage?

    @State private var isPresentingImagePickerOptions: Bool = false
    @State private var sourceSelection: UIImagePickerController.SourceType?

    func body(content: Content) -> some View {
    content
    .confirmationDialog(
    title,
    isPresented: $isPresentingSourceSelector,
    titleVisibility: titleVisibility
    ) {
    Button(galleryOptionTitle) {
    sourceSelection = .photoLibrary
    isPresentingImagePickerOptions = true
    }
    Button(takePictureOptionTitle) {
    sourceSelection = .camera
    isPresentingImagePickerOptions = true
    }
    #if targetEnvironment(simulator)
    .disabled(true)
    #endif
    }
    .sheet(isPresented: $isPresentingImagePickerOptions) {
    if let source = sourceSelection {
    ImagePicker(sourceType: source, selectedImage: $selectedImage)
    }
    }
    }
    }

    extension View {
    /// A modifier that adds image selection capabilities to a view.
    /// Applying this modifier will let the view present a confirmation dialog with the given properties
    /// to change an image, letting the users select an image from their gallery or with their camera.
    /// - Parameters:
    /// - title: The title of the confirmation dialog.
    /// - titleVisibility: The visibility of the title.
    /// - galleryOptionTitle: The text to display for the Gallery Source Option.
    /// - takePictureOptionTitle: The text to display for the Camera Source Option.
    /// - isPresentingSourceSelector: The binding to present the dialog.
    /// - selectedImage: A binding to represent the image selected by the user.
    /// - Usage:
    /// To use this modifier, you need two @State properties in the View:
    /// ```swift
    /// @State private var isPresentingImagePickerOptions = false
    /// @State private var selectedImage: UIImage?
    /// ```
    /// - Then: Just add the modifier using those properties:
    /// ```swift
    /// Button("Present Picker") {
    /// isPresentingImagePickerOptions = true
    /// }
    /// .imageSelectorOptions(
    /// title: "Select Source",
    /// titleVisibility: .visible,
    /// isPresentingSourceSelector: $isPresentingImagePickerOptions,
    /// selectedImage: $selectedImage
    /// )
    /// ```
    /// - Returns: The original view with the applied modifier.
    func imageSelectorOptions(
    title: String = "",
    titleVisibility: Visibility = .automatic,
    galleryOptionTitle: String = "Choose from gallery",
    takePictureOptionTitle: String = "Take Picture",
    isPresentingSourceSelector: Binding<Bool>,
    selectedImage: Binding<UIImage?>
    ) -> some View {
    self.modifier(
    ImageSelectorOptionsModifier(
    title: title,
    titleVisibility: titleVisibility,
    galleryOptionTitle: galleryOptionTitle,
    takePictureOptionTitle: takePictureOptionTitle,
    isPresentingSourceSelector: isPresentingSourceSelector,
    selectedImage: selectedImage
    )
    )
    }
    }