You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:13:25