PhotoKit实现照片随机排序的方法探讨
关于照片库随机排序的问题解答
能否通过NSSortDescriptor实现随机排序?
不行。原因是NSSortDescriptor依赖确定、可重复的比较逻辑——不管是基于属性键值排序,还是自定义比较器,每次对两个元素的比较结果必须是固定的(比如A始终大于B)。而你写的arr.sorted { Bool.random() }这种逻辑是完全不稳定的,每次比较结果随机,Photos框架(或Core Data)在处理查询时不会接受这种排序规则,因为底层需要保证查询结果的一致性和可预测性,所以没法用NSSortDescriptor直接实现随机排序。
无需获取全部照片的随机获取方法
如果不想加载全部照片再排序,有两种实用方案:
1. 先取总数,随机索引直接获取
- 先用
PHAsset.fetchAssets(with: options)获取包含目标照片的PHFetchResult(即使不设fetchLimit,PHFetchResult也不会立即加载所有照片对象,只是记录总数) - 通过
result.count拿到照片总数,生成随机索引:let randomIndex = Int.random(in: 0..<result.count) - 用
result.object(at: randomIndex)直接获取对应位置的照片对象 - 如果需要多张不重复的随机照片,生成多个不重复的随机索引即可,全程不需要把所有照片加载到内存
2. 用fetchLimit + fetchOffset批量随机获取
- 先拿到照片总数,确定要获取的照片数量
limit - 生成随机偏移量:
let randomOffset = Int.random(in: 0...(totalCount - limit))(需保证totalCount >= limit) - 创建
PHFetchOptions,设置fetchLimit = limit和fetchOffset = randomOffset - 执行fetch就能拿到一批随机位置的照片
- 注意:如果照片库在查询过程中发生增删,可能会出现重复或缺失的情况,但日常场景下足够使用
如果确实需要一个完整的随机排序列表,那只能先把PHFetchResult转成数组,再用arr.sorted { Bool.random() }排序,但这种方式在照片数量大时会占用较多内存,谨慎使用。
内容的提问来源于stack exchange,提问作者Stoic
相关产品推荐
相关产品推荐

