Photos Frameworkとは
iOS8以降で利用できるALAssetLibraryに変わるPhoto Libraryを取り扱うAPI群。
概要は @ainameの日記が分かりやすい。
詳細はReferenceを参照。
この記事で解決したい問題
Photos FrameworkのPHAssetクラスを利用するとPhoto Libraryから写真・動画のモデルオブジェクトを効率よく取得できる。
PHFetchOptions *fetchOptions = [PHFetchOptions new];
fetchOptions.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO], ]; // ソートしたりとか楽勝
PHFetchResult *result = [PHAsset fetchAssetsWithOptions:fetchOptions];
上記のように取得したPHFetchResultをもとにPHAssetからサムネイルを取得してたとえばUIColloctionViewにimageを並べて表示するようなアプリケーションを作るとする。
このときに何も考えずにFetchした結果を描画すると「画像が重複して表示されてしまう」ことがあった。
iOS8対応直後のInstagramのアップロードメディア選択画面でも同様の事象が起こっていた記憶が…。
解決
いろいろ調べているとどうやらiCloudフォトストリームを使って自動的にアップロードしているのが原因。Photos FrameworkはiCloud上のメディアリソースも端末内と差異無く取り扱ってしまう(取り扱うことが出来る)。iCloud上のメディアは、元が同じ画像でも別のIDがふられた別リソースとして取り扱われる。
問題というより実際はそういう仕様なので、どこにAssetが保存されているかを意識して各Assetを取り扱えば「画像が重複して表示されてしまう」ことはなくなる。
で、PHFetchOptionにわたせるPredicateで指定出来るのかと思いきや、どうやらassetSourceは検索キーとして利用できないっぽい。
なので、取得してきたPHFetchResultから "assetSource=3" のレコードを間引くしかいまのところなさそう。
NSArray *array = [result objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, result.count)]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description contains %@", @"assetSource=3"];
NSArray *filteredArray = [array filteredArrayUsingPredicate:predicate];
参考
同じような悩みを抱えてる人がいて参考になりました。