如何从 iOS 中两个日期范围内的照片库中获取图像?

Posted

技术标签:

【中文标题】如何从 iOS 中两个日期范围内的照片库中获取图像?【英文标题】:How to fetch images from photo library within range of two dates in iOS? 【发布时间】:2016-09-20 06:46:26 【问题描述】:

上下文

我正在尝试从照片库中获取两个日期范围内的图像。

首先,我在字典表单中一张一张地获取照片库图像的信息,并使用键选择每个图像日期,并使用 if 条件将该日期与两个日期进行比较。

如果该图像的日期介于两个日期之间,我将该图像插入到数组中。

我正在将图像保存在数组中,因为我想在集合视图中显示它们。

问题

虽然它在模拟器上运行,但由于内存问题,它不能在真实设备上运行。

我认为真实设备照片库中有大量图像,这就是内存问题的原因。

我该如何解决这个问题?

【问题讨论】:

我在您的问题中添加了 AlAssetsLibrary 标签以避免混淆。如果您愿意使用照片库,请告诉我。 好的,谢谢你的 AlAssetsLibrary 标签。是的,我只需要从照片库中获取图像。 我的意思是 This Photos Framework 是 AssetsLibrary 的更新替代品。 好吧,我会...我觉得它更好,新的 查看更新后的答案。如果您有任何问题,请发表评论 【参考方案1】:

根据我们在 cmets 中的对话,您同意切换到照片框架而不是资产库,而不是将图像保存到您的数组中,而是将 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

中获取两个日期之间的图像

【讨论】:

感谢您的重播,您能否发布在日期之间获取图像的代码,因为我没有使用 PHAsset 我正在使用 ALAsset @ChandanReddy 照片库比资产库好。您会考虑切换到照片库吗?如果不是,此答案无效,我将其删除。 你知道图像的经纬度吗? 如果存在,可以从 PHAsset 中获取。如果您愿意,请创建一个新问题,并在您这样做时联系我。 @ChandanReddy 查看***.com/questions/39744762/…【参考方案2】:

为什么要将图像保存在数组中。如果图像在两个日期之间,只需将图像的名称存储在数组中。然后使用下面的代码通过库中的名称获取和使用图像

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;

【讨论】:

将图像保存在数组中,因为我想在集合视图中显示它们 在数组和 cellForItemAtIndexPath 方法中存储名称使用上述代码获取图像并在集合视图中显示。

以上是关于如何从 iOS 中两个日期范围内的照片库中获取图像?的主要内容,如果未能解决你的问题,请参考以下文章

斯威夫特:如何设置两个日期之间的照片范围?

如何获取日期范围内的缺失值?

从照片库加载图像并按日期排序的内存问题

获取两个日期范围内的上周日(GMT、DST)

Sql Server - 从提供的范围内的数据库中获取日期

SQL从日期范围内的同一表中的不同记录中获取多个项目的总和(ORACLE)