티스토리 뷰

반응형

[WidgetKit] 위젯만들기 포스팅에서는 StaticConfiguration을 사용하였는데요,

 

 

 

 

 

 

위의 움짤처럼 Edit Widget 기능을 추가해주기 위해 IntentConfiguration을 사용해보겠습니다.

참고로 Making a Configurable Widget 문서를 보고 알게 되었는데, 저렇게 Editable한 위젯을 Configurable Widget이라고 부릅니다-!

 

 

 

우선 Intent가 필요합니다. 

 

Widget extension 타겟으로 SiriKit Intent Definition File을 추가해주세요 (저는 파일이름 WidgetIntents로 해줬습니다.)

 

 

 

 

 

 

 

Intent 파일을 클릭하고 + 눌러서 New Intent 해주세요

 

 

 

 

 

 

 

저는 PRList라고 이름을 지었습니다. 

Intent 카테고리는 View라고 해주세요.

 

그리고 저는 repository에 따른 PR 목록 보여주고 싶어서

파라미터로 repository 추가했어요

 

파란박스 쳐놓은 것 두개 체크해주세요

1) Intent를 위젯에 쓰겠다.

2) 파라미터 value를 위젯에서 수정하겠다.

 

라고 하는 것 체크-!!

 

 

 

 

 

 

이렇게 추가하면 빌드하면 돌려주면~ XCode는 PRListIntent를 알아서 만들어주는데요,

Custom Class 쪽 빨간 화살표를 누르면 볼 수 있어요

 

 

 

 

 

 

 

 

 

 

 

 

이제 Intent에 PRListIntent 넣어주면 됩니다-! 

 

 

 

 

 

그리고 IntentConfiguration에 들어가는 provider는 IntentTimelineProvider 프로토콜을 따르는 instance여야합니다..

PRListProvider는 기존에 TimelineProvider 프로토콜을 따르고 있었는데요, IntentTimelineProvider를 따르게 바꿔줄게요-!! 

 

typealias Intent 해주고 

메소드명만 바꿔주면 되네요 ( getSnapshot(for:in:completion:) 랑 getTimeline(for:in:completion:) method)

import WidgetKit
import Foundation

struct PRListProvider: IntentTimelineProvider {
    
    typealias Intent = PRListIntent
    typealias Entry = PRListEntry
    
    func getSnapshot(for configuration: PRListIntent, in context: Context, completion: @escaping (PRListEntry) -> Void) {
        let pr1 = PullRequest(url: "", state: "", title: "버그 픽스 PR 합니다.", user: User(name: "죠르디", imageUrl: ""), createdDate: "2020-07-06", updatedDate: "2020-07-07")
        let pr2 = PullRequest(url: "", state: "", title: "새로운 피쳐 PR 합니다.", user: User(name: "라이언", imageUrl: ""), createdDate: "2020-07-06", updatedDate: "2020-07-07")
        let entry = Entry(prList: [pr1, pr2])
        completion(entry)
    }
    
    func getTimeline(for configuration: PRListIntent, in context: Context, completion: @escaping (Timeline<PRListEntry>) -> Void) {

        let currentDate = Date()
        // 30분마다 refresh 하겠음
        let refreshDate = Calendar.current.date(byAdding: .minute, value: 30, to: currentDate)!
        
        GithubFetcher.getPulls(owner: "eunjin3786", repo: "MyRepo") { result in
            switch result {
            case .success(let pulls):
                let entry = Entry(date: currentDate, prList: pulls)
                let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
                completion(timeline)
            case .failure:
                let entry = Entry(prList: [PullRequest(url: "", state: "", title: "데이터를 가져올 수 없습니다.", user: User(name: "또르르", imageUrl: ""), createdDate: "로그인을 안한 것 아닐까요..?", updatedDate: "")])
                let entries: [Entry] = [entry]
                let timeline = Timeline(entries: entries, policy: .after(refreshDate))
                completion(timeline)
            }
        }
    }
}


 

이렇게 하고 돌려주면 repository 파라미터가 안나오는 것을 볼 수 있어요

 

 

 

 

 

근데 놀랍게도 indentdefinition파일에 타겟 멤버쉽설정을 widget extension뿐만아니라 

본 앱까지 해주면 파라미터가 잘나옵니다. (이거 좀 더 찾아봐야할듯!! 왜지?!??!?!?!?)

 

 

 

 

 

 

 

 

 

이제 새로운 repository 이름을 입력했을때, 위젯에 해당 repository 목록을 보여주도록 해볼게요-!! 

provider > getTimeline함수에서 configuration의 repository를 가져와서 그것으로 요청해주면 됩니다.

 

struct PRListProvider: IntentTimelineProvider {

    ... 
    
    func getTimeline(for configuration: PRListIntent, in context: Context, completion: @escaping (Timeline<PRListEntry>) -> Void) {

        let repositoryName = configuration.repository ?? ""
        
        let currentDate = Date()
        // 30분마다 refresh 하겠음
        let refreshDate = Calendar.current.date(byAdding: .minute, value: 30, to: currentDate)!
        
        GithubFetcher.getPulls(owner: "eunjin3786", repo: repositoryName) { result in
            switch result {
            case .success(let pulls):
                let entry = Entry(date: currentDate, prList: pulls)
                let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
                completion(timeline)
            case .failure:
                let entry = Entry(prList: [PullRequest(url: "", state: "", title: "데이터를 가져올 수 없습니다.", user: User(name: "또르르", imageUrl: ""), createdDate: "로그인을 안한 것 아닐까요..?", updatedDate: "")])
                let entries: [Entry] = [entry]
                let timeline = Timeline(entries: entries, policy: .after(refreshDate))
                completion(timeline)
            }
        }
    }
}


 

 

그럼 이렇게 repository 이름을 바꿔줄때마다 위젯에 보여주는 PR목록을 갱신해주게 됩니다. 

 

 

 

 

사용자 인풋을 받아서 바로바로 업데이트 되어야하는 Configurable Widget인 경우

입력을 하고 홈으로 돌아올때 timeline 요청을 새로 해주는 것 같습니다.

문서에는 해당 내용을 못찾았지만, refresh 정책과 상관없이 바로바로 위젯을 refresh 시켜주는 것을 볼 수 있기때문입니다.

실제로 timeline 함수에 디버깅 포인트 걸어보면 인풋입력하고 홈 돌아올때마다 계속 디버깅 걸립니다.

(Xcode 버그때문에 widget extension에 디버깅 포인트 안잡힐때가 많아서 한번 더 확인하고 싶었는데, 이제 안잡히네요ㅠㅠ흑)

 

반응형
댓글