[SwiftUI] 위젯 추가하기

RudinP·2025년 9월 3일
0

Study

목록 보기
352/363

1. APP Config에서 위젯 extension 추가

  • 선택 등 상호작용이 필요하다면 Include Configuration App Intent 체크

2. Entry 구조체 구현

  • WidgetKit 사용
  • TimelineEntry 프로퍼티를 채택해야 함
  • Date가 필수 속성
import Foundation
import WidgetKit

struct WeatherEntry: TimelineEntry {
    let widgetData: WidgetData
    
    var date: Date {
        widgetData.date
    }
}

3. Provider 구현

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> WeatherEntry {
        WeatherEntry(widgetData: .preview)
    }

    func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> ()) {
        let entry =  WeatherEntry(widgetData: .preview)
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> ()) {
        var entries = [WeatherEntry(widgetData: .preview)]
        
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }

//    func relevances() async -> WidgetRelevances<Void> {
//        // Generate a list containing the contexts this widget is relevant in.
//    }
}

4. Widget 관련 모디파이어

struct WeatherAppWidget: Widget {
    let kind: String = "WeatherAppWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            if #available(iOS 17.0, *) {
                WeatherEntryView(entry: entry)
                    .containerBackground(.fill.tertiary, for: .widget)
            } else {
                WeatherEntryView(entry: entry)
                    .padding()
                    .background()
            }
        }
        .configurationDisplayName("날씨 위젯")
        .description("위젯 설명은 여기에 들어갑니다.")
        .supportedFamilies([.systemSmall])
    }
}

  • configurationDisplayName: My Widget 부분에 뜨는 이름

  • description: 제목 아래 설명

  • supportedFamilies: 지원되는 위젯의 크기 종류

    Target Membership

  • 파일 추가 시 접근할 수 있는 범위를 지정할 수 있다.

  • 위젯과 본 앱 모두 접근 가능한 파일이려면 체크해야함.

프리뷰에서 보이게 하기

1. View파일의 프리뷰에 context 추가

struct WeatherEntryView_Previews: PreviewProvider {
    static var previews: some View {
        WeatherEntryView(entry: Provider.Entry(widgetData: .preview))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}

2. containerBackground 추가

    var body: some View {
        if #available(iOSApplicationExtension 17.0, *) {
            ZStack {
                LinearGradient(colors: [
                    Color(red: 4/255, green: 7/255, blue: 24/255),
                    Color(red: 39/255, green: 54/255, blue: 80/255)
                ], startPoint: .topTrailing, endPoint: .bottomLeading)
            }
            .containerBackground(.fill.tertiary, for: .widget)

3. 여백을 없애기 위한 코드 widget 파일에 추가

struct WeatherAppWidget: Widget {
    let kind: String = "WeatherAppWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            if #available(iOS 17.0, *) {
                WeatherEntryView(entry: entry)
                    .containerBackground(.fill.tertiary, for: .widget)
            } else {
                WeatherEntryView(entry: entry)
                    .padding()
                    .background()
            }
        }
        .configurationDisplayName("날씨 위젯")
        .description("위젯 설명은 여기에 들어갑니다.")
        .supportedFamilies([.systemSmall])
        //아래 부분 추가
        .contentMarginsDisabled()
        .containerBackgroundRemovable(false)
    }
}

위젯과 앱간 데이터 공유 방법

1. signing&capabilities 에서 +Capability 통해 App groups 추가

  • 이름은 group. 뒤에 기존 signing 붙이기

2. 위젯데이터 관리하는 파일에서 JSON으로 데이터 공유 코드 작성하기

  1. FileManager extension으로 방금 추가한 앱그룹 사인 url을 sharedContainerURL로 등록해주기
extension FileManager {
    static var sharedContainerURL: URL {
        return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "여기사이닝")!
    }
}
  1. 위젯데이터 관리하는 파일에서 write, read하는 코드를 위의 url로 작성하기

즉, 파일을 작성,읽음으로서 데이터를 공유

위젯 리로드하기

앱에서 새로운 데이터를 받았을 때 write를 하면서 reload 하기

WidgetCenter.shared.reloadAllTimelines()
  • 위젯의 Provider쪽의 getTimeLine 메소드 호출
profile
iOS 개발자가 되기 위한 스터디룸...

0개의 댓글