위젯은 만들때 두가지 형태로 만들수있어요
static형식과 intent형식이 있죠
2021.07.06 - [iyOmSd/Title: SwiftUI] - [SwiftUI] Widget 위젯만들기
이름에서도 느껴지듯 static은 그냥 보여주기만하는 정적인 위젯이에요
위젯 타임라인에 의해서 일정주기로 업데이트되거나 특정API로 위젯을 새로고침해서
보여주는 방식이죠
하지만 오늘 해볼것은
intent 형식이에요
intent형식은 위젯에 동적으로 값을 선택할 수 있고
사용자와 상호작용이 가능한 특성이 있어요
intent 체크박스를 클릭하면 intent형식의 위젯을 생성할 수 있어요
static과는 다르게
.intentdefinition파일이 생성되는걸 볼 수 있어요
위젯설정파일 같은곳인데
여기서 필요한 파라미터를 설정할 수 있어요
string, bool, 사용자정의 enum값 등등 원하는 값으로 설정할 수 있어요
위젯을 롱클릭하면 뜨는 저런 설정창에 보이게하려면
프로퍼티를 추가하고 프로퍼티속성에
Configurable에 있는 user can edit value in shortcuts, widgets 체크박스를 설정해야
롱클릭시 위젯에대한 프로퍼티를 수정 할수 있도록 보여줘요
이렇게 추가한 속성들을 컨트롤해야 동적으로 위젯을 설정할 수 있겟죠?
handler와 관련된 클래스는 엑스코드에서 자동으로 생성돼요
처음으로 위젯을 생성하면 Configuration이라는 이름으로 생성되고 이름을 변경할 수 있어요
(Configuration이름)Intent 형식으로 생성돼있어요
위젯에서 정의한 프로퍼티에 접근할때는
기본구현함수에 있는 configuration에 접근해서 해당 프로퍼티를 읽으면 사용할 수 있어요
Intent Handler 정의하기
추가적인 기능처리를위해서 IntentHandler를 새로 추가할수 있어요
widget을 생성하듯이
file > new > target에서
intents extension을 생성해주세요
새로운 디랙토리와 함께
INExtension를 상속받은 클래스가 생성될거에요
위젯설정파일에서 방금추가한 handler타겟을 추가해주세요
handler는 동적인 옵션을 처리할 때 유용하게 사용할 수 있어요
Dynamic Options에 체크표시를하면 사용할 수 있어요
모든 타입에서 사용할 순 없고 옵션이 가능한 타입에서만 가능해요
Dynamic Options에 체크표시하면
IntentHandling프로토콜에 해당 프로퍼티를 동적으로 컨트롤할 수 있도록 함수가 자동으로 생성되요
IntentHandling프로토콜은
건든게없다면 디폴트는 ConfigurationIntentHandling 이거일거에요
위에서 정의한 (Configuration의 이름)IntentHandling 타입으로 생성되요
testArray라는 이름이라면
provideTestArrayOptionsCollection 이렇게 함수가 생성되네요
class IntentHandler: INExtension, ConfigurationIntentHandling {
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
func provideTestArrayOptionsCollection(for intent: ConfigurationIntent) async throws -> INObjectCollection<NSString> {
var items: [NSString] = []
items.append("1")
items.append("12")
items.append("123")
items.append("1234")
return INObjectCollection(items: items)
}
}
이렇게 아이템 혹은 섹션을 이용한 아이템을 만들어주면
위젯에서 이렇게 리스트형식으로 사용할 수 있어요
업데이트 시점
Intent 위젯의 업데이트 시점은
getTimeline에 정의한 시간간격 혹은 Intent가 프로퍼티가 변경되는 시점에 위젯이 업데이트되요
예시
앞서 만든 위젯설정을 적용하기위해 간단한 예시를 만들어볼까요
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 1 ..< 10 {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset * 30, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
위젯을 건들지않는다면 30초간격으로 업데이트가 일어나도록 해놨어요
struct LockScreenWidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
ZStack {
selectedColor(with: entry.configuration)
VStack(alignment: .leading) {
Text("time: \(timeString(entry.date))")
Text("selected:\n\(entry.configuration.testSelected ?? 0)")
Text("enum:\n \(selectedColorString(with: entry.configuration))")
}
}
}
private func timeString(_ date: Date) -> String {
let format = DateFormatter()
format.dateFormat = "mm:ss"
return format.string(from: date)
}
private func selectedColor(with configuration: ConfigurationIntent) -> Color {
switch configuration.testEnum {
case .red: return .red
case .blue: return .blue
case .orange: return .orange
default: return .white
}
}
private func selectedColorString(with configuration: ConfigurationIntent) -> String {
switch configuration.testEnum {
case .red: return "빨강"
case .blue: return "파랑"
case .orange: return "주황"
default: return ""
}
}
}
간단하게 위젯의 속성
업데이트된 시점을보기위해 시간이 분:초 가 써있고
selected의 값을보여주고
enum타입으로 컬러를 선택한 결과에맞게 위젯색을 변경하는거에요
위에서 위젯을 건들지않는다면 30초간격으로 업데이트가 일어나도록 했지만
속성을 건든다면 바로 위젯이 업데이트되서
분초가 바뀌는걸 볼 수 있을거에요