Photos framework와 사용법에 대해 알아 보겠습니다.
Photos 프레임워크
UIImagePickerController는 사용자가 카메라나 앨범에서 직접 사진을 고르는 방식으로 이미지를 얻어 오는 반면, photos 프레임워크는 UI를 이용한 사용자의 조작 업이 iOS에서 iCloud사진 라이브러리를 포함하여 사진 및 비디오에 직접 접근할 수 있습니다.
포토 프레임 워크를 사용하려면 Photo Framework를 직접 추가 합니다.
그 이후 import를 작성 합니다.
import Photos
Photos 프레임워크 모델 클래스에는 PHAsset, PHAssetCollection, PHCollectionList 3가지가 있습니다.
1. 애셋과 콜렉션
PHAsset
- 이미지, 비디오, 라이브 포토 각각을 표현하는 클래스 입니다.
애셋(Assets)은 다음과 같은 데이터를 다룹니다.
- 미디어타입 (Media type)
- 생성일 (Creation date)
- 위치(Location)
- 선호하는 사진(Favorite)
PHAssetCollectoin
- 앨범, 사용자 정의 앨범, 특별한 순간과 같은 에셋 그룹을 나타냅니다.
애셋 콜렉션은 다음과 같은 데이터를 다룹니다.
- 타입(Type)
- 이름(Title)
- 콜렉션에 속한 애셋의 시작 날짜와 종료 날짜
PHCollectionList
- 앨범 폴더, 사용자정의 앨범, 특별한 순간들 연도와 같은 에셋 컬렉션 그룹을 나타냅니다.
콜렉션 리스트는 다음과 같은 데이터를 다룹니다.
- 타입(Type)
- 제목(Title)
- 콜렉션 리스트에 속한 애셋의 시작 날짜와 종료 날짜
2. 접근 권한
요청
접근 권한을 요청하려면 PHPhotoLibrary클래스의 다음과 같은 메소드로 요청해야합니다.
open class func requestAuthorization(_ handler: @escaping (PHAuthorizationStatus) -> Void)
권한을 요청하면 UIImagePickerController와 마찬가지로 info.plist에 다음과 같은 문구를 입력해야 합니다.
Privacy - Photo Library Usage Description
권한 상태
사용자의 앨범에 접근하려면 사용자에게 권한을 승인 받아야 사용할 수 있습니다.
PHPhotoLibrary클래스의 authorizationStatus메소드를 이용해서 사용자의 승인 여부 상태를 알 수 있습니다.
open class func authorizationStatus() -> PHAuthorizationStatus
PHAuthorizationStatus는 다음과 같이 정의된 enum 타입으로 이루어져 있습니다.
- notDetermined : 아직 접근 여부를 결정하지 않은 상태
- restricted : 앨범에 접근 불가능하고, 권한 변경이 불가능한 상태
- denied : 앨범 접근 불가능한 상태. 권한 변경이 가능함.
- authorized : 앨범 접근이 승인된 상태.
< 코드 >
// 접근 권한 요청 방법
switch PHPhotoLibrary.authorizationStatus() {
case .notDetermined:
print("권한 요청 필요합니다.")
PHPhotoLibrary.requestAuthorization { (status) in
print("접근 권한 결정 : ", status)
}
case .denied :
print("앨범 접근 허가가 필요합니다. 사용자에게 권한 변경 요청 해야함")
case .restricted:
print("앨범 접근 불가능")
case .authorized:
print("앨범 접근 가능")
}
3. 모델 얻어 오기
애셋과 애셋 콜렉션, 콜렉션리스트를 모델이라고 합니다.
개별 사진이나 비디오를 다루는 PHAsset 클래스는 다음과 같은 메서드로 정의되어있고,
사진 라이브러리에서 모델을 얻어오려면 Fetch 메소드를 사용해야합니다.
// 미디어 타입으로 가져오기
open class func fetchAssets(with mediaType: PHAssetMediaType, options: PHFetchOptions?) -> PHFetchResult// 애셋 콜렉션에 속한 애셋 가져오기
open class func fetchAssets(in assetCollection: PHAssetCollection, options: PHFetchOptions?) -> PHFetchResult
PHAssetMediaType
PHAssetMediaType을 이용해서 사진이나 동영상, 오디오와 같은 미디어 타입을 설정할 수 있습니다.
- unknown
- image
- video
- audio
PHFetchOptions
PHFetchOptions는 다음과 같이 모델을 가져오는 과정에서 정렬(sort)를 하거나 검색 조건(NSPredicate)을 설정 할 수 있습니다.
- open var predicate: NSPredicate?
- open var sortDescriptors: [NSSortDescriptor]?
- open var includeHiddenAssets: Bool
- open var includeAllBurstAssets: Bool
- @available(iOS 9.0, *)
open var includeAssetSourceTypes: PHAssetSourceType- @available(iOS 9.0, *)
open var fetchLimit: Int- open var wantsIncrementalChangeDetails: Bool
PHFetchResult
PHFetchResult<Type>은 요청 결과 클래스의 제네릭 타입으로 표현으로 PHAsset을 얻기 위한 요청 결과는 PHFetchResult입니다.
이렇게 얻은 PHFetchResult를 이용해서 애셋이나 애셋컬렉션에 접근 할 수 있습니다.
PHFetchResult을 다루는 메서드
open var count: Int { get }
open func index(of anObject: ObjectType) -> Int
open func enumerateObjects(_ block: @escaping (ObjectType, Int, UnsafeMutablePointer) -> Void)
//이미지 요청
let allPhotos = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
//이미지 애셋 갯수
allPhotos.count
//index를 통해서 해당 Asset에 접근가능
allPhotos.object(at: 2)
//이미지 애셋을 enumerate로 접근해서 애셋 정보를 가져오기
allPhotos.enumerateObjects { (asset, count, stop) in
// asset <PHAsset: 0x14fe04c00> 2A3ECFFC-9C01-4FB1-88C4-71C01245A0E5/L0/001 mediaType=1/0, sourceType=1, (1440x1080), creationDate=2018-12-01 08:12:06 +0000, location=0, hidden=0, favorite=0
// count 0
// stop 0x000000016f9a1e28
}
// 예제 2
let fetchOptions = PHFetchOptions()
fetchOptions.fetchLimit = 10
let sortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)
fetchOptions.sortDescriptors = [sortDescriptor]
let allPhotos = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
allPhotos.enumerateObjects { (asset, count, stop) in
print("asset",asset)
print("count",count)
print("stop",stop)
}
4. 이미지 가져오기
실제 이미지와 비디오를 가져오려면 PHImageManager를 이용해야 됩니다.
// 객체 생성
let imageManager = PHImageManager.default()
// 이미지 요청
open func requestImage(for asset: PHAsset, targetSize: CGSize, contentMode: PHImageContentMode, options: PHImageRequestOptions?, resultHandler: @escaping (UIImage?, [AnyHashable : Any]?) -> Void) -> PHImageRequestID
private func fetchPhotos() {
let fetchOptions = PHFetchOptions()
fetchOptions.fetchLimit = 10
let sortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)
fetchOptions.sortDescriptors = [sortDescriptor]
let allPhotos = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
allPhotos.enumerateObjects { (asset, count, stop) in
print("asset",asset)
print("count",count)
print("stop",stop)
let targetSize = CGSize(width: 350, height: 350)
let imageManager = PHImageManager.default()
let optinos = PHImageRequestOptions()
optinos.isSynchronous = true // 순서대로 불러온다.
// 이미지 정보 얻어오기
imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: PHImageContentMode.aspectFit, options: optinos, resultHandler: { (image, info) in
print("Image : ", image)
//Image : Optional(<UIImage: 0x600001b81dc0>, {386, 256})
print("Info : ", info)
// Info : Optional([AnyHashable("PHImageResultIsDegradedKey"): 0, AnyHashable("PHImageFileOrientationKey"): 0, AnyHashable("PHImageResultWantedImageFormatKey"): 5003, AnyHashable("PHImageResultDeliveredImageFormatKey"): 5003])
if let image = image {
self.images.append(image)
}
if count == allPhotos.count - 1 {
self.collectionView?.reloadData()
}
})
}
}
'iOS' 카테고리의 다른 글
[iOS] ContentOffset과 ContentInset (0) | 2019.07.25 |
---|---|
[iOS] ScrollView (0) | 2019.07.25 |
[iOS] iOS Realm이란? (0) | 2019.07.24 |
[iOS] UIDevice (0) | 2019.07.24 |
[iOS] GCD(Grand Central Dispatch) (0) | 2019.07.24 |