티스토리 뷰

iOS

iOS ) PHContentEditingInput

Zedd0202 2020. 5. 5. 17:15
반응형

 

안녕하세요 :) Zedd입니다.

오늘은 PHContentEditingInput에 대해서 공부해보겠삼

앞에...PH가 붙은걸 보니..Photos 프레임워크에 있는 친구라는 것을 짐작할 수 있습니다.

응 맞아

 

PHContentEditingInput

정의는 "편집할 asset의 이미지, 비디오 또는 라이브 사진 컨텐츠에 대한 정보와 접근을 제공하는 컨테이너"

입니다.

 

무슨 소리인지..아직 이해 못하는 사람이 있다? 뿌슝빠슝

그건 바로 나,...

그냥 바로 예제로 봅시다.

 

오늘의 주인공인 PHContentEditingInput은 그냥 뿅ㄴ하고 만들 수 없습니다.

PHAsset을 가지고 

야!!!!!!!!!!!!!!!!!!!! PHContentEditingInput 내놓으삼 

해야하는 부분

그 작업은 requestContentEditingInput를 통해 하면 됩니다. 

그럼 해본다..

자 저는 지금 UIImagePickerController를 present해줬습니다.

이미지를 선택하면, UIImagePickerControllerDelegate메소드인 어쩌구가 불리고

 선택한 이미지에서 PHAsset을 가져올 수 있습니다. 

그럼 requestContentEditingInput를 해봅시더.

자! 이렇게 해줬습니다. completionHandler안에 contentEditingInput과 info를 줍니다.

 

contentEditingInput은 말그대로...contentEditingInput이고

info는 요청 상태에 대한 정보를 제공하는 dictionary라고 해요.

아무튼 위 코드는 

Optional(<PHContentEditingInput: 0x6000003c2490> mediaType=1/0, creationDate=2012-08-08 18:52:11 +0000, location=1, adjustmentData=(null)) // contentEditingInput

[AnyHashable("PHImageResultRequestIDKey"): 1] // info

를 출력합니다.

 

자 일단!!! 난 왕초보니간..

info는 나중에보고 contentEditingInput만 보겠습니다.

Optional(<PHContentEditingInput: 0x6000003c2490> mediaType=1/0, creationDate=2012-08-08 18:52:11 +0000, location=1, adjustmentData=(null))

흠...ㅎㅡㅁ...

 

뜬금없지만!!!!!! 우리 아까 

asset을 만들어줬잖아요? 이 asset을 출력해보겠삼

Optional(<PHAsset: 0x7fa76f31d6f0> 9F983DBA-EC35-42B8-8773-B597CF782EDD/L0/001 mediaType=1/0, sourceType=1, (3000x2002), creationDate=2012-08-08 18:52:11 +0000, location=1, hidden=0, favorite=0, adjusted=0 )

오....contentEditingInput랑 상당히 비슷하네요!

contentEditingInput : Optional(<PHContentEditingInput: 0x6000003c2490> mediaType=1/0, creationDate=2012-08-08 18:52:11 +0000, location=1, adjustmentData=(null))

phasset : Optional(<PHAsset: 0x7fa76f31d6f0> 9F983DBA-EC35-42B8-8773-B597CF782EDD/L0/001 mediaType=1/0, sourceType=1, (3000x2002), creationDate=2012-08-08 18:52:11 +0000, location=1, hidden=0, favorite=0, adjusted=0 )

제가 궁금ㄴ한건 contentEditingInput이니까 contentEditingInput에만 있는걸 볼게요. 

 

네! 바로 adjustmentData입니다ㅏㅏㅏ

contentEditingInput : Optional(<PHContentEditingInput: 0x6000003c2490> mediaType=1/0, creationDate=2012-08-08 18:52:11 +0000, location=1, adjustmentData=(null))

요게 뭘까요!?

그럼 이것도 예제로 살펴봅시다..

 

그저 빛

자..사진에 "편집"이라는 기능이 있잖아요!?

편집을 눌러서 편집을 해봅시다.

 

자 이렇게 사진을 돌려주고 > 완료를 누르면 변경사항이 적용되죠!?

우리 방금 사진 "편집"한거죠?! 

"편집할 asset의 이미지, 비디오 또는 라이브 사진 컨텐츠에 대한 정보와 접근을 제공하는 컨테이너"

contentEditingInput은 편집할 asset의 정보를 가지고 있기 때문에, 이미 편집된!!!! 정보도 가지고 있습니다.

내가 어떤걸 편집했는지에 대한 정보..?라고 해야하는건가...! 

 

이 말은 즉, 내가 어떤 사진이나 동영상을 편집하고 싶으면,

contentEditingInput을 호출 한 뒤 contentEditingInput에 변경사항을 적용하고

어쩌고 하면 된다는 소리인데, 이거는 나중에 볼게요.

 

 

자 그럼 정보를 볼까요?

Asset은 편집하면, Photos는 편집한 앱 또는 extension에서 제공한 PHAdjustmentData객체를 저장한다고 해요.

 PHAdjustmentData객체는 original asset data를 사용하여 편집된 Asset을 재구성하는데 필요한 모든 정보를 제공한다고 합니다.

앱이 Asset에 대한 이전 편집 작업을 수행할 수 있는지 여부를 canHandleAdjustmentData에서 줄 수 있는데요. 

음 이걸 false로 줘도 되고 true로 줘도 돼요! 저는 사진앱에서 편집한 정보를 보고싶은거기 때문에 true로 넣어줬어요.

false를 주면, 가장 최근의 Asset Data(모든 이전 편집의 렌더링 결과)를 제공해요. 

 

자 이제 실행하면..

Optional(<PHContentEditingInput: 0x280832630> mediaType=1/0, creationDate=2019-08-15 12:54:37 +0000, location=1, adjustmentData=<PHAdjustmentData: 0x283c35a40> identifier=com.apple.photo version=1.4 data=0x283c34a20 (278))

 

이런게 나오게 됩니다. 네! adjustmentData요! (저게 PHAdjustmentData객체겠죠..!?)

아까는

contentEditingInput : Optional(<PHContentEditingInput: 0x6000003c2490> mediaType=1/0, creationDate=2012-08-08 18:52:11 +0000, location=1, adjustmentData=(null))

이었는데 말이죠.

 

adjustmentData=<PHAdjustmentData: 0x283c35a40> identifier=com.apple.photo version=1.4 data=0x283c34a20 (278))

아까 "편집한 앱 또는 extension에서 제공한 PHAdjustmentData객체를 저장"한다고 그랬는데, Bundle Identifier를 저장하는건가?

사진 앱 = com.apple.photo 

저는 사진앱에서 편집했으니까 사진앱의 Bundle Identifier를 저장한거다...라고 보면 되는거겠죠!?..

자..아무튼 신기하죠?! 전 너무 신기했..

 

자 이렇게 이전에 편집된 정보(?)를 가져오는 궁극적인 이유가 뭘까요..!

네 편집!!!!!!!! ContentEditingInput은 말그대로 Editing을 위한 Input입니다.

 

(근데!!!!!!!! 내가 그 편집사항을 사진앱에 있는 사진에 고대로 적용하고 싶다...고 할 때 이 requestContentEditingInput을 호출해서 하면 좋은거..?같아요.)

그러니까 제가 하고싶은 말은..이 requestContentEditingInput 안에서 사진 또는 동영상을 편집하는거에요!

이전 편집된 정보를 가져오고 싶으면 canHandleAdjustmentData를 true로 주면 되고,

그게 싫으면 false를 주고 새로 편집..(?)하면 되는거에요. (이게 맞는 표현인지는 잘 모르겠네요)

 

자..그럼 본격적으로 우리도 편집을 해봅시다.

그냥 간단하게...필터만 적용해볼게요.

https://zeddios.tistory.com/1019

 

iOS ) CIFilter 사용해보기

안녕하세요 :) Zedd입니다. 지금 어떤걸 하고 있는데..CIFilter를 사용해야해서요! CIFilter를 사용해보는 방법을 공부해보려고 합니다아ㅏ 그냥 간단하게만 볼거에용 먼저 CI를 보면 짐작하실 수 있듯

zeddios.tistory.com

응 하는 법 알아

 

사진을 편집ㄹ하구 싶니?..

 

1. 일단 PHAsset 가져와

2. 가져온 asset에 requestContentEditingInput(with:completionHandler:) 호출 ㄱㄱ 그래서 PHContentEditingInput가져오렴

3. 자 가져온 PHContentEditingInput가지고 너 하고싶은 편집 하면돼. 너는 결과적으로 이 객체가 어떤 변화를 줬는지 기술하는 PHAdjustmentData를 만들어야돼. 

4. PHContentEditingInput이 있으면  PHContentEditingOutput도 있겠죠? PHContentEditingOutput객체를 Initialize하렴. 

5. PHContentEditingOutput의 adjustmentData프로퍼티에 너가 방금 만든 PHAdjustmentData를 넣어줘.

6. 사진 또는 비디오 asset의 경우, 편집된 컨텐츠에 renderedContentURL을 제공해. 

7. 자 이 변경사항을 사진앱에도 적용 해야 할거잖아요? PHAssetChangeRequest를 사용해서 너 사진앱에도 이 변경사항을 commit 하렴₩~

 

위와같은 과정을 거치면 됩니다..ㅎ

해봅시다!

 

1. 일단 PHAsset 가져와

2. 가져온 asset에 requestContentEditingInput(with:completionHandler:) 호출 ㄱㄱ 그래서 PHContentEditingInput가져오렴

-> 여기까진 위에서 했죠?

 

 

3. 자 가져온 PHContentEditingInput가지고 너 하고싶은 편집 하면돼. 너는 결과적으로 이 객체가 어떤 변화를 줬는지 기술하는 PHAdjustmentData를 만들어야돼. 

여기서부터 해봅시다.

내가 하고싶은 편집은 필터를 먹이는거에요.

 

1. URL가져오기

2. CIImage로 만들기

3. 필터먹이기

4. UIImage로 만들기

이렇게 해줍시다. 전체코드는 이따가 올릴게요. 그리고 이렇게 막 강제 언래핑 하면 위험합니다....

일단 코드 흐름만 봐주세요.

 

너는 결과적으로 이 객체가 어떤 변화를 줬는지 기술하는 PHAdjustmentData를 만들어야돼. 

라고 했죠?

PHAdjustmentData의 이니셜라이저는 이렇게 생겼어요. 일단은 Data타입이 보이네요!!!!!!!!

그럼 만들어준 UIImage를 Data로 만들면 되겠어요

PHAdjustmentData를 만들어야 한대서 PHAdjustmentData를 만들어줬습니다. 

formatIdentifier와 formatVersion는 아까 본

Optional(<PHContentEditingInput: 0x280832630> mediaType=1/0, creationDate=2019-08-15 12:54:37 +0000, location=1, adjustmentData=<PHAdjustmentData: 0x283c35a40> identifier=com.apple.photo version=1.4 data=0x283c34a20 (278))

이거 같죠!?..그냥 제 Bundle Identifier랑  버전...버전은 걍 1.0으로 넣어주겠음

그럼 이렇게 3단계가 끝이 나게 됩니다. 

 

 

4. PHContentEditingInput이 있으면  PHContentEditingOutput도 있겠죠? PHContentEditingOutput객체를 Initialize하렴. 

PHContentEditingOutput를 만들어줍니다. PHContentEditingOutput은

PHContentEditingInput을 받는 이니셜라이저가 있어요. 응 개꿀

이렇게 만들어줍니다. 

 

 

5. PHContentEditingOutput의 adjustmentData프로퍼티에 너가 방금 만든 PHAdjustmentData를 넣어줘.

 

 

6. 사진 또는 비디오 asset의 경우, 편집된 컨텐츠에 renderedContentURL을 제공해. 

이게 몬 소리인가..봤더니 

데이터를 renderedContentURL에 쓰라는 거였음. 

아 gist 진짜 개귀찮네

 

 

7. 자 이 변경사항을 사진앱에도 적용 해야 할거잖아요? PHAssetChangeRequest를 사용해서 너 사진앱에도 이 변경사항을 commit 하렴₩~

이렇게 해주면 됩니다.

 

자..이제 돌려볼게요

사진을 누르면 갑자기 이런게 뜹니다. 수정을 누르면 오른쪽과 같이 수정된 이미지가 UIImageView에 들어가게 해놨어요.

우리는 PHAssetChangeRequest를 사용해서 원래 Asset에도 변경사항을 적용했기 때문에

사진 앱에 가면

세피아 필터가 들어간 것을 볼 수 있습니다. adjustmentData를 넣어줬기 때문에 당연히!!!!!! 

편집을 눌렀을 시 오른쪽 아래의 복귀가 활성화됩니다. 복귀를 누르면 원본 이미지로 다시 돌아가죠.

아시겠나요!?

최종코드는 github에 올려놨습니다. crash가 좀 잘나는 느낌이어서 guard의 향연이..되어버렸군요.

암튼 에러처리는 알아서 ㅎ

 

⚠️현재 문제점⚠️

인터넷에서 다운받은 이미지..? 암튼 그런거는 괜찮은데, 제가 직접 찍은 이미지 == 용량이 좀 있는 이미지..는

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Adjustment data is too large'

를 뿜으며 crash가 납니다. 이건 어떻게 처리를 해야할지 모르겠어요..ㅠ

 

결론

위에서도 말했지만, 사진앱과 내 앱에서 편집한 사항을 공유(..? 동기화?) 하고 싶을 때 이런식으로 사용하면 될 것 같아요. 그게 아니라면....contentEditingInput을 사용할 이유는 못느끼겠네요.

Asset의 URL을 얻기 위해서 requestContentEditingInput을 많이들 사용하시잖아요!?

딱히 그 용도 빼고는...별로 쓸 일이 없을 것 같군요.

 

혹시 틀린 내용이 있다면 댓글로 알려주시면 감사하겠습니당

반응형

'iOS' 카테고리의 다른 글

iOS ) Share Extension (1)  (4) 2020.06.10
iOS ) UIKey  (0) 2020.05.16
iOS ) CIFilter 사용해보기  (1) 2020.05.01
Line graph animation  (1) 2020.04.23
UIBezierPath (8) - line graph  (0) 2020.04.22