HXPHPicker

repository·main·Indexed 18 days ago

https://github.com/silencelove/hxphpicker

A comprehensive photo and video selector for iOS and iPadOS. HXPHPicker supports multiple media types including Photos, GIFs, Live Photos, and Videos, and features iCloud asset downloading and built-in photo/video editing capabilities. It is available in several modular versions (Full, Lite, Picker, Editor, and Camera) to optimize binary size, with support for iOS 12.0+ (or iOS 10.0+ via HXPHPicker-Lite).

Tokens
14.8K
Snippets
50
Records
55
Agent score
62%

What's inside HXPHPicker

  1. Overview of HXPHPicker

    main
    HXPHPicker is a Swift-based toolkit designed for selecting, editing, and displaying images. It provides a comprehensive suite of tools for handling image-related workflows in iOS applications, including a picker for selecting media, an editor for modifications, and components for displaying images.
  2. Handle iCloud Synchronization behavior

    main

    The allowSyncICloudWhenSelectPhoto setting determines how the picker handles assets stored in iCloud:

    • If true: The picker will attempt to sync iCloud resources before selection. If the network is down or iCloud fails, the selection will fail.
    • If false: The picker will not attempt sync. If the resource is only in iCloud, fetching the original image will fail.
  3. Manage local camera assets across sessions

    main

    The picker supports persisting locally captured camera assets. When the picker is dismissed, the pickerController(_:didDismissComplete:) method provides an array of [PhotoAsset] representing local camera data. You can store these and re-inject them into the next picker instance by setting the localCameraAssetArray property on the PhotoPickerController.

    // 1. Capture local assets on dismiss
    func pickerController(_ pickerController: PhotoPickerController, 
                          didDismissComplete localCameraAssetArray: [PhotoAsset]) {
        self.savedLocalAssets = localCameraAssetArray
    }
    
    // 2. Re-inject assets on next launch
    let config = PickerConfiguration()
    let pickerController = PhotoPickerController(picker: config, delegate: self) 
    pickerController.localCameraAssetArray = self.savedLocalAssets
    present(pickerController, animated: true, completion: nil)
  4. Configure Info.plist permissions

    main

    To use the Picker, Camera, or Library features, you must add the following keys to your Info.plist file depending on the module you are using:

    | Key | Module | Info |
    | ----- | ----  | ---- |
    | NSPhotoLibraryUsageDescription | Picker | Allow access to album |
    | NSPhotoLibraryAddUsageDescription | Picker | Allow to save pictures to album |
    | PHPhotoLibraryPreventAutomaticLimitedAccessAlert | Picker | Set YES to prevent automatic limited access alert in iOS 14+ |
    | NSCameraUsageDescription | Camera | Allow camera |
    | NSMicrophoneUsageDescription | Camera | Allow microphone |
  5. Quick Start: Present the Photo Picker

    main

    You can present the photo picker using two different methods.

    Method 1: Using PhotoPickerController directly This method gives you more control via a delegate. You can set the pickerDelegate, pre-select assets using selectedAssetArray, and toggle original image selection with isOriginal.

    Method 2: Using the Photo.picker convenience method This is a closure-based approach that provides a result (containing selected assets and original status) on success and a cancel callback on cancellation.

    import HXPHPicker
    
    class ViewController: UIViewController, PhotoPickerControllerDelegate {
    
        func presentPickerController() {
            let config = PickerConfiguration.default
            
            // Method 1: Direct Controller
            let pickerController = PhotoPickerController(picker: config)
            pickerController.pickerDelegate = self
            pickerController.selectedAssetArray = selectedAssets 
            pickerController.isOriginal = isOriginal
            present(pickerController, animated: true, completion: nil)
            
            // Method 2: Convenience Method
            Photo.picker(config) { result, pickerController in
                // result.photoAssets: Currently selected data
                // result.isOriginal: Whether the original image is selected
            } cancel: { pickerController in
                // Cancelled callback
            }
        }
    
        // Delegate methods
        func pickerController(_ pickerController: PhotoPickerController, didFinishSelection result: PickerResult) {
            result.getImage { (image, photoAsset, index) in
                if let image = image { print("success", image) }
            } completionHandler: { (images) in
                print(images)
            }
        }
    
        func pickerController(didCancel pickerController: PhotoPickerController) {
            // Handle cancel
        }
    }
  6. Use the Photo Picker via PhotoPickerControllerDelegate

    main

    For more control, you can initialize a PhotoPickerController and conform to the PhotoPickerControllerDelegate.

    Important Note on Dismissal: By default, the controller dismisses itself automatically upon completion or cancellation. If you need to manage the dismissal manually, set the autoDismiss property of the picker to false.

    To retrieve the actual images from the PickerResult, use the getImage method which provides both an individual asset callback and a final completion handler.

    // 1. Initialize and present
    let config = PickerConfiguration()
    let pickerController = PhotoPickerController(picker: config)
    pickerController.pickerDelegate = self
    present(pickerController, animated: true, completion: nil)
    
    // 2. Implement Delegate methods
    func pickerController(_ pickerController: PhotoPickerController, 
                            didFinishSelection result: PickerResult) {
        // Retrieve images from assets
        result.getImage { (image, photoAsset, index) in
            if let image = image { 
                print("success", image)
            } else {
                print("failed")
            }
        } completionHandler: { (images) in
            // All images have been processed
        }
    }
    
    func pickerController(didCancel pickerController: PhotoPickerController) {
        // Handle cancellation
    }
  7. Initialize the Video Editor

    main

    To use the video editor, first initialize a VideoEditorConfiguration object. You can then instantiate an EditorController using one of the following methods: a local URL, an AVAsset, or a network URL.

    // Initialize configuration first
    let config = VideoEditorConfiguration()
    
    // Option 1: Initialize from a local video URL
    let controller = EditorController(videoURL: videoURL, config: config, delegate: self)
    
    // Option 2: Initialize from an AVAsset
    let controller = EditorController(avAsset: avAsset, config: config, delegate: self)
    
    // Option 3: Initialize from a network video URL
    let controller = EditorController(networkVideoURL: url, config: config, delegate: self)
    
    present(controller, animated: true)
  8. Preview assets using PhotoPickerController

    main

    To show a preview of selected assets using a controller, use PhotoPickerController with a configuration object.

    1. Get a configuration using PhotoTools.getWXPickerConfig().
    2. Initialize PhotoPickerController with the config, a starting index, and a delegate.
    3. Assign the array of assets to selectedAssetArray.
    4. Present the controller.
    let previewConfig = PhotoTools.getWXPickerConfig() 
    let previewController = PhotoPickerController(preview: previewConfig, 
                                                  currentIndex: 0, 
                                                  delegate: self)
    previewController.selectedAssetArray = selectedAssets
    present(previewController, animated: true, completion: nil)
  9. Preview assets using PhotoBrowser

    main

    For a more interactive preview (including deletion and long-press support), use PhotoBrowser.show.

    Key parameters:

    • selectedAssets: The array of assets to preview.
    • pageIndex: The starting position.
    • config: A PhotoBrowser.Configuration object to control UI behavior (e.g., showDelete).
    • transitionalImage: An initial UIImage for the transition animation.
    • deleteAssetHandler: A callback triggered when the delete button is pressed. Use photoBrowser.deleteCurrentPreviewPhotoAsset() inside this handler to perform the deletion.
    • longPressHandler: A callback for long-press events on assets.
    let config = PhotoBrowser.Configuration()
    config.showDelete = true
    
    PhotoBrowser.show(
        selectedAssets,
        pageIndex: indexPath.item,
        config: config,
        transitionalImage: cell?.imageView.image
    ) {
        index in
        // Transition handler
    } deleteAssetHandler: { index, photoAsset, photoBrowser in
        // Handle deletion
        photoBrowser.deleteCurrentPreviewPhotoAsset()
    } longPressHandler: { index, photoAsset, photoBrowser in
        // Handle long press
    }
  10. Install Kingfisher via SPM, CocoaPods, or Carthage

    main

    You can integrate Kingfisher into your project using several dependency managers:

    Swift Package Manager

    1. Go to File > Swift Packages > Add Package Dependency.
    2. Add the URL: https://github.com/onevcat/Kingfisher.git.
    3. Select Up to Next Major version starting from 7.0.0.

    CocoaPods

    Add the following to your Podfile:

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '12.0'
    use_frameworks!
    
    target 'MyApp' do
      pod 'Kingfisher', '~> 7.0'
    end

    Carthage

    Add the following to your Cartfile:

    github "onevcat/Kingfisher" ~> 7.0
    pod 'Kingfisher', '~> 7.0'