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

如何通过自定义Transferable类型从PhotosPickerItem加载LivePhoto

问题分析与解决

问题原因

你自定义的LivephotoTrasferable仅实现了FileRepresentation,该表示仅适配文件拖拽场景;而PhotosPickerItem提供LivePhoto时,系统默认通过内置逻辑将其转换为PHLivePhoto实例,而非直接暴露文件URL,因此无法匹配到你的FileRepresentation导入逻辑,导致加载失败。

解决方案

给LivephotoTrasferable添加ItemProviderRepresentation,利用系统NSItemProvider能力直接加载LivePhoto对应的文件URL,同时保留原有的FileRepresentation用于拖拽场景,实现统一管理导入、导出及拖拽逻辑的需求。

修改后的完整代码

struct ContentView: View {
    @State private var selection: PhotosPickerItem?
    
    var body: some View {
        VStack {
            PhotosPicker(selection: $selection) {
                Text("Import image")
            }
            .buttonStyle(.borderedProminent)
            .onChange(of: selection) { oldValue, newValue in
                if let item = newValue {
                    loadTransferable(item)
                    selection = nil
                }
            }
        }
        .padding()
    }
    
    func loadTransferable(_ item: PhotosPickerItem) {
        Task {
            let livephoto = try? await item.loadTransferable(type: PHLivePhoto.self)
            let livephoto2 = try? await item.loadTransferable(type: LivephotoTrasferable.self)
            print(livephoto != nil, livephoto2 != nil) // 现在输出 true, true
        }
    }
}

struct LivephotoTrasferable: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        // 适配PhotosPicker加载:从ItemProvider获取LivePhoto的文件URL
        ItemProviderRepresentation { itemProvider in
            guard itemProvider.hasItemConformingToTypeIdentifier(UTType.livePhoto.identifier) else {
                throw TransferError.unsupportedType
            }
            
            let fileURL = try await itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.livePhoto.identifier) { tempURL, error in
                if let error = error { throw error }
                return tempURL
            }
            
            return Self(url: fileURL)
        }
        
        // 保留原逻辑:处理拖拽场景的文件导入导出
        FileRepresentation(contentType: .livePhoto) { item in
            SentTransferredFile(item.url)
        } importing: { file in
            print("livephoto!")
            return Self.init(url: file.file)
        }
    }
    
    var url: URL
    
    enum TransferError: Error {
        case unsupportedType
    }
}

补充说明

  • ItemProviderRepresentation直接与系统NSItemProvider交互,能够处理PhotosPickerItem提供的LivePhoto资源,通过loadFileRepresentation获取到LivePhoto对应的包文件URL。
  • 原有的FileRepresentation依然可以处理拖拽场景下的文件逻辑,完全满足你统一管理的需求。
  • 修改后测试,livephoto2将不再为nil,打印结果会变为true, true。

内容的提问来源于stack exchange,提问作者Chocoford

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 07:32:04