我尝试在照片库的两个日期范围内获取图像。
首先,我在字典表格中逐个获取照片库图片的信息,并使用密钥选择每个图像日期,并使用if条件将该日期与两个日期进行比较。
如果该图像的日期位于两个日期之间,我将该图像插入数组。
我正在将数据保存在数组中,因为我想在集合视图中显示它们。
虽然它在模拟器上运行,但由于内存问题,它无法在真实设备上运行。
我认为真实设备照片库中有大量图像,这就是为什么会出现内存问题。
我该如何解决这个问题?
答案 0 :(得分:5)
根据我们在评论中的对话,您同意切换到照片框架而不是资产库,而不是将图像保存到您的阵列,将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:方法获取它,但我会建议您反对它。
如果您有任何疑问或有任何其他反馈,请发表评论。
向Lyndsey Scott致信,将谓词设置为PHFetchResult请求,以便在她的回答here 中的两个日期之间获取图像
答案 1 :(得分:-1)
为什么要将图像保存在数组中。如果图像位于两个日期之间,则只存储图像中的图像名称。然后使用下面的代码从库中获取和使用图像
NSString* photoName = [NSString stringWithFormat:@"%@.png",imageName];
NSArray *arrayPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask, YES);
NSString *path = [arrayPaths objectAtIndex:0];
NSString* imagePath = [path stringByAppendingPathComponent: photoName];
UIImage *image1=[UIImage imageWithContentsOfFile: imagePath];
imageView.image=image1;