본문 바로가기
아이폰 개발/ios 개념&튜토리얼

iOS Photos Framework 정리 (PhotoKit)

by 인생여희 2020. 12. 14.

iOS Photos Framework 정리

 

iOS Photos Framework

 

iOS에서 사진이나 동영상에 접근할려면 어떻게 해야할까? 다양한 방법이 있다. 이번 포스팅에서는 다양한 방법중에서 Photos Framework를 이용해서 사진에 접근하고, 사진을 가져오는 방법을 알아본다. 

 

Photos Framework?

Photos Framework란 애플에서 개발자에게 사진이나 영상에 쉽게 접근할 수있도록 관련 라이브러리들을 모아놓은 라이브러리 집합이라고 할 수 있다. 위의 사진 처럼 사용자의 앱은 직접 사진 라이브러리나 iCloud 사진에 접근 할 수 없다. 보안이슈 등의 문제가 있기 때문이다. 그래서 그림과 같이 우리의 앱은 무조건 PhotoKit 라이브러리를 통해서 사진에 접근할 수 있다.

 

Photos Framework 대표 클래스 3개

Photos Framework에는 대표적인 클래스가 3개 있다. 지금은 이 클래스의 이름과 특징만 기억해도 좋다. Photos Framework 대표 클래스의 종류와 특징은 아래와 같다.

1.PHAsset
이미지, 비디오, 라이브  사진을 나타내는 클래스이다. 사진 하나하나. 영상 하나하나의 정보를 가지고 있다. 어려운 말로 에셋이라고 한다.

 

PHAsset 예

* 미디어타입 (Media type)
* 생성일 (Creation date)
* 위치(Location)

* 선호하는 사진(Favorite)

 

 

2.PHAssetCollectoin

앨범, 사용자 정의 앨범, 특별한 순간과 같은 그룹을 나타낸다. 사진의 앨범 단위라고 생각하면된다. 에셋 그룹이라고도 한다.

 

PHAssetCollectoin 예

* 타입(Type)
* 이름(Title)
* 콜렉션에 속한 애셋의 시작 날짜와 종료 날짜

 

3.PHCollectionList

앨범 폴더, 사용자정의 앨범, 특별한 순간들 연도와 같은 에셋 컬렉션 리스트를 나타낸다. 2번의 에셋 그룹의 리스트라고 생각하면 된다.

 

PHCollectionList 예


* 타입(Type)
* 제목(Title)

* 콜렉션 리스트에 속한 애셋의 시작 날짜와 종료 날짜

 

 

특징

위의 대표적인 3개의 클래스는 한가지 특징이 있다. 바로 위의 클래스를 이용해서 사진과 영상을 읽어 올 수 있지만, 사진을 편집할 수는 없다. PHAsset, PHCollection, PHObject, PHFetchResult 등의 클래스들은 메타데이터만 가지고 있는 읽기 전용 클래스이다. 만약 사진을 편집할려고 한다면 PHContentEditingInput, PHContentEditingOutput, PHAdjustmentData 등의 클래스를 이용해서 사진을 편집 할 수 있다.

 

앨범 정보 조회하기

위에서 언급한 클래스 중 PHAssetCollection 클래스를 이용해서 앨범을 가져오는 코드를 살펴본다. PHAssetCollection은 사진 하나하나를 다루는 클래스가 아니라 사진들의 모음인 앨범 단위를 다루는 클래스이다. 그래서 PHAssetCollection에 구현되어 있는 fetchAssetCollectionsWithType 메소드를 이용해서 smart앨범 리스트를 가져와보자.

 

    
    PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    
    NSLog(@"## smartAlbum 개수 : %d" , (int)[smartAlbums count]);
    
    //앨범 개수
    int count = (int)[smartAlbums count];
    for (int i = 0; i < count ; i++) {

        //앨범 단위
        PHCollection *collection = [smartAlbums objectAtIndex:i];
        NSLog(@"앨범 이름(Title) : %@" , collection.localizedTitle);
    }
    
    /*

출력 결과

## smartAlbum 개수 : 17
2020-12-14 23:01:07.481275+0900 TableViewTest[33309:9419439] 앨범 이름(Title) : Panoramas
2020-12-14 23:01:07.481330+0900 TableViewTest[33309:9419439] 앨범 이름(Title) : Videos
2020-12-14 23:01:07.481369+0900 TableViewTest[33309:9419439] 앨범 이름(Title) : Favorites

....
    
    */

 

PHAssetCollection의 fetchAssetCollectionsWithType 메소드를 실행하면 PHFetchResult를 반환한다. 반환된 PHFetchResult의 인덱스에 접근해서 PHCollection를 얻어오면 이 객체에 앨범 제목이 담겨있다.

 

참고로 PHCollection 클래스의 인스턴스를 직접 만들거나 사용하지 않고 두 개의 구체적인 하위 클래스인 PHAssetCollection 또는 PHCollectionList 중 하나를 사용해서 PHCollection을 만들어야 한다.

 

*PHAssetCollection 객체는 앨범, 순간사진 또는 공유사진 스트림과 같은 사진 또는 비디오 모음이다.

*PHCollectionList 객체는 앨범이 포함 된 폴더 또는 특정 연도에 포함된 사진 집합 또늰 모든순간 집합과 같은 다른 컬렉션이 포함 된 부모 컬렉션을 나타낸다.

 

전체 사진 개수 조회 하기

여기서 사진 하나하나에 접근할려면 어떤 클래스를 이용해야 할까? 위에서 언급한 PHAsset 클래스를 사용해야 한다. PHAsset의 fetchAssetsWithOptions 메소드를 사용하면 사진 하나하나가 담긴 PHFetchResult를 얻을 수 있다. 로직은 아래와 같다. 

 

	//PHFetchResult객체
	PHFetchResult *assetsFetchResults;
    
    //전체 사진 개수
    PHFetchOptions *option = [[PHFetchOptions alloc]init];
    
    //옵션설정
    option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
    
    //옵션적용해서 조회
    assetsFetchResults = [PHAsset fetchAssetsWithOptions:option];
    
    NSLog(@"## [results count] 개수 : %d" , (int)[assetsFetchResults count]);
    

 

사진 이미지 조회하기

위의 대표 클래스라고 말한  PHAsset, PHAssetCollectoin, PHCollectionList는 사진 , 앨범, 또는 앨범 리스트에 대한 메타데이터만 가지고 있을 뿐이다. 실제 사진 이미지를 가지고 오려면, 이 메타데이터를 이용해서 PHImageManager 또는 PHCachingImageManager에게

실제 사진을 달라고 요청해야 한다.

 

PHImageManager 클래스는 썸네일이나 에셋등을 검색하거나 생성하는 기능을 제공한다. PHImageManager를 이용하면 photos framework가 알아서 요청한 크기에 맞는 이미지를 로드해서 캐싱해준다. 썸네일이나 작은 이미지를 만들 때, 간단하게 작업할 수 있게 도와준다.

 

//이미지 관리자 객체 생성
PHCachingImageManager *imageManager = [[PHCachingImageManager alloc]init];

        //이미지 사이즈
        CGSize size =  cell.imageView.image.size;
        
        //사진의 메타 데이터
        PHAsset *asset = assetsFetchResults[indexPath.item];
        
        [imageManager requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {

                cell.imageView.image = result;

        }];

 

위의 로직은 ios 테이블 뷰의 cellForRowAtIndexPath 메소드에서 셀을 구성하는 로직 중 일부분이다. 중요한건 이미지를 가져오기 위해서 PHCachingImageManager 객체를 생성한 후, requestImageForAsset 메소드를 호출하면서 PHAset(사진 하나하나 각각의 메타데이터)을 인자로 넣어주었다는 점이다. 리턴 값으로 UIImage 타입의 result 이미지를 리턴해준다.

 

사진권한

참고로 사진에 접근하기 위해서는 접근권한을 체크해야 한다. 사진접근권한을 체크하는 로직은 아래와 같다.

 

    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        switch (status) {
            case PHAuthorizationStatusAuthorized:
                NSLog(@"사용 가능");

                break;
            case PHAuthorizationStatusRestricted:
                NSLog(@"아직 안됨..");
                break;
            case PHAuthorizationStatusDenied:
                NSLog(@"거부");
                break;
            default:
                break;
        }
    }];