基于creationDate以Swift[更快的方式?]从库中获取所有照片
我有一个基于creationDate以Swift[更快的方式?]从库中获取所有照片,swift,phasset,photosframework,phassetslibrary,Swift,Phasset,Photosframework,Phassetslibrary,我有一个UICollectionView显示基于最新“creationDate”的图书馆照片。为此,我使用以下代码: struct AssetsData { var creationDate: Date, assetResult: PHFetchResult<PHAsset> } func fetchPhotos() -> [AssetsData] { //Date Formatter let formatter = DateFormatter()
UICollectionView
显示基于最新“creationDate”的图书馆照片。为此,我使用以下代码:
struct AssetsData {
var creationDate: Date, assetResult: PHFetchResult<PHAsset>
}
func fetchPhotos() -> [AssetsData] {
//Date Formatter
let formatter = DateFormatter()
formatter.dateStyle = DateFormatter.Style.medium
formatter.timeStyle = DateFormatter.Style.none
//Photos fetch
let fetchOptions = PHFetchOptions()
let sortOrder = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.sortDescriptors = sortOrder
let assetsFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
var arrCreationDate = [Date]()
var arrDates = [String]()
//Getting All dates
for index in 0..<assetsFetchResult.count {
if let creationDate = assetsFetchResult[index].creationDate {
let formattedDate = formatter.string(from: creationDate)
if !arrDates.contains(formattedDate) {
arrDates.append(formattedDate)
arrCreationDate.append(creationDate)
}
}
}
//Fetching Assets based on Dates
var arrPhotoAssetsData = [AssetsData]()
for createdDate in arrCreationDate {
if let startDate = getDate(forDay: createdDate.day, forMonth: createdDate.month, forYear: createdDate.year, forHour: 0, forMinute: 0, forSecond: 0), let endDate = getDate(forDay: createdDate.day, forMonth: createdDate.month, forYear: createdDate.year, forHour: 23, forMinute: 59, forSecond: 59) {
fetchOptions.predicate = NSPredicate(format: "creationDate > %@ AND creationDate < %@", startDate as NSDate, endDate as NSDate)
let assetsPhotoFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
arrPhotoAssetsData.append(AssetsData(creationDate: createdDate, assetResult: assetsPhotoFetchResult))
}
}
return arrPhotoAssetsData
}
func getDate(forDay day: Int, forMonth month: Int, forYear year: Int, forHour hour: Int, forMinute minute: Int, forSecond second: Int) -> Date? {
var dateComponents = DateComponents()
dateComponents.day = day
dateComponents.month = month
dateComponents.year = year
dateComponents.hour = hour
dateComponents.minute = minute
dateComponents.second = second
var gregorian = Calendar(identifier: Calendar.Identifier.gregorian)
gregorian.timeZone = NSTimeZone.system
return gregorian.date(from: dateComponents)
}
struct AssetsData{
var creationDate:日期,assetResult:PHFetchResult
}
func fetchPhotos()->[AssetsData]{
//日期格式化程序
let formatter=DateFormatter()
formatter.dateStyle=DateFormatter.Style.medium
formatter.timeStyle=DateFormatter.Style.none
//照片获取
让fetchOptions=PHFetchOptions()
let sortOrder=[NSSortDescriptor(键:“creationDate”,升序:false)]
fetchOptions.sortDescriptors=sortOrder
让AssetFetchResult=PHAsset.fetchAssets(带:。图像,选项:fetchOptions)
var arrcreaiondate=[日期]()
var arrDates=[String]()
//获取所有日期
对于0..Date中的索引{
var dateComponents=dateComponents()
dateComponents.day=天
dateComponents.month=月份
dateComponents.year=年
dateComponents.hour=小时
dateComponents.minute=分钟
dateComponents.second=秒
var gregorian=日历(标识符:Calendar.identifier.gregorian)
gregorian.timeZone=NSTimeZone.system
返回公历日期(起始日期:dateComponents)
}
代码运行得很好!但问题是加载10k+照片几乎需要7-9秒。直到6k照片都没有问题,但我真的需要一些有效的方法,以便我可以加载
UICollectionView
中的一些资产
,其余的我可以稍后添加。我需要的是,无论照片数量多少,都不应该占用更多超过2-3秒。有人能帮忙吗?假设您有8k张照片。因此,您迭代两个“for”循环,以获取arrCreationDate和arrPhotoAssets数据(这是所需工作量的两倍)
相反,您可以尝试通过一个循环来完成。下面是一个粗略的方法:-
let assetsFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
let fetchOptions = PHFetchOptions()
var arrCreationDate = [Date]()
var arrPhotoAssetsData = [AssetsData]()
var arrDates = [String]()
for index in 0..<assetsFetchResult.count {
if let creationDate = assetsFetchResult[index].creationDate {
let formattedDate = formatter.string(from: creationDate)
if !arrDates.contains(formattedDate) {
//You can convert the formattedDate to actual date here and do a check similar to this, do what you do in the other loop here too
if(actualDate < actualDateOfTheFirstElementAtArray){
arrCreationDate.insert(actualDate, at: 0)
fetchOptions.predicate = NSPredicate(format: "creationDate > %@ AND creationDate < %@", startDate as NSDate, endDate as NSDate)
let assetsPhotoFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
arrPhotoAssetsData.insert(AssetsData(creationDate: createdDate, assetResult: assetsPhotoFetchResult), at: 0)
}
}
}
}
让AssetFetchResult=PHAsset.fetchAssets(带:。图像,选项:fetchOptions)
让fetchOptions=PHFetchOptions()
var arrcreaiondate=[日期]()
var arrpotoassetsdata=[AssetsData]()
var arrDates=[String]()
对于0中的索引。谢谢。我尝试了,但仍然需要2.09秒才能获取3.1k照片,而我的照片需要1.85秒。很酷,所以您在当前for循环中使用了另一个循环来对元素进行排序?在这种情况下,它是一个嵌套循环,显然比通常的两个单独循环花费更多的时间。您可以尝试使用bin进行排序ary searchUmm..二进制搜索不会像我想的那样有效,因为没有搜索特定日期。我们需要根据从图书馆获取的日期获取所有数据。你认为呢?不,我知道,但我认为你采用了与我想的类似的方法,我的错。我已经编辑了答案。让我知道你的想法…那么你呢刚刚区分了附加部分!这很酷,我会尝试这样做,比如先附加5或6个日期,然后重新加载UICollectionView
,然后再次附加新数据重新加载它。
func fetchPhotos() -> [AssetsData] {
//Date Formatter
let formatter = DateFormatter()
formatter.dateStyle = DateFormatter.Style.medium
formatter.timeStyle = DateFormatter.Style.none
//Photos fetch
let fetchOptions = PHFetchOptions()
let sortOrder = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.sortDescriptors = sortOrder
let assetsFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
var arrCreationDate = [Date]()
var arrDates = [String]()
var arrPhotoAssetsData = [AssetsData]()
//Getting All dates
for index in 0..<assetsFetchResult.count {
if let creationDate = assetsFetchResult[index].creationDate {
let formattedDate = formatter.string(from: creationDate)
if !arrDates.contains(formattedDate) {
arrDates.append(formattedDate)
arrCreationDate.append(creationDate)
convertToAssetsDataAndAppend(date: creationDate, fetchOptions: fetchOptions, toArray: &arrPhotoAssetsData)
}
}
}
return arrPhotoAssetsData
}
func convertToAssetsDataAndAppend(date: Date, fetchOptions: PHFetchOptions, toArray: inout [AssetsData]){
if let startDate = getDate(forDay: date.day, forMonth: date.month, forYear: date.year, forHour: 0, forMinute: 0, forSecond: 0), let endDate = getDate(forDay: date.day, forMonth: date.month, forYear: date.year, forHour: 23, forMinute: 59, forSecond: 59) {
fetchOptions.predicate = NSPredicate(format: "creationDate > %@ AND creationDate < %@", startDate as NSDate, endDate as NSDate)
let assetsPhotoFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
toArray.append(AssetsData(creationDate: date, assetResult: assetsPhotoFetchResult))
}
}
func getDate(forDay day: Int, forMonth month: Int, forYear year: Int, forHour hour: Int, forMinute minute: Int, forSecond second: Int) -> Date? {
var dateComponents = DateComponents()
dateComponents.day = day
dateComponents.month = month
dateComponents.year = year
dateComponents.hour = hour
dateComponents.minute = minute
dateComponents.second = second
var gregorian = Calendar(identifier: Calendar.Identifier.gregorian)
gregorian.timeZone = NSTimeZone.system
return gregorian.date(from: dateComponents)
}