1

I am willing to order my results by day so that the oldest photos are displayed on top.

I am currently fetching photos using the PHAsset fetchAssetsWithMediaType:

@property PHFetchResult *photos;

self.photos = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];

Ideally I want the results ordered by day, oldest photos first. Like this:

[11 Dec]
Photo #20 with creation time 17:00
Photo #21 with creation time 18:30
Photo #22 with creation time 19:00
Photo #23 with creation time 20:40
Photo #24 with creation time 21:00
[10 Dec]
Photo #16 with creation time 10:30
Photo #17 with creation time 11:00
Photo #18 with creation time 12:20
Photo #19 with creation time 13:00
[9 Dec]
Photo #14 with creation time 16:30
Photo #15 with creation time 17:00

I have seen I can pass a PHFetchOptions object with a predicate and some sort descriptors ( https://developer.apple.com/reference/photos/phfetchoptions ), can you suggest me how to specify them (I believe I should sort them using the creationDate attribute) so that I'll get the desired order?

Niko Zarzani
  • 1,372
  • 2
  • 15
  • 28

2 Answers2

7

You should use PHFetchOptions

    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:true]];
    PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
jignesh Vadadoriya
  • 3,244
  • 3
  • 18
  • 29
  • thanks but this is not the order I was asking, I need the results ordered by day (hence creation date descending), oldest photos first (hence creation time ascending) – Niko Zarzani Dec 14 '16 at 09:48
  • OMG.. let me try that way – jignesh Vadadoriya Dec 14 '16 at 09:50
  • 1
    This doesn't appear to work anymore. Not sure if the problem is Swift or iOS 12, but an exception is thrown when using that sort descriptor. `Unsupported sort descriptor in fetch options: (creationDate, ascending, compare:)` – InkGolem Nov 20 '18 at 01:02
  • @InkGolem Make sure your fetch request is for Asset and not AssetCollection. I had the same problem and later realised I was querying for Album first then Asset in the next part which is where I put in the sort descriptor. – Nur Iman Izam Jul 21 '21 at 14:12
1

PHFetchOptions accepts sortDescriptors, however it ignores custom comparisons (i believe since it simply does an SQL query) as written here (https://developer.apple.com/reference/photos/phfetchoptions/1624771-sortdescriptors):

Photos does not support sort descriptors created with the sortDescriptorWithKey:ascending:comparator: method.

The answer is that you should move the results in a new NSArray and then order them after fetching them:

- (void)loadPhotos
{
    PHFetchResult *photosResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];

    self.photos = [@[] mutableCopy];
    for(PHAsset *asset in photosResult){
        [self.photos addObject:asset];
    }
    [self.photos sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"creationDate"
                                                                      ascending:YES
                                                                     comparator:^NSComparisonResult(NSDate *dateTime1, NSDate *dateTime2) {
                                                                         unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
                                                                         NSCalendar* calendar = [NSCalendar currentCalendar];

                                                                         NSDateComponents* components1 = [calendar components:flags fromDate:dateTime1];
                                                                         NSDate* date1 = [calendar dateFromComponents:components1];

                                                                         NSDateComponents* components2 = [calendar components:flags fromDate:dateTime2];
                                                                         NSDate* date2 = [calendar dateFromComponents:components2];

                                                                         NSComparisonResult comparedDates = [date1 compare:date2];
                                                                         if(comparedDates == NSOrderedSame)
                                                                         {
                                                                             return [dateTime2 compare:dateTime1];
                                                                         }
                                                                         return comparedDates;
                                                                     }
                                         ]]];

}

I didn't tested this solution with a huge camera roll (sorting here is done in memory and it can be a performance bottleneck), but I hope this can help.

Niko Zarzani
  • 1,372
  • 2
  • 15
  • 28
  • From the documentation you linked: `Photos does not support sort descriptors created with the sortDescriptorWithKey:ascending:comparator: method.`. – InkGolem Nov 20 '18 at 01:03