Согласно нашему разговору в комментариях, в котором вы согласились переключиться на Photos Framework вместо библиотеки активов, вместо сохранения изображений в свой массив сохраните локальный идентификатор PHAsset в свой массив.
Получите локальные идентификаторы изображений, которые находятся в вашем диапазоне дат
Чтобы получить изображения по дате, сначала создайте служебный метод для создания даты для повторного использования:
-(NSDate*) getDateForDay:(NSInteger) day andMonth:(NSInteger) month andYear:(NSInteger) year{
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:day];
[comps setMonth:month];
[comps setYear:year];
NSDate *date = [[NSCalendar currentCalendar] dateFromComponents:comps];
return date;
}
Вы можете создать startDate и endDate из него следующим образом:
NSDate *startDate = [self getDateForDay:11 andMonth:10 andYear:2015];
NSDate *endDate = [self getDateForDay:15 andMonth:8 andYear:2016];
Теперь вам нужно получить FetchResults из библиотеки фотографий, которые существуют между этим диапазоном. Используйте для этого этот метод:
-(PHFetchResult*) getAssetsFromLibraryWithStartDate:(NSDate *)startDate andEndDate:(NSDate*) endDate
{
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"creationDate > %@ AND creationDate < %@",startDate ,endDate];
PHFetchResult *allPhotos = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
return allPhotos;
}
Теперь вы получаете PHFetchResults
всех фотографий, существующих в этом диапазоне дат. Теперь, чтобы извлечь массив данных локальных идентификаторов, вы можете использовать этот метод:
-(NSMutableArray *) getAssetIdentifiersForFetchResults:(PHFetchResult *) result{
NSMutableArray *identifierArray = [[NSMutableArray alloc] init];
for(PHAsset *asset in result){
NSString *identifierString = asset.localIdentifier;
[identifierArray addObject:identifierString];
}
return identifierArray;
}
Добавьте методы для извлечения/использования отдельных активов, когда они вам нужны.
Теперь вам понадобится PHAsset
для изображения. Вы можете использовать LocalIdentifier следующим образом, чтобы получить PHAsset
:
-(void) getPHAssetWithIdentifier:(NSString *) localIdentifier andSuccessBlock:(void (^)(id asset))successBlock failure:(void (^)(NSError *))failureBlock{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *identifiers = [[NSArray alloc] initWithObjects:localIdentifier, nil];
PHFetchResult *savedAssets = [PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:nil];
if(savedAssets.count>0)
{
successBlock(savedAssets[0]);
}
else
{
NSError *error;
failureBlock(error);
}
});
}
Затем, используя этот PHAsset
, вы можете получить изображение нужного вам размера (постарайтесь сделать его как можно меньше, чтобы свести к минимуму использование памяти):
-(void) getImageForAsset: (PHAsset *) asset andTargetSize: (CGSize) targetSize andSuccessBlock:(void (^)(UIImage * photoObj))successBlock {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PHImageRequestOptions *requestOptions;
requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
requestOptions.synchronous = true;
PHImageManager *manager = [PHImageManager defaultManager];
[manager requestImageForAsset:asset
targetSize:targetSize
contentMode:PHImageContentModeDefault
options:requestOptions
resultHandler:^void(UIImage *image, NSDictionary *info) {
@autoreleasepool {
if(image!=nil){
successBlock(image);
}
}
}];
});
}
Но не вызывайте эти методы напрямую, чтобы получить все желаемые изображения.
Вместо этого вызовите эти методы в своем методе cellForItemAtIndexPath
, например:
//Show spinner
[self getPHAssetWithIdentifier:yourLocalIdentifierAtIndexPath andSuccessBlock:^(id assetObj) {
PHAsset *asset = (PHAsset*)assetObj;
[self getImageForAsset:asset andTargetSize:yourTargetCGSize andSuccessBlock:^(UIImage *photoObj) {
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI of cell
//Hide spinner
cell.imgViewBg.image = photoObj;
});
}];
} failure:^(NSError *err) {
//Some error occurred in fetching the image
}];
Заключение
Итак, в заключение:
- Вы можете решить свои проблемы с памятью, извлекая изображения только для видимых ячеек, а не извлекая их все.
- Вы можете оптимизировать свою производительность, извлекая изображения из фоновых потоков.
Если вы все равно хотите собрать все свои активы вместе, вы можете получить их с помощью fetchAssetCollectionWithLocalIdentifiers:, хотя я не рекомендую его.
Пожалуйста, оставьте комментарий, если у вас есть какие-либо вопросы или если у вас есть какие-либо другие отзывы.
Кредиты Линдси Скотт за установку предиката для запроса PHFetchResult для получения изображений между двумя датами в ее ответе здесь
person
NSNoob
schedule
20.09.2016