iOS 카메라 개발기 - 잠금 화면과 제어센터에서 켜지는 카메라
인텐트만 만들면 제어센터에 뜰 줄 알았는데 진입점마다 필요한 게 달랐다. 컨트롤 익스텐션이 31MB가 된 이유와, 앱을 지워야만 바뀌던 아이콘까지.
egg2분 읽기
iOS 18부터 서드파티 카메라 앱도 잠금 화면, 제어센터, 카메라 컨트롤 버튼에서 켤 수 있다. 기본 카메라처럼 주머니에서 꺼내자마자 찍으려면 이게 있어야 한다.
지난 편까지는 앱 안 이야기였고 이번은 앱 밖이다. 확인한 환경은 iPhone 17 Pro, iOS 26.6.1이다.
진입점마다 필요한 게 다르다
CameraCaptureIntent 하나만 만들면 여기저기 다 뜰 줄 알았다. 아니었다. 정리하면 이렇다.
| 진입 | 필요한 것 |
|---|---|
| 잠금 해제 상태, 카메라 컨트롤 버튼 | CameraCaptureIntent |
| 잠금 상태, 카메라 컨트롤 버튼 | Capture Extension(LockedCameraCapture) |
| 제어센터·잠금 화면 컨트롤·액션 버튼 | 위젯 익스텐션의 ControlWidget |
인텐트만 있으면 목록에 오르는 곳은 설정 → 카메라 → 카메라 컨트롤 하나뿐이다. 제어센터에 올리려면 ControlWidget이 따로 필요하다.
다행히 연결은 간단하다. CameraCaptureIntent는 ControlWidgetButton(action:)에 그대로 들어간다. 잠겨 있으면 캡처 익스텐션으로, 풀려 있으면 앱으로 보내는 분기는 시스템이 한다.
ControlWidget은 자체로 main()이 있어서 WidgetBundle 없이 @main을 바로 붙일 수 있다. 컨트롤 하나뿐인 위젯 익스텐션이면 번들을 만들 필요가 없다.
캡처 익스텐션에서 안 되는 것들
잠금 상태에서 뜨는 캡처 익스텐션은 할 수 있는 게 적다. App Group도 네트워크도 안 되고 컨테이너는 익스텐션이 내려갈 때 지워진다.
앱 설정은 appContext로 넘기는데 크기가 4KB다. 넘길 설정은 4KB 안에 들어가게 줄여야 한다.
PhotoKit 저장은 익스텐션에서 직접 된다. 앱으로 넘겨야 하는 파일은 sessionContentURL에 둔다. 익스텐션에서 끝낼 수 없는 일은 시스템에 잠금 해제를 맡기고 NSUserActivity로 목적지를 넘긴다.
그리고 AVCaptureEventInteraction이 붙은 카메라 뷰가 없으면 익스텐션이 곧 종료된다. 빈 화면으로 먼저 띄워보려 하면 바로 여기에 걸린다.
확장점 id com.apple.securecapture는 문서에서 못 찾았다. Xcode 템플릿(Capture Extension.xctemplate) 안에 있다. 템플릿 없이 손으로 타깃을 만들 거라면 거기서 가져와야 한다.
인텐트 파일 하나가 31MB를 끌고 왔다
인텐트 선언 파일은 앱, 캡처 익스텐션, 컨트롤 익스텐션 세 타깃에 같이 들어가야 한다. 그런데 이 파일이 앱 쪽 타입을 하나 참조하고 있었다.
그 하나 때문에 컨트롤 익스텐션이 앱 전체를 끌고 왔다. 560KB가 31MB가 됐다…
세 타깃이 같이 쓰는 파일이라면 아무것도 참조하지 않는 편이 안전한 것 같다.
컨트롤 글리프는 커스텀 SF 심볼만 된다
컨트롤 아이콘으로 PDF나 PNG를 주면 제어센터에 물음표가 뜬다. 커스텀 SF 심볼만 받는다.
심볼도 제약이 있다. 단색으로 납작해지면서 fill-opacity가 1.0이 된다. 색도 불투명도도 못 쓴다. 선(stroke) 대신 채운 도형(evenodd)으로 그린다.
심볼 템플릿이 맞는지는 문서보다 actool이 정확했다. 최소로 통과하는 구성은 Guides의 Baseline/Capline에 Regular-S/M/L 세 개였다.
xcrun actool <x>.xcassets --compile <out> --platform iphoneos \
--minimum-deployment-target 18.0 --output-partial-info-plist <p>
<out> 디렉터리는 미리 만들어둬야 한다. 없으면 실패한다.
크기는 시스템 심볼(circle.circle)과 나란히 렌더해서 맞췄다. 캡 높이의 1.13배로 그리면 옆에 놓았을 때 왜소했고 1.45배가 맞았다.
아이콘은 앱을 지워야 바뀐다
글리프를 고치고 덮어쓰기로 설치했는데 제어센터 갤러리에는 계속 옛 물음표가 떴다. 이상한 건 잠금 화면에 올려둔 같은 컨트롤은 새 글리프로 그려졌다는 것이다.
에셋이 잘못됐다고 의심하면서 반나절을 날렸다. 앱을 삭제하고 다시 설치하니 바로 바뀌었다. 갤러리 아이콘은 덮어쓰기 설치로는 갱신되지 않는다.
컨트롤 이름에 앱 이름을 넣지 않는다
갤러리와 타일은 컨트롤 이름 옆에 앱 이름을 알아서 붙인다. “앱명 카메라”라고 지으면 “앱명 앱명 카메라”로 보인다.
이번 편에서 제일 아까운 건 반나절이다. 에셋을 고치기 전에 앱부터 지워봤으면 10분이면 끝났을 것 같다.
다음 편이 이 연재의 마지막이다. 환경 설정에서 걸린 것들과, 이 모든 걸 겪고 나서 바꾼 검증 습관을 적는다.
Filed under 개발