如何在App Intent中配置参数实现从照片库选取照片?
解决方法
要让你的Intent参数支持从照片库选择Live Photo,有两种可行方案,根据你的需求选择:
方案一:改用系统内置的照片类型参数
如果不需要严格使用IntentFile类型,直接将参数类型改为[INPhotoMediaItem],系统会自动提供照片库选择的入口,无需额外处理:
@Parameter(title: "Images") var images: [INPhotoMediaItem]?
INPhotoMediaItem是苹果内置的支持照片/Live Photo选择的类型,用户在配置快捷指令时,会看到「照片库」的选择选项,系统会自动匹配你需要的Live Photo类型。
方案二:保留IntentFile类型,自定义照片选择流程
如果必须使用IntentFile作为参数类型,需要手动实现照片库选择并将Live Photo转换为IntentFile:
步骤1:添加照片权限
在你的Info.plist中添加照片访问权限描述:
<key>NSPhotoLibraryUsageDescription</key> <string>需要访问照片库以选择Live Photo</string>
步骤2:实现参数解析与照片选择
在你的Intent处理类中,实现resolveImages(for:with:)方法,触发照片选择器并处理结果:
import Intents import PhotosUI import Photos class YourIntentHandler: NSObject, YourCustomIntentHandling { private var resolveCompletion: (([IntentFile]?, Error?) -> Void)? func resolveImages(for intent: YourCustomIntent, with completion: @escaping ([IntentFile]?, Error?) -> Void) { resolveCompletion = completion // 请求照片库权限 PHPhotoLibrary.requestAuthorization { status in guard status == .authorized else { completion(nil, NSError(domain: "YourAppDomain", code: 1001, userInfo: [NSLocalizedDescriptionKey: "需要授予照片库访问权限才能选择Live Photo"])) return } // 配置PHPicker,仅允许选择Live Photo var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared()) config.filter = .livePhotos config.selectionLimit = 0 // 允许多选 let picker = PHPickerViewController(configuration: config) picker.delegate = self // 在主线程弹出选择器(适配Extension环境) DispatchQueue.main.async { if let rootVC = UIApplication.shared.keyWindow?.rootViewController { rootVC.present(picker, animated: true) } else { completion(nil, NSError(domain: "YourAppDomain", code: 1002, userInfo: [NSLocalizedDescriptionKey: "无法弹出照片选择器"])) } } } } } // 实现PHPicker代理,处理选中的Live Photo extension YourIntentHandler: PHPickerViewControllerDelegate { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) var intentFiles = [IntentFile]() let totalResults = results.count var completedCount = 0 for result in results { guard result.itemProvider.canLoadObject(ofClass: PHLivePhoto.self) else { completedCount += 1 checkCompletion(completedCount: completedCount, total: totalResults, files: intentFiles) continue } result.itemProvider.loadObject(ofClass: PHLivePhoto.self) { [weak self] livePhoto, error in guard let self = self, let livePhoto = livePhoto as? PHLivePhoto else { completedCount += 1 self?.checkCompletion(completedCount: completedCount, total: totalResults, files: intentFiles) return } // 将Live Photo导出到临时目录 let tempDir = FileManager.default.temporaryDirectory let fileURL = tempDir.appendingPathComponent("\(UUID().uuidString).mov") // 导出Live Photo的视频资源(对应com.apple.live-photo类型) let resources = PHAssetResource.assetResources(for: livePhoto) for resource in resources { if resource.type == .pairedVideo { let options = PHAssetResourceRequestOptions() PHAssetResourceManager.default().writeData(for: resource, toFile: fileURL, options: options) { error in if error == nil { let intentFile = IntentFile(fileURL: fileURL, typeIdentifier: "com.apple.live-photo") intentFiles.append(intentFile) } completedCount += 1 self.checkCompletion(completedCount: completedCount, total: totalResults, files: intentFiles) } break } } } } } private func checkCompletion(completedCount: Int, total: Int, files: [IntentFile]) { guard completedCount == total else { return } resolveCompletion?(files, nil) resolveCompletion = nil } }
步骤3:在Intent Definition中配置输入选项
打开你的.intentdefinition文件,选中Images参数,在右侧检查器的「Input Options」中添加「Photo Library」选项,确保系统在参数选择界面显示该入口。
内容的提问来源于stack exchange,提问作者Owen Zhao
相关产品推荐
相关产品推荐

