Notice
Recent Posts
Recent Comments
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 |
Tags
- 리팩토링
- rxswift
- tableView
- 리펙터링
- SWIFT
- 리펙토링
- combine
- UITextView
- uiscrollview
- Human interface guide
- collectionview
- 스위프트
- UICollectionView
- swiftUI
- clean architecture
- Xcode
- ribs
- uitableview
- swift documentation
- RxCocoa
- map
- ios
- Protocol
- Refactoring
- MVVM
- 애니메이션
- Observable
- Clean Code
- HIG
- 클린 코드
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - SwiftUI] 2. 위젯 Widget 사용 방법 - API 데이터 로드와 위젯UI 업데이트 본문
iOS 응용 (SwiftUI)
[iOS - SwiftUI] 2. 위젯 Widget 사용 방법 - API 데이터 로드와 위젯UI 업데이트
jake-kim 2022. 10. 2. 22:491. 위젯 Widget 사용 방법 - WidgetKit, WidgetFamily
2. 위젯 Widget 사용 방법 - API 데이터 로드와 위젯UI 업데이트
3. 위젯 Widget 사용 방법 - 위젯 딥링크 구현 방법 (widgetURL)
4. 위젯 Widget 사용 방법 - 위젯 이미지 로드 방법
5. 위젯 Widget 사용 방법 - Provisioning Profile 등록 (WidgetExtension)
Widget에 표출할 API 준비
- 텍스트를 불러오는 API
- url
https://meowfacts.herokuapp.com/?count=1
- response
{
"data":[
"The way you treat kittens in the early stages of it's life will render it's personality traits later in life."
]
}
- URLSession을 통한 호출
private func getTexts(completion: @escaping ([String]) -> ()) {
// https://github.com/wh-iterabb-it/meowfacts
guard
let url = URL(string: "https://meowfacts.herokuapp.com/?count=1")
else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let data = data,
let textModel = try? JSONDecoder().decode(TextModel.self, from: data)
else { return }
completion(textModel.datas)
}.resume()
}
struct TextModel: Codable {
enum CodingKeys : String, CodingKey {
case datas = "data"
}
let datas: [String]
}
API 로드하여 Widget에 표출하는 방법
- Widget 관련 첫 번째 포스팅 글에서 알아본듯이, Widget Extension 타겟을 추가
- API 관련 모델 추가
- SimpleEntry는 기존에 있는 모델이므로 여기에 texts 프로퍼티 추가
// MyWidget.swift
struct TextModel: Codable {
enum CodingKeys : String, CodingKey {
case datas = "data"
}
let datas: [String]
}
struct SimpleEntry: TimelineEntry {
let date: Date
let texts: [String]
}
- API 조회 메소드 추가
- getTexts(completion:)
struct Provider: IntentTimelineProvider {
...
private func getTexts(completion: @escaping ([String]) -> ()) {
guard
let url = URL(string: "https://meowfacts.herokuapp.com/?count=1")
else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let data = data,
let textModel = try? JSONDecoder().decode(TextModel.self, from: data)
else { return }
completion(textModel.datas)
}.resume()
}
}
- @main에서 title, description 수정
- configurationDisplayName()
- description()
@main
struct MyWidget: Widget {
let kind: String = "MyWidget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
MyWidgetEntryView(entry: entry)
}
.configurationDisplayName("위젯 예제")
.description("랜덤 텍스트를 불러오는 위젯 예제입니다")
}
}
- UI가 보여질 MyWidgetEntryView 구현
struct MyWidgetEntryView : View {
var entry: Provider.Entry
private var randomColor: Color {
Color(
red: .random(in: 0...1),
green: .random(in: 0...1),
blue: .random(in: 0...1)
)
}
var body: some View {
ZStack {
randomColor.opacity(0.7)
ForEach(entry.texts, id: \.hashValue) { text in
LazyVStack { // Widget은 스크롤이 안되므로, List지원 x (대신 VStack 사용)
Text(text)
.foregroundColor(Color.white)
.lineLimit(1)
Divider()
}
}
}
}
}
Provider 구현
- 위젯의 데이터를 언제 불러오고 언제 refresh 결정하는 Widget의 핵심
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
// TODO
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
// TODO
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// TODO
}
// 예제 텍스트를 불러올 API
private func getTexts(completion: @escaping ([String]) -> ()) {
// https://github.com/wh-iterabb-it/meowfacts
guard
let url = URL(string: "https://meowfacts.herokuapp.com/?count=1")
else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let data = data,
let textModel = try? JSONDecoder().decode(TextModel.self, from: data)
else { return }
completion(textModel.datas)
}.resume()
}
}
- Provider에서는 SimpleEntry 모델이 자주 등장
- 언제(date), 무엇(texts)를 표출할것인지 명시
struct SimpleEntry: TimelineEntry {
let date: Date
let texts: [String]
}
- placeholder(in:)
- 데이터를 불러오기 전에 표출될 placeholder
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), texts: ["Empty"])
}
- getSnapshot(for:in:completion:)
- 데이터 로드 담당 메소드
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
getTexts { texts in
let entry = SimpleEntry(date: Date(), texts: texts)
completion(entry)
}
}
- getTimeline(for:in:completion:)
- 데이터를 언제 리프레시 할지 결정
- 지금으로부터 3분후마다 리프레시
- 데이터를 언제 리프레시 할지 결정
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
getTexts { texts in
let currentDate = Date()
let entry = SimpleEntry(date: currentDate, texts: texts)
let nextRefresh = Calendar.current.date(byAdding: .minute, value: 3, to: currentDate)!
let timeline = Timeline(entries: [entry], policy: .after(nextRefresh))
completion(timeline)
}
}
구현 완료)
'iOS 응용 (SwiftUI)' 카테고리의 다른 글
Comments