Dex (9)
WidgetKit으로 홈 화면에 포켓몬 위젯 표시하기
Widget 만들기
앱을 실행하지 않아도 정보를 확인할 수 있게 하려면 Widget이 필요하다. 이번 글에서는 WidgetKit을 사용해 포켓몬 정보를 아래 사진처럼 홈 화면에서 바로 볼 수 있도록 위젯을 만들어본다.
이것도 역시 전에 공부를 했던 적이 있기에 WidgetKit 지난글을 참고하면 좋을듯하다.
위젯 추가는 이렇게
이때 check는 모두 하지 않는걸로…
늘 그렇듯 Activate
이전에도 이렇게 캡쳐를 했었지만 리마인드할때는 역시 다시한번 캡쳐하는게 좋긴하다.
위의 과정을 거치면 우리를 맞이해주는 귀여운 위젯이 나타난다.
이렇게 기본적인 위젯 생성이 끝났다.
Widget의 핵심 구조
이전에 한번 다뤄봤기에, 이번엔 간단하게 정리.
SwiftUI 기반의 Widget은 다음과 같은 핵심 구성 요소로 이루어져 있다:
구성요소 | 설명 |
---|---|
TimelineProvider | 위젯이 언제, 어떤 데이터를 표시할지 결정함. 업데이트 주기, 데이터 제공 등의 역할 수행 |
TimelineEntry | 실제 위젯에 표시할 데이터 모델. date 는 필수 속성이며, 사용자 정의 속성 추가 가능 |
EntryView | 위젯의 실제 UI 구성 요소. SwiftUI View 형태로 작성 |
Widget | 위젯을 선언하고 시스템에 등록함. 어떤 provider, view, supported size를 사용할지 정의 |
WidgetBundle | 복수 개의 위젯을 한 프로젝트 내에서 묶을 때 사용 |
PreviewProvider | 위젯의 다양한 상태를 Xcode에서 시각적으로 테스트할 수 있도록 지원 |
TimelineProvider의 주요 함수
함수 이름 | 설명 |
---|---|
placeholder(in:) | 위젯이 로드되기 전 잠깐 표시할 자리 표시용 콘텐츠를 반환. 위젯 갤러리 등에서 사용됨 |
getSnapshot(in:completion:) | 위젯의 미리보기에서 사용될 콘텐츠를 반환. 빠른 응답이 중요하며 placeholder와 유사한 데이터 사용 |
getTimeline(in:completion:) | 위젯이 실제 표시할 데이터를 시간 순서대로 반환. 여러 개의 TimelineEntry 를 담아 업데이트 시점을 지정 |
Widget 다듬기
데이터 모델링
1
2
3
4
5
6
struct SimpleEntry: TimelineEntry {
let date: Date
let name: String
let types: [String]
let sprite: Image
}
이렇게 우리가 필요한 데이터들을 모델링 해준다.
코드 수정하기
이제 Provider 부분을 수정해야한다.
모델링을 손봤기 때문에 에러가 발생.
1
2
3
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: .now, name: "bulbasaur", types: ["grass", "poison"], sprite: Image(.bulbasaur))
}
이런식으로 나머지들도 고쳐주면 된다. (그래봤자 Provider 함수부분만 고쳐주면 끝)
Target 추가하기 (Asset, CoreData, PokemonExt, Persistence)
이렇게 코드를 작성하고 보니 이미지가 없다고 에러가 발생
이렇게 Widget을 추가하게되면 Asset도 생기는데, 아무것도 없기 때문.
그러면 또 이미지를 드래그해서 추가해야하나? 그건 아니다.
Target을 추가해주면된다. 현재 이미지 에셋이 Dex 앱 하나에만 적용이 되어있는데, 위젯에서도 사용하기위해 Target을 추가 해주기만 하면 된다.
현재는 Dex 앱 하나에만 타겟이 설정된 상태. +를 눌러 추가해주자.
이렇게 Target에 Wigdet도 추가가 된걸 알 수 있다.
나머지들도 동일한 방법으로 추가해준다. (사진은 생략)
이렇게 하면 이제 Widget에서도 사용이 가능해진다.
Placeholder 만들기
일종의 MockData라고 보면된다.
Preview에서 사용할 데이터이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct SimpleEntry: TimelineEntry {
let date: Date
let name: String
let types: [String]
let sprite: Image
static var placeholder: SimpleEntry {
SimpleEntry(
date: .now,
name: "bulbasaur",
types: ["grass", "poison"],
sprite: Image(.bulbasaur)
)
}
static var placeholder2: SimpleEntry {
SimpleEntry(
date: .now,
name: "mew",
types: ["psychic"],
sprite: Image(.mew)
)
}
}
이렇게 2개를 만들어 주었다.
Placeholder 적용하기
위에서 Provider 쪽에 코드를 작성했던것을 placeholder를 사용하여 바꿔주도록 하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry.placeholder // chagned
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry.placeholder // chagned
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// 생략
let currentDate = Date()
for hourOffset in 0 ..< 5 {
//생략
let entry = SimpleEntry.placeholder // changed
entries.append(entry)
}
//생략
}
이런식으로 바꿔준다.
getSnapshot, getTimeline 부분도 동일하게 수정하자.
이후 Preview에도 적용을 한다.
1
2
3
4
5
6
#Preview(as: .systemSmall) {
DexWidget()
} timeline: {
SimpleEntry.placeholder
SimpleEntry.placeholder2
}
Preview에서 2개를 만들었기에 이렇게 2개를 선택할수 있다.
다음 글에서는 이 데이터를 바탕으로 위젯 디자인을 해볼 예정이다.