일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- app intents
- widgetkit
- backend
- Firebase
- watchkit
- Project
- swift concurrency
- Complication
- UITableView
- Flutter
- spring
- Sendbird
- task.yield()
- SwiftUI
- Coding Test
- WWDC22
- fcm
- coreml
- UIStackView
- github
- Delegate Pattern
- Apple Developer Academy
- ios
- 코테
- Swift
- cloud functions
- UIDatePicker
- createml
- tabman
- Tuist
- Today
- Total
azhy의 iOS 이야기
[iOS] WatchKit[5] - 예시를 통해 Complication 알아보기 본문
2022년 8월 8일에 작성됨
제가 진행했던 코드들을 보면서 Complication을 어떻게 핸들링하는지 한번 알아보도록 하겠습니다! 앞에 글을 안 보고 오셨으면 이해를 하기 어려울 수 있으니 꼭 한 번씩 읽어보시고 오세요!
Watch와 Complication 데이터 공유
데이터를 보여주지않고 앱 아이콘이나 사진 같은걸 Complication에 보여주면 넘어가셔도 됩니다.
// InterfaceController
//
class DayInfo {
static let shared = DayInfo()
var days: String?
private init() { }
}
class InterfaceController: WKInterfaceController, WCSessionDelegate {
...
override func willActivate() {
...
DayInfo.shared.days = data
...
}
...
}
이 방법이 정확하지는 않을 수도 있지만, 저는 InterfaceController에서 싱글톤을 이용해 데이터를 세팅하고 ComplicationController에서 이 데이터를 이용해서 세팅하니 정상적으로 데이터가 나왔습니다. 더 좋은 방법이 있으시면 댓글 부탁드려요!
Complication Assets
WatchKit Extension - Assets 에 들어가 보면
요렇게 생긴 친구들이 있습니다. 저도 사용해보지는 않았습니다만 예상해 보면 CLKComplicationFamily에 맞춘 이미지를 넣으면 해당 Complication에 이미지가 나오지 않을까 예상해 봅니다.
예를 들면 앱 아이콘 이미지가 될 수 있겠네요. 이미지를 사용하실 분들은 여기다가 워치 사이즈에 맞게 이미지를 넣어주시면 될 거 같습니다.
ComplicationController
Watch를 추가하고 ComplicationController를 처음 딱 열어보면 많은 메서드들이 반겨줍니다. 하나씩 알아보도록 하겠습니다.
getComplicationDescriptors(handler:)
ClockKit은 이 메서드를 호출하여 앱이 지원하는 컴플리케이션을 결정합니다. 여기서 중요한 게 바로 지원하는 CLKComplicationFamily 선택할 수 있습니다.
func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) {
let descriptors = [
CLKComplicationDescriptor(identifier: "complication", displayName: "너랑나랑",
supportedFamilies: [
CLKComplicationFamily.modularSmall, CLKComplicationFamily.circularSmall, CLKComplicationFamily.graphicCircular])
]
handler(descriptors)
}
supportedFamilies 배열에 본인이 원하는 family 종류를 넣어주시면 됩니다. 만약 모든 케이스를 넣고 싶으시면 .allCases를 넣어주시면 됩니다.
getTimelineEndDate(for:withHandler:)
이 메서드는 업데이트할 날짜를 지정해야 합니다. 이걸 구현하지 않으면 ClockKit은 현재 항목 이후를 업데이트하지 않는다고 합니다.
func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
handler(Date().addingTimeInterval(60.0 * 30.0)) // 30분..
}
추가로 컴플리케이션을 백그라운드로 새로 고침을 막 계속할 수는 없습니다. 애플이 막아놨거든요. WKApplicationRefreshBackgroundTask를 보시면 "컴플리케이션과 함께 각 앱에 대해 시간당 네 가지 작업을 수행합니다. 현재 시계 페이스의 모든 컴플리케이션은 이 예산을 공유합니다. 예산이 소진되면 더 많은 시간을 사용할 수 있을 때까지 시스템에서 요청을 연기합니다."라고 적혀있네요.
remainingComplicationUserInfoTransfers에는 "컴플리케이션이 활성 워치 페이스에 있는 경우 하루에 50번의 전송이 제공됩니다."라고 적혀있습니다. 사실 컴플리케이션을 초나 분 단위로 업데이트하는 일은 거의 없을 거라고 보지만 참고하시길 바랍니다!
getPrivacyBehavior(for:withHandler:)
ClockKit은 이 메서드를 호출하여 사용자의 Apple Watch가 잠겨 있을 때 정보 표시 데이터를 표시하는 방법을 결정합니다. 손목을 올리고 내릴 때를 핸들링하는 메서드인 거 같습니다. 이 친구도 딱히 건드리지는 않았네요.
func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
handler(.showOnLockScreen)
}
getTimelineEntries(for:after:limit:withHandler:), getTimelineEntries(for:before:limit:withHandler:)
앱의 미래 데이터, 과거 데이터로 타임라인 항목의 배열을 빌드합니다.라고 적혀있습니다만.. 잘 모르겠네요.. 심지어 애플 공식 예제 파일에도 handler(nil)로 되어있습니다. 이 친구들에 대해 잘 아시는 분은 댓글 부탁드릴게요!
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
handler(nil)
}
func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
handler(nil)
}
getLocalizableSampleTemplate(for:withHandler:)
컴플리케이션의 샘플 데이터를 표시해 줍니다.
저렇게 미리 보기 화면에서 어떻게 컴플리케이션이 나타날지 보여주는 메서드입니다. placeholder랑 비슷한 느낌이라고 하면 이해가 편하실 겁니다.
func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
switch complication.family {
case .modularSmall:
let tallBody = CLKComplicationTemplateModularSmallStackImage(line1ImageProvider: CLKImageProvider(onePieceImage: (UIImage(systemName: "heart")?.withTintColor(appMainColorAlaph40))!), line2TextProvider: CLKTextProvider(format: "days"))
handler(tallBody)
break
case .circularSmall:
let tallBody = CLKComplicationTemplateCircularSmallStackImage(line1ImageProvider: CLKImageProvider(onePieceImage: (UIImage(systemName: "heart")?.withTintColor(appMainColorAlaph40))!), line2TextProvider: CLKTextProvider(format: "days"))
handler(tallBody)
break
case .graphicCircular:
let tallBody = CLKComplicationTemplateGraphicCircularStackImage(line1ImageProvider: CLKFullColorImageProvider(fullColorImage: (UIImage(systemName: "heart")?.withTintColor(appMainColorAlaph40))!), line2TextProvider: CLKTextProvider(format: "days"))
handler(tallBody)
break
default:
handler(nil)
break
}
}
위에서 설정한 CLKComplicationFamily 종류대로 전부 다 세팅을 해주셔야 합니다.
getCurrentTimelineEntry(for:withHandler:)
이 메서드가 메인입니다. 지금 표시하는 데이터를 가지고 컴플리케이션에 보여주는 메서드입니다.
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
var value = ""
switch complication.family {
case .modularSmall:
let tallBody = CLKComplicationTemplateModularSmallStackImage(line1ImageProvider: CLKImageProvider(onePieceImage: (UIImage(systemName: "heart")?.withTintColor(appMainColorAlaph40))!), line2TextProvider: CLKTextProvider(format: DayInfo.shared.days == nil ? "days" : "\(value)"))
let entry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: tallBody)
handler(entry)
break
case .circularSmall:
let tallBody = CLKComplicationTemplateCircularSmallStackImage(line1ImageProvider: CLKImageProvider(onePieceImage: (UIImage(systemName: "heart")?.withTintColor(appMainColorAlaph40))!), line2TextProvider: CLKTextProvider(format: DayInfo.shared.days == nil ? "days" : "\(value)"))
let entry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: tallBody)
handler(entry)
break
case .graphicCircular:
let tallBody = CLKComplicationTemplateGraphicCircularStackImage(line1ImageProvider: CLKFullColorImageProvider(fullColorImage: (UIImage(systemName: "heart")?.withTintColor(appMainColorAlaph40))!), line2TextProvider: CLKTextProvider(format: DayInfo.shared.days == nil ? "days" : "\(value)"))
let entry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: tallBody)
handler(entry)
break
default:
handler(nil)
break
}
}
결과
글 정리한다고 공식 문서에 들어가 보니 거의 다 Deprecated가 떠있네요.. watchOS 9 기준으로 대대적인 변화가 있을 거 같습니다. 그래도 버전 적용해서 작업하려면 시간이 꽤 걸릴 거 같긴 하네요. 이렇게 제가 작업한 내용들을 가지고 watch와 complication에 대해 정리를 한번 해봤습니다. 전부 다 정답이 아닐 수 있습니다.. 제가 몰랐던 부분이나 틀린 부분은 댓글로 달아주시면 수정하겠습니다!
'iOS' 카테고리의 다른 글
[iOS] 앱 강제 업데이트 (1) | 2024.11.13 |
---|---|
[iOS] 세 번째 앱 출시 후기 (1) | 2024.11.13 |
[iOS] WatchKit[4] - Complication 살펴보기 (0) | 2024.11.13 |
[iOS] WatchKit[3] - 예시를 통해 Watch Connectivity 알아보기, 주의사항 (0) | 2024.11.13 |
[iOS] WatchKit[2] - Watch Connectivity, 앱이랑 데이터 주고받기 (3) | 2024.11.13 |