티스토리 뷰
[1] iOS App과 WatchKit Extension 사이의 관계
WatchApp도 위젯처럼 Shared Container를 이용하여 간단히 앱과 워치 사이의 데이터를 공유할 수 있을 줄 알았으나,,,
(참고: App과 Extension간 UserDefaults 공유하기 )
Watch는 이 방법말고 Watch Connectivity 라는 framework를 사용해서
iOS App과 paired watchOS app 사이의 two-way communication을 구현해줘야한다고 합니다.
그 이유는 다음과 같습니다.
WatchOS 1에서는
iOS App과 Watchkit Extension이 둘다 아이폰 안에 있었으며 data store를 공유했습니다.
하지만 WatchOS 2부터는 WatchKit Extension을 Watch로 옮겼고
각각의 data store를 가지게 되었습니다.
이제 이 그림처럼 App과 AppExtension의 개념이 아니므로
Shared Container를 사용할 수 없는 것이죠,,,
[2] Watch Connectivity Framework
Watch Connectivity Framework에 대해서 알아보겠습니다.
이 Framework를 사용하여서 iOS app과 paired WatchOS app의 WatchKit extension 는 data transfer를 할 수 있습니다.
그리고 이 Framework를 이용해서 WatchOS app의 complication의 업데이트를 trigger 할 수도 있습니다.
앱에서 transter를 초기화 한 후부터는, 시스템이 data 전송에 대한 모든 책임을 집니다.
대부분의 transfer는 receiving app이 inactive인 상태일 때 background에서 일어납니다.
app이 깨어나면, inactive 상태였을 때 도착한 데이터들을 노티받게 됩니다.
두 app이 모두 active 상태일 때, 실시간 통신(Live communication)도 가능합니다.
[2.1] Initiate transfers between your iOS app and watchOS app
communication 하기 전에 먼저 초기화 과정이 필요합니다.
iOS app과 watchOS app 둘다 WCSession object를 create & configure 해야합니다.
session object를 configure하고 active 시킨 후, 메세지를 보내거나 연결 상태에 대한 정보를 얻으려고 시도할 수 있습니다.
또한 session을 활성화하기 전에 isSupported() 메소드를 통해
현재 디바이스가 Watch Connectivity framework를 사용할 수 있는 지 알 수 있습니다.
위에서 말한 과정을 아래의 코드로 해줄 수 있습니다.
session을 만들고 delegate 를 assign 해줍니다.
그리고 activate() 메소드를 불러 session을 활성화시켜줍니다.
WatchKit extension과 iOS app 에 모두 각각의 session을 configure 해줘야합니다.
예제를 보면 iOS app은 AppDelegate > didFinishLaunching에서 해줬고
WatchKit Extension은
ExtensionDelegate의 init에서 해줬네요
그리고 info.plist에 WKExtensionDelegateClassName을 추가해준 것을 볼 수 있습니다.
두 session object가 active되면, 두 프로세스는 즉시 커뮤니케이션을 할 수 있습니다.
하나의 session만 active 되었을 때는 active session이 계속 update를 보내고 file을 전송할 수 있지만
이 전송은 background에서 기회적으로(opportunistically) 수행됩니다.
(아래의 설명을 보면 이해가 갑니다)
[2.2] Communicating with the Counterpart App
이제 초기화과정이 끝났으니 커뮤니케이션을 어떻게 하는 지 알아봅시다.
그 전에 먼저 문서에서 계속 언급되는 sessionActivationState를 살펴봅시다.
WCSessionActivationState 는 session의 현재 activation state를 말하며 notActivated / inactive / activate 세가지가 있습니다.
제가 이해하기로는
- notActivated : 세션이 비활성화인 상태. 아무런 커뮤니케이션도 할 수 없음
- inactive: 세션 활성화되었지만, 비활성화상태로 전환 중.. session delegate는 이 상태에서 데이터를 받기는 가능하지만, 상대방 앱으로 data를 보낼 수는 없음 (받기 가능 / 보내기 불가능)
- activate: 받기 / 보내기 모두 가능!
# Send
나의 activationState가 activated여야지만 상대방에게 데이터를 전송할 수 있습니다.
iOS App은 watch app으로 데이터를 전송하기 전에 isPaired 랑 isWatchAppInstalled 프로퍼티를 체크하세요
+
iOS 9.3 이후부터는 하나 이상의 애플워치(watchOS 2.2 이후)와 페어링가능합니다.
multiple Apple Watch를 지원하는 경우 주의사항도 문서에 있습니다
# 1.
상대방에게 최근 상태 정보를 전달하려면
updateApplicationContext(_:) 메소드를 사용하세요
상대방이 깨어나면 이 정보를 사용하여 자신의 상태를 업데이트 할 수도 있습니다.
# 2.
iOS app과 WatchKit extension 사이의 즉각적인 커뮤니케이션을 가능하게 해주는 메소드는 아래 두개가 있습니다.
- sendMessage(_:replyHandler:errorHandler:)
- sendMessageData(_:replyHandler:errorHandler:)
(참고로 isReachable 프로퍼티가 true여야지 메소드들이 성공합니다)
# 3.
background에서 dictionary를 전달하고 싶으면
transferUserInfo(_:) 를 쓰면 되고
background에서 file을 전달하고 싶으면
transferFile(_:metadata:) 를 쓰면 됩니다.
# 4.
iOS 앱이 Wath app의 complicaton에게 데이터를 보내고 싶으면
transferCurrentComplicationUserInfo(_:) 를 쓰면 됩니다.
# 5.
상대방에게 메세지를 보낼 때, background message는 queue에 배치되고 순서대로 전달됩니다.
한편 아래 세개 메소드를 통해 보내진 데이터는 더 높은 우선순위를 가지며 즉시 전송됩니다.
sendMessage(_:replyHandler:errorHandler:),
sendMessageData(_:replyHandler:errorHandler:),
transferCurrentComplicationUserInfo(_:)
앱에서 받은 모든 메세지는 background thread에서 session delegate에게 연속적으로 전달됩니다.
# Receive
WCSessionDelegate 의 메소드들을 통해 message를 Receive 할 수 있습니다.
[ 주의사항 ]
- Receive: func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:])
이 두개가 한 세트인데, 시뮬레이터말고 실기기에서만 테스트해볼 수 있다고 합니다,,🥲
그리고 reloadComplicationDescriptors 에 있는 내용도 주의해주세요!
이미 watch face에 present 되고 있는 complication을 data source에서 제거한 경우,
ClockKit은 해당 compication을 계속 보여주고 계속 새로운 timeline entries를 요청합니다.
하지만 사용자가 new watch face에서 compication을 편집할 때 해당 complication을 추가할 수는 없습니다.
=> datasource에서 지우고 reload해도 기존 워치 페이스에 있는 complication은 지워지지 않는다!! 대신 새로운 Watch Face에서는 지운 complication이 안나온다!!
[ Reference ]
- 개발문서: https://developer.apple.com/documentation/watchconnectivity
- 애플 예제 프로젝트: Using Watch Connectivity to Communicate Between Your Apple Watch App and iPhone App
- WWDC:
WWDC 2015 - Introducing Watch Connectivity
WWDC 2020 - Create complications for Apple Watch
- 추천 아티클: https://betterprogramming.pub/get-started-with-watch-connectivity-with-swiftui-51722324b6f6
'🍏 > WatchOS' 카테고리의 다른 글
[WatchOS] Complication Family & Templates (0) | 2021.06.11 |
---|
- Total
- Today
- Yesterday
- Flutter Spacer
- DRF APIException
- ipad multitasking
- drf custom error
- flutter build mode
- Flutter getter setter
- github actions
- Django Firebase Cloud Messaging
- ribs
- SerializerMethodField
- 구글 Geocoding API
- PencilKit
- Flutter Text Gradient
- flutter dynamic link
- Django FCM
- flutter 앱 출시
- Dart Factory
- Python Type Hint
- Django Heroku Scheduler
- Sketch 누끼
- Watch App for iOS App vs Watch App
- 장고 Custom Management Command
- Flutter 로딩
- 플러터 얼럿
- cocoapod
- METAL
- 장고 URL querystring
- Flutter Clipboard
- 플러터 싱글톤
- flutter deep link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |