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

Swift中PHAsset数组转URL数组:如何等待异步任务完成后返回结果

解决PHAsset数组转URL数组的异步等待问题

核心问题在于PHAsset的URL获取是异步操作(比如调用requestContentEditingInput或requestAVAsset这类方法),如果直接在循环里执行这些异步逻辑,函数会在所有异步任务完成前就返回空数组,这就是你不确定结果是否始终正确的原因。下面提供两种可靠的实现方式,确保所有URL获取完成后再返回结果:

方案1:使用Async/Await(iOS 15+,推荐)

从iOS15开始,Photos框架原生支持异步/等待API,代码更简洁且不会阻塞主线程。你可以把getUrlsFromPHAssets改成异步函数:

import Photos

func getUrlsFromPHAssets(_ assets: [PHAsset]) async throws -> [URL] {
    var urls = [URL]()
    
    for asset in assets {
        // 异步等待每个Asset的编辑输入
        let input = try await asset.requestContentEditingInput(with: nil)
        // 根据Asset类型取对应的URL
        if let url = input.fullSizeImageURL ?? input.fullSizeVideoURL {
            urls.append(url)
        }
    }
    
    return urls
}

主线程调用方式:

因为是异步函数,你需要用await等待结果,记得包裹在Task中避免阻塞主线程:

Task {
    do {
        let targetAssets: [PHAsset] = // 你的PHAsset数组
        let fetchedUrls = try await getUrlsFromPHAssets(targetAssets)
        // 这里处理获取完成的URL数组
        print("所有URL已获取:\(fetchedUrls)")
    } catch {
        print("URL获取失败:\(error.localizedDescription)")
    }
}

方案2:使用DispatchGroup(兼容iOS <15)

如果需要支持iOS15以下版本,可以用DispatchGroup跟踪所有异步任务的完成状态。注意绝对不要在主线程直接调用group.wait(),否则会阻塞UI,建议结合后台线程使用:

import Photos

func getUrlsFromPHAssets(_ assets: [PHAsset], completion: @escaping ([URL]) -> Void) {
    var urls = [URL]()
    let group = DispatchGroup()
    
    for asset in assets {
        group.enter()
        asset.requestContentEditingInput(with: nil) { input, _ in
            defer { group.leave() } // 确保任务结束后标记完成
            guard let input = input else { return }
            if let url = input.fullSizeImageURL ?? input.fullSizeVideoURL {
                urls.append(url)
            }
        }
    }
    
    // 所有任务完成后回调结果
    group.notify(queue: .main) {
        completion(urls)
    }
}

主线程调用方式:

let targetAssets: [PHAsset] = // 你的PHAsset数组
getUrlsFromPHAssets(targetAssets) { fetchedUrls in
    // 这里处理获取完成的URL数组
    print("所有URL已获取:\(fetchedUrls)")
}

为什么你的当前结果看似正常?

大概率是测试时的PHAsset数量少、设备性能较好,异步任务刚好在函数返回前侥幸完成了。但这种情况是不可靠的——当资产数量多、设备负载高时,异步任务还没执行完函数就返回了,结果必然会缺失URL。上面的两种方案都能确保所有异步任务完成后再返回/回调结果,不会出现随机错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:25:30