美文网首页
相册组件 PHPickerViewController

相册组件 PHPickerViewController

作者: 大成小栈 | 来源:发表于2024-08-07 21:35 被阅读0次

    PHPickerViewController

    iOS的相册系统组件UIImagePickerController 目前已经不推荐使用,我们需要逐渐切换到新的组件 PHPickerViewController 上来:

    import UIKit
    import PhotosUI
    
    class ViewController: UIViewController, UINavigationControllerDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
        }
        
        @IBAction func openClick(_ sender: UIButton) {
            var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
            configuration.filter = PHPickerFilter.any(of: [.livePhotos, .videos])
            configuration.selectionLimit = 1
            
            let picker = PHPickerViewController(configuration: configuration)
            picker.delegate = self
            present(picker, animated: true, completion: nil)
        }
    
        func presentVideoEditor(for url: URL) {
            // 调试路径打印
               print("Video URL: \(url.path)")
    
               // 确保视频文件路径存在
               let fileManager = FileManager.default
               if fileManager.fileExists(atPath: url.path) {
                   print("File exists at path: \(url.path)")
               } else {
                   print("File does not exist at path: \(url.path)")
                   return
               }
               
               // 验证视频是否可编辑
               if UIVideoEditorController.canEditVideo(atPath: url.path) {
                   let editor = UIVideoEditorController()
                   editor.videoMaximumDuration = 10
                   editor.videoPath = url.path
                   editor.delegate = self
                   present(editor, animated: true, completion: nil)
               } else {
                   print("This video cannot be edited.")  // 打印调试信息
               }
        }
    
    }
    
    extension ViewController: PHPickerViewControllerDelegate {
        
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            picker.dismiss(animated: true, completion: nil)
            
            guard let provider = results.first?.itemProvider else {
                return
            }
            
            if provider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
                provider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { (url, error) in
                    if let error = error {
                        print("Error loading video file: \(error.localizedDescription)")
                        return
                    }
                    
                    guard let tempURL = url else {
                        print("Error: URL is nil")
                        return
                    }
                    
                    // 拷贝临时文件到合适的位置,以防止被删除
                    let destinationURL = FileManager.default.temporaryDirectory.appendingPathComponent(tempURL.lastPathComponent)
                    do {
                        if FileManager.default.fileExists(atPath: destinationURL.path) {
                            try FileManager.default.removeItem(at: destinationURL)
                        }
                        try FileManager.default.copyItem(at: tempURL, to: destinationURL)
                        print("Video copied to \(destinationURL)")
                        
                        // 使用系统的视频编辑器
                        DispatchQueue.main.async {
                            self.presentVideoEditor(for: destinationURL)
                        }
                    } catch {
                        print("Error copying video file: \(error.localizedDescription)")
                    }
                }
            } else {
                print("load file fail!")
            }
        }
    }
    
    
    extension ViewController: UIVideoEditorControllerDelegate {
        func videoEditorController(_ editor: UIVideoEditorController, didSaveEditedVideoToPath editedVideoPath: String) {
            editor.dismiss(animated: true, completion: nil)
            print("Edited video saved at: \(editedVideoPath)")
        }
    
        func videoEditorController(_ editor: UIVideoEditorController, didFailWithError error: Error) {
            editor.dismiss(animated: true, completion: nil)
            print("Video editing failed with error: \(error.localizedDescription)")
        }
    
        func videoEditorControllerDidCancel(_ editor: UIVideoEditorController) {
            editor.dismiss(animated: true, completion: nil)
            print("Video editing canceled.")
        }
    }
    

    PHContentEditingController

    https://developer.apple.com/documentation/photokit/phcontenteditingcontroller?language=objc_2
    https://blog.51cto.com/u_13360/7840126

    PHContentEditingController 是 iOS 中用于扩展相册(Photos)应用的接口,允许开发者提供自定义的内容编辑扩展。通过实现这个协议,可以将自己的编辑工具集成到 iOS 相册中,用于编辑照片或视频。

    核心概念
    扩展点 (Extension Point): PHContentEditingController 被设计为用于 iOS 相册应用的扩展点,允许第三方应用提供自定义的照片或视频编辑功能。
    输入 (Input): 相册中的照片或视频作为输入内容传递给 PHContentEditingController。
    输出 (Output): 编辑后的内容将以新的形式保存,供用户使用。
    实现步骤
    创建内容编辑扩展 (Content Editing Extension):
    在 Xcode 中创建一个新的目标(Target),选择 "Photo Editing Extension"。这会生成一个包含 PHContentEditingController 协议的模板文件。

    实现 PHContentEditingController 方法:
    你需要实现以下几个核心方法:

    canHandle(_:):判断扩展是否能处理给定的输入内容类型。
    startContentEditing(with:placeholderImage:):在用户选择内容后,准备编辑界面。
    finishContentEditing(completionHandler:):用户完成编辑后,处理并返回编辑结果。
    cancelContentEditing():用户取消编辑时,撤销所有操作。
    shouldShowCancelConfirmation():返回一个布尔值,决定是否显示取消编辑的确认提示。
    示例代码:
    下面是一个基本的实现示例:

    import Photos
    import UIKit
    
    class PhotoEditingViewController: UIViewController, PHContentEditingController {
        
        var input: PHContentEditingInput?
        var isEditingVideo = false
        
        func canHandle(_ adjustmentData: PHAdjustmentData?) -> Bool {
            // 检查是否可以处理这个调整数据
            return true
        }
        
        func startContentEditing(with contentEditingInput: PHContentEditingInput, placeholderImage: UIImage) {
            // 保存输入内容
            self.input = contentEditingInput
            
            // 检查输入内容是否是视频
            if let videoURL = contentEditingInput.audiovisualAsset?.url {
                isEditingVideo = true
                // 在这里加载并显示视频
            } else {
                isEditingVideo = false
                // 在这里加载并显示图片
            }
        }
        
        func finishContentEditing(completionHandler: @escaping ((PHContentEditingOutput?) -> Void)) {
            guard let input = input else {
                completionHandler(nil)
                return
            }
            
            // 创建编辑输出对象
            let output = PHContentEditingOutput(contentEditingInput: input)
            
            if isEditingVideo {
                // 视频处理逻辑
                // 保存修改后的视频到 output.renderedContentURL
            } else {
                // 图片处理逻辑
                // 保存修改后的图片到 output.renderedContentURL
            }
            
            // 生成调整数据
            let adjustmentData = PHAdjustmentData(formatIdentifier: "com.yourcompany.appname", formatVersion: "1.0", data: Data())
            output.adjustmentData = adjustmentData
            
            // 调用回调并传递输出结果
            completionHandler(output)
        }
        
        func cancelContentEditing() {
            // 处理用户取消编辑的情况
        }
        
        func shouldShowCancelConfirmation() -> Bool {
            // 返回是否应该显示取消确认提示
            return true
        }
    }
    

    关键点说明:
    PHContentEditingInput 和 PHContentEditingOutput: 这两个类用于在编辑过程中处理输入和输出内容。
    PHAdjustmentData: 用于保存编辑操作的元数据,以便将来恢复或重新应用这些操作。
    注意事项
    这个扩展是直接与系统相册集成的,用户可以在相册应用中使用你的自定义编辑器。
    确保正确处理用户的操作,无论是保存编辑结果还是取消编辑,都要提供流畅的用户体验。
    如果你需要进一步了解或实现具体功能,随时告诉我!

    相关文章

      网友评论

          本文标题:相册组件 PHPickerViewController

          本文链接:https://www.haomeiwen.com/subject/bmrckjtx.html