PhotoKit은 iOS의 기본 사진 앱이 관리하는 사진과 비디오에 접근하여 데이터를 가져오거나 편집, 삭제 등을 할 수 있게 해주는 프레임워크입니다.

PhotoKit
PhotoKit 작동 원리

사진이나 비디오는 기본적으로 텍스트나 여타 바이너리에 비해 용량이 크고, 요즘 같이 고화질 시대에는 더더욱 용량이 어마어마해집니다. 그래서 PhotoKit은 사진과 비디오 등에 대한 메타 데이터만을 우선 제공한 뒤, 필요할 때 이 메타데이터를 가지고 필요한 사진이나 비디오를 요청하는 방식으로 작동됩니다. 따라서 이 메타 데이터를 이해하는 게 PhotoKit을 잘 다루는 것의 핵심이라 할 수 있습니다.

PHHierachy

PhotoKit에서 다루는 모든 데이터는 PHObject의 서브클래스로 나타납니다.

참고로, 이 PHObject와 그 하위클래스들은 hashable 프로토콜을 채택하여서, Set,Dictionalry등의 키로써도 사용이 가능합니다.

  • PHAsset : 개별적인 사진 또는 비디오를 나타내는 타입으로, 해당 타입의 인스턴스로 실제 사진 이나 비디오를 요청하게 됩니다.

  • PHAssetCollection : 하나의 앨범을 나타내는 타입입니다.

  • PHCollectionList : 여러 개의 앨범을 담을 수 있는 폴더를 나타내는 타입입니다.

  • PHObjectPlaceholder : PhotoKit이 새로운 사진, 비디오, 앨범 등을 생성하는 요청을 받았을때, 생성이 끝나기 이전에 임시적으로 생기는 객체를 나타내는 타입입니다.

사진이나 비디오를 불러오기 위해서는 다음과 같은 과정을 거칩니다.

  1. 원하는 사진 또는 비디오의 메타데이터를 가져옵니다. 이를 위해 먼저 앨범 리스트, 앨범 등의 정보를 가져와야 할 수도 있습니다만, 결국에 사진이나 비디오를 요청하기 위해서는 PHAsset이 필요합니다.

    PHObject의 서브클래스들은 ‘fetch’라는 단어가 붙은 정적 메소드들을 제공하는데, 이 메소드들을 통해서 해당 타입의 데이터들을 PHFetchResult 라는 지연 계산(lazy evaluation)을 하는 전용 컨테이너 타입에 넣어서 반환해 줍니다. 이 때 PHFecthOption을 이용해 불러오는 데이터의 범위를 제한할 수 있습니다.

    PHFetchOption은 각 타입의 여러 키 값들을 기준으로 값을 걸러내는 판단자(predicate - NSPredicate 타입), 결과값의 순서를 결정하는 정렬서술자(Sort Descriptor - NSSortDescriptor 타입)로 이루어져 있고 정렬 서술자는 Array타입으로 되어 있고, 순서가 앞설수록 우선순위가 높습니다.

    fetch메소드들의 종류는 각 타입의 공식 문서를 확인해주세요!

    또한 PHFetchOption에서 사용 가능한 각 타입의 키 값들은 PHFecthOption의 공식 문서를 확인해주세요.

     // PHAsset의 fetch 메소드 중 하나로, 특정 앨범의 사진들을 반환해줍니다.
     class func fetchAssets(in: PHAssetCollection, options: PHFetchOptions?) -> PHFetchResult<PHAsset>
    
     // PHAssetCollection의 fetch 메소드 중 하나로, 특정 타입의 앨범들을 반환해줍니다.
     class func fetchAssetCollections(with: PHAssetCollectionType, subtype: PHAssetCollectionSubtype, options: PHFetchOptions?) -> PHFetchResult<PHAssetCollection>
    
  2. 1에서 얻은 PHFetchResult의 결과물들을 가지고 이제는 PHImageManager 계열의 인스턴스를 만들고, 해당 인스턴스의 requestImage() 메소드를 통해 PhotoKit에 실제 사진을 요청합니다. 이때도 역시 옵션값을 줄 수 있는데, 이 경우는 PHImageRequestOptions를 사용합니다.

     func requestImage(for asset: PHAsset, // 요청하는 사진
         targetSize: CGSize, // 요청하는 크기. 
         contentMode: PHImageContentMode, // 요청하는 크기에 대한 이미지 비율
             options: PHImageRequestOptions?, //부가적인 옵션
         resultHandler: @escaping (UIImage?, [AnyHashable : Any]?) -> Void) -> PHImageRequestID // 이미지를 불러온 뒤의 처리
    
  • PHImageRequestOption의 주요 프로퍼티들

    프로퍼티 설명 가능한 값
    isSynchronous 이미지 요청을 동기적으로 할 것인지 여부, 기본은 false(비동기) true, false
    version 편집이 된 상태의 이미지를 받을지, 원본 이미지를 받을지 여부 .current,
    .unadjusted,
    .original
    deliveryMode 요청한 이미지의 품질. 속도와 품질의 균형을 결정한다. .oppotunistic,
    .highQualityFormat,
    .fastFormat
    resizeMode 이미지를 요청한 크기에 맞게 사이즈를 변경하는 정도 .none,
    .fast,
    .exact
    normalizedCropRect 원본 이미지에서 일부만을 사용하고자 할때, 그 범위 0.0<=x<=1.0,
    0.0<=y<=1.0
    의 범위 내의 Rectangle

PhotoKit은 처음보면 이해하기 어렵지만, 원리와 구조만 알면 다음과 같이 아주 간단하게 사용할 수 있습니다. 다음에는 이 Asset들을 가지고 Photos에 변화를 주는 법에 대해서 정리해보도록 하겠습니다!