VesselWheel

ActivityKit & WidgetKit 본문

Xcode Study

ActivityKit & WidgetKit

JasonYang 2024. 3. 30. 12:14

https://developer.apple.com/videos/play/wwdc2023/10184

 

Meet ActivityKit - WWDC23 - Videos - Apple Developer

Live Activities are a glanceable way for someone to keep track of the progress of a task within your app. We'll teach you how you can...

developer.apple.com

https://developer.apple.com/documentation/widgetkit/

 

WidgetKit | Apple Developer Documentation

Extend the reach of your app by creating widgets, watch complications, and Live Activities.

developer.apple.com

https://developer.apple.com/wwdc22/10050

 

Complications and widgets: Reloaded - WWDC22 - Videos - Apple Developer

Our widgets code-along returns as we adventure onto the watchOS and iOS Lock Screen. Learn about the latest improvements to WidgetKit...

developer.apple.com

 

https://gyuios.tistory.com/226

 

WWDC22) Complications and widgets: Reloaded

Complications and widgets: Reloaded - WWDC22 - Videos - Apple Developer 본 글은 WWDC 를 보고, 번역 및 요약 그리고 실행해보는 스터디 프로젝트의 일환입니다. 내용 watchOS Lock Screen 과 complications 로 액세서리 위젯

gyuios.tistory.com

widgetkit에 대한 설명 블로그

widgetkit의 공식문서 예시 

https://developer.apple.com/documentation/widgetkit/emoji-rangers-supporting-live-activities-interactivity-and-animations

 

Emoji Rangers: Supporting Live Activities, interactivity, and animations | Apple Developer Documentation

Offer Live Activities, animate data updates, and add interactivity to widgets.

developer.apple.com


더보기
//
//  RunItWidget.swift
//  RunItWidget
//
//  Created by Jason Yang on 4/11/24.
//

import WidgetKit
import SwiftUI
// struct Provider의 정체
// 위젯을 업데이트 할 시기를 WidgetKit에 알리는 역할
// SimpleEntry를 포함하여, 본격적으로 위젯에 표시될 placeholder, 데이터를 가져와서 표출해주는 getSnapshot, 타임라인 설정 관련된 getTimeLine이 존재
struct Provider: AppIntentTimelineProvider {
    // 데이터를 불러오기 전(getSnapshot)에 보여줄 placeholder
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(),  // *TimelineEntry를 준수하는 구조체, *TimelineEntry: 위젯을 표시할 Date를 정하고, 그 Data에 표시할 데이터를 나타냄
                    configuration: ConfigurationAppIntent())
    }

    // 위젯 갤러리에서 위젯을 고를 때 보이는 샘플 데이터를 보여줄때 해당 메소드 호출
    // API를 통해서 데이터를 fetch하여 보여줄때 딜레이가 있는 경우 여기서 샘플 데이터를 하드코딩해서 보여주는 작업도 가능
    // context.isPreview가 true인 경우 위젯 갤러리에 위젯이 표출되는 상태
    
    func snapshot(for configuration: ConfigurationAppIntent, in context: Context) async -> SimpleEntry {
        SimpleEntry(date: Date(), configuration: configuration)
    }
    
    // 홈화면에 있는 위젯을 언제 업데이트 시킬것인지 구현하는 부분
    func timeline(for configuration: ConfigurationAppIntent, in context: Context) async -> Timeline<SimpleEntry> {
        var entries: [SimpleEntry] = []

        // Generate a timeline consisting of five entries an hour apart, starting from the current date.
        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            // 1시간뒤, 2시간뒤, ... 4시간뒤 entry 값으로 업데이트 하라는 코드
            let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate, configuration: configuration)
            entries.append(entry)
        }

        // (4시간뒤에 다시 타임라인을 새로 다시 불러옴)
        return Timeline(entries: entries, policy: .atEnd)
        // .atEnd: 마지막 date가 끝난 후 타임라인 reloading
        // .after: 다음 data가 지난 후 타임라인 reloading
        // .never: 즉시 타임라인 reloading
    }

    func recommendations() -> [AppIntentRecommendation<ConfigurationAppIntent>] {
        // Create an array with all the preconfigured widgets to show.
        [AppIntentRecommendation(intent: ConfigurationAppIntent(), description: "Example Widget")]
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let configuration: ConfigurationAppIntent
}

struct RunItWidgetEntryView : View {
    @Environment(\.widgetFamily) var family: WidgetFamily
    var entry: Provider.Entry

    var body: some View {
        VStack {
            HStack {
                Text("Time:")
                Text(entry.date, style: .time)
            }
        
            Text("Favorite Emoji:")
            Text(entry.configuration.favoriteEmoji)
        }
    }
}

@main
struct RunItWidget: Widget {
    let kind: String = "RunItWidget"
    
    // body 안에 사용하는 Configuration
    // IntentConfiguration: 사용자가 위젯에서 Edit을 통해 위젯에 보여지는 내용 변경이 가능
    // StaticConfiguration: 사용자가 변경 불가능한 정적 데이터 표출

    var body: some WidgetConfiguration {
        AppIntentConfiguration(
            kind: kind,
            intent: ConfigurationAppIntent.self, // 사용자가 설정하는 컨피그
            provider: Provider()  // 위젯 생성자 (타이밍 설정도 가능)
        ) { entry in  // 위젯에 표출될 뷰
            RunItWidgetEntryView(entry: entry)
                .containerBackground(.fill.tertiary, for: .widget)
        }
    }
}

extension ConfigurationAppIntent {
    fileprivate static var smiley: ConfigurationAppIntent {
        let intent = ConfigurationAppIntent()
        intent.favoriteEmoji = "😀"
        return intent
    }
    
    fileprivate static var starEyes: ConfigurationAppIntent {
        let intent = ConfigurationAppIntent()
        intent.favoriteEmoji = "🤩"
        return intent
    }
}

#Preview(as: .accessoryRectangular) {
    RunItWidget()
} timeline: {
    SimpleEntry(date: .now, configuration: .smiley)
    SimpleEntry(date: .now, configuration: .starEyes)
}

코드 설명

더보기

**RunItWidget 코드 설명**

이 코드는 SwiftUI를 사용하여 iOS 위젯을 만드는 방법을 보여줍니다. 위젯은 사용자의 홈 화면에 작은 정보 조각을 제공하며, 이 코드는 위젯의 기본 구조와 기능을 설명합니다. 📱

---

### Provider 구조체
- **역할**: 위젯의 데이터를 관리하고, 위젯이 언제 업데이트될지 WidgetKit에 알립니다.
- **주요 메소드**:
  - `placeholder`: 데이터 로딩 전에 임시로 보여줄 내용을 정의합니다.
  - `snapshot`: 위젯 갤러리에서 샘플 데이터를 보여줄 때 사용합니다. 실제 데이터 로딩에 딜레이가 있을 때 샘플 데이터를 표시할 수 있습니다.
  - `timeline`: 위젯의 업데이트 타이밍을 결정합니다. 여기서는 현재 시간부터 시작하여 1시간 간격으로 5개의 엔트리를 생성하고, 마지막 엔트리 이후에 타임라인을 다시 로딩합니다.

### SimpleEntry 구조체
- **목적**: 위젯에 표시될 데이터를 정의합니다.
- **특징**: `TimelineEntry` 프로토콜을 준수하며, 위젯에 표시될 날짜와 설정을 포함합니다.

### RunItWidgetEntryView 구조체
- **기능**: 위젯의 UI를 정의합니다.
- **디자인**: 사용자가 선택한 이모지와 현재 시간을 표시합니다.

### RunItWidget 구조체
- **설정**: 위젯의 메인 구조를 정의합니다.
- **Configuration 타입**:
  - `AppIntentConfiguration`: 사용자가 위젯의 내용을 변경할 수 있게 해주는 설정입니다.
  - `Provider`: 위젯의 데이터와 업데이트 타이밍을 관리합니다.

### ConfigurationAppIntent 확장
- **목적**: 사용자가 위젯에서 선택할 수 있는 이모지를 미리 설정합니다.
- **예시**: "😀"와 "🤩" 이모지를 선택할 수 있게 해줍니다.

---

이 코드는 SwiftUI와 WidgetKit을 사용하여 사용자 정의 가능한 iOS 위젯을 만드는 방법을 보여줍니다. 위젯을 통해 사용자는 자신의 홈 화면에서 유용한 정보를 빠르게 확인할 수 있습니다. 더 자세한 정보는 [Apple Developer 문서](https://developer.apple.com/tutorials/swiftui-concepts/exploring-the-structure-of-a-swiftui-app)에서 확인할 수 있습니다. 📚

위젯 개발에 관한 더 궁금한 점이 있다면 언제든지 물어보세요! 😊 

이런 자료를 참고했어요.
[1] Apple Developer - Exploring the structure of a SwiftUI app (https://developer.apple.com/tutorials/swiftui-concepts/exploring-the-structure-of-a-swiftui-app)
[2] Apple Developer - Creating and combining views — SwiftUI Tutorials (https://developer.apple.com/tutorials/swiftui/creating-and-combining-views)