본문 바로가기

STUDY/IOS

[부스트코스] iOS프로그래밍 4강 - 포토 라이브러리 구현하기 (1)

하루만에 4강을 다 들었다...

친구들이랑 같이 하는데, 다들 멘탈이 나가있어서 구현 하기 좀 무섭..

 

암튼 이번 구현 과제의 조건은 앨범앱을 만드는 것이다.

 

구현하는데 필요한 기술은

Operation Queue, Collection View, data decode 정도 될 것 같다.

화면 1 - 앨범 목록

첫 화면에는 앨범 목록을 구현한다.

화면 구성은 다음과 같다.

  • 네비게이션 아이템 타이틀 : 앨범
  • 컬렉션 뷰를 이용한 앨범의 대표 이미지 뷰.
    • 정사각형 모양으로, 내부의 이미지는 기존 이미지 비율을 유지
    • 앨범의 대표 이미지는 해당 앨범의 가장 최신 사진
    • 이미지 아래 앨범 이름을 보여주어야 함
    • 앨범 이름 아래 앨범에 포함된 사진의 개수를 보여줌

구현 해야 하는 기능은 사진 라이브러리 접근권한 허용 여부를 묻는 기능과, 화면 전환 기능이다.

접근권한 수락시 기본앨범과 사용자 커스텀 앨범을 가져오고, 비 수락시 컬렉션 뷰에 사진이 나타나지 않으며, 강제종료가 되지 않음.

 

우선 늘 하듯 네비게이션 뷰 컨트롤러 설정과 컬렉션 뷰를 설정해준다.

기기의 사진 앨범에 접근하기 위한 코드를 작성해 준다.

 

하다보니 중간에 이상한 오류가 계속 나왔는데 Privacy와 관련해서 경고 메세지를 작성하는 부분을 빼먹었었다.

애플은 참 이 부분을 중요하게 생각 하는 것 같다.

잊지 말자 프라이버시

앨범 데이터를 불러오기 위해, Photos Library를 열심히 탐방했다.

여기서 AssetCollection을 쓰는것 까지는 금방 찾았는데, 그 이후에 요소를 다루는 데에서 정말 애먹었다.

한 4-5시간 그것만 찾은 듯.

 

일단 앨범 목록을 불러와야 하기 때문에 PHAssetCollection을 이용해서 불러와 주었다.

불러올 때에는 fetchAssetCollection 메서드를 이용할 수 있다.

나는 사용자 앨범과 스마트 앨범을 모두 불러오고 싶어서 다음과 같이 코드를 작성했다.

var fetchResult : [var fetchResult : [PHAssetCollection] = []] = []
let photoAlbums : PHFetchResult<PHAssetCollection> = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
let smartAlbums : PHFetchResult<PHAssetCollection> = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumFavorites, options: nil)

.album은 customer(user) album을, .smartAlbum은 최신, 즐겨찾기 등의 앨범을 나타낸다.

subtype을 이용하여 옵션(?)을 줄 수 있는데 .any일 경우 해당하는 모든 앨범 타입을 나타내게 할 수도 있고,

.smartAlbumFavorites와 같이 특정 앨범만 불러올 수도 있다.

 

ViewDidLoad에서 fetchResult 배열에 값을 넣어주고자 다음과 같은 코드를 삽입했다.

self.photoAlbums.enumerateObjects({(collection, index, object) in
            self.fetchResult.append(collection)
        })
        
self.smartAlbums.enumerateObjects({(collection, index, object) in
    	    self.fetchResult.append(collection)
        })

해당 코드는 enumerateObjects를 이용하여, 각 요소가 순차적으로 fetchResult 에 append 될 수 있게 짜 주었다.

 

cell은 커스터마이징해서, CollectionViewCell을 만들어 지정해 주었고,

asset은 fetchResult의 각 요소(앨범)으로, firstImg는 PHFetchResult로 만들어 주었다.

이때 firstImg는 정렬되어 불러와진 요소들을 가지고 있기 때문에, 추후에 생성 날짜별로 정렬될 수 있도록 코드를 짜 줄 예정이다.

img의 경우 UIImageView에 삽입하기 위해 PHAsset으로 선언하여, firstImg에서 받아온 에셋들의 첫번째 항목을 불러오게끔 했다.

 

약간 여기서 좀 헷갈렸는데, fetchResult에는 enumerate를 하면서 PHFetchResult<PHAssetCollection>의 object가 들어가 있다.

즉, fetchResult 는 Object의 배열이고

asset의 경우 PHAssetColletion의 자료형이기 때문에 fetchResult의 각 요소를 참조.

firstImg의 경우 PHFetchResult<PHAsset> 으로 PHAsset을 object로 가진 집합이 된다. 

그래서 그 부분을 한번 더 벗기기 위해서,

img라는 변수를 선언해서 fistImg의 0번째 object를 할당 해 주었다.

 

Title과, count는 PHAssetCollection이 가진 프로퍼티이기 때문에 바로 구현해 주었다.

 

배열속의 배열속의 배열속의 이미지 같은 느낌...

 

이렇게 구현 된 코드에, 스토리 보드는 다음과 같다.

실제로 구현된 화면은 다음과 같다.

시뮬레이터 포토부스 앨범 (왼쪽), 구현한 앨범 목록(가운데), 셀을 눌렀을때 작동 화면(오른쪽)

구현하면서 애플 개발자 문서를 몇번이고 보고, 스택오버플로우도 정말정말 많이 본 것 같다.

아직 의문이 남은 것은 smartAlbum의 경우, estimatedAssetCount가 굉장히 크게 나온다는 것인데

지금 의심해 보기로는 저장 가능한 애셋의 숫자를 반환하는게 아닐까 싶긴하다. 

 

아까 얘기했던, 날짜순 정렬과, 해당 문제 해결 및 가능하다면 앨범끼리도 이름 순 정렬을 해보고자 한다.

오늘 첫 화면을 구성했으니, 다음에는 힘내서 두번째 화면을 구성해 봐야겠다.