[WWDC21] Add intelligence to your widgets
Add intelligence to your widgets - WWDC 2021 - Videos - Apple Developer
Widget intelligence overview
intelligence.. 사전적 의미는 지능, 기밀, 정보입니다. 아직은 정확히 뭘 뜻하는지는 모르겠네요. 느낌에 정보같긴한데..
Smart Rotate
- Automatically scrolls to a widget in a Smart Stack
- Uses relevance signals from the widget
- Uses behavioral patterns learned from app usage
위젯 써보시면, 여러 개 겹쳐서 위젯 스택을 만들 수 있는거 아시죠? 그 위젯 스택이 알아서 rotate 되도록 해주는게 Smart Rotate라고 하네요..
저는 그냥 시간 초 지나면 자동으로 rotate 해주는 거라고 생각했는데, 이게 글쎄 사용자의 동작 패턴을 학습한다고 하네요… 🤔 체감은 안드는데 그렇다고 합니다.
보시는 것과 같이, 시간 별로 알아서 뜬다고 하네요… 근데 애플에서 제공하는 앱 말고 다른 앱의 위젯들도 뜰런지는 모르겠어요..
일단 뭐 아침에는 날씨가 뜨고, 일정 관리에 따라 미팅에 잡혀져 있을 경우엔 미리 알림이 스택에 나타나는 형태입니다. 이런 것만 봤을 땐 User의 행동패턴을 학습했다기 보단 state의 변화가 있거나, 일정이 가까운 것 먼저 보여주는 식인거 같은데.. 이건 어디까지나 저의 생각입니다.
Widget Suggestions
- Inserts a new widget into a Smart Stack
- Uses relevance signals from the app
- Uses behavioral patterns learned from app usage
iOS 15에선 Widget Suggestions라는게 생겼다고 합니다. 직역하자면, 사용자가 위젯을 발견하고 안전하고 예방적인 위젯에 대한 정보를 받을 수 있다? 라고 하는데, 아마도 위젯 스택에 자동으로 추가되는 거겠죠?
또한, Smart Rotate가 사용자 행동 패턴을 학습해서 Widget Suggestions이 가능하다고 합니다.
위젯에 대한 예시입니다. 보시는 바와 같이 스택에 2개의 위젯이 있습니다.
이 경우, 일정관리 위젯이 없어도 일정이 있는 경우, 위젯에 자동으로 일정관리 위젯이 추가된다고 합니다. 그리고 더 이상 관련이 없어진다면, 시스템이 위젯을 스택에서 제거합니다.
그래서 이 기능이 불러오는 효과는 사용자 입장에선 있는지도 모르는 위젯의 존재를 알게 되는 것에 도움을 줄 수 있다고 합니다… 좋은건가… 모르고 못쓰는 것보단 좋겠네요…🤷♂️
흠.. 너무 이상적인데, 위젯의 종류가 정말 많은데 진짜 이게 이상적으로 추가, 삭제가 가능할지는 직접 써봐야 알 것 같습니다.
Provide timely, glanceable information with obvious value to the user
이 새로운 Widget Suggestions의 핵심인 듯 합니다. 시기적절하게 분명한 가치를 가진 알기쉬운 정보를 user에게 제공하자!! 그렇게 하기위한 3가지 방법이 있다고 합니다.
- INRelevantShortcut
- 이 값은 donate해서 Widget Suggestions를 생성하는 시기를 알릴 수 있습니다.
- TimelineEntryRelevance
- relevance score를 제공해서 위젯이 스택에 있을 때 Smart Rotation을 활성화할 수 있습니다.
- INInteraction
- 구성 의도를 donate하면 시스템 사용자의 동작패턴을 학습하여 Smart Rotate, Smart Suggestions에 모두 쓰일 수 있습니다.
여기서의 donate라는 말은 기부한다고 해석한다기보단, 제공한다 정도로 생각해야 될 것 같습니다. 잘하는 영어는 아니라서 틀렸다면 지적해주세요..
INRelevantShortcut
- Donated from an app to tell the system to insert a widget into a stack
- Specifies time-based or behavioral relevance
- Supports both static and intent-configured widgets
요약하자면, 스택에 추가 시키기 위한 값인가봐요.. 행동 패턴에 따라 삽입 시기를 결정하고, static widget이랑 intent-configured widget에서 둘다 사용 가능하다고 합니다.
Donating INRelevantShortcut
- Set the array of relevant shortcuts in the default store
- Update donated relevant shortcuts by donating a new array
- Invalidate a relevant shortcut by ommitting it from a newly donated array
- Donations with an intent can surface the intent on the Siri watch face
INRelevantShortcut을 array를 만들어서 관리하나봐요. 역시 이렇게 말로만 서술되어 있는 건 직관적이지 않네요.. 얼른 코드 나와라..
INRelevanceProvider
- Use INDateRelevanceProvider for known time periods of relevance
- Use no providers to tell the system to suggest based on behavioral pattens
- Other relevance providers support only the Siri watch face
WidgetKit을 써보면 알 수 있는데 Widget에서 Provider를 사용해서 일정 주기마다 원하는 데이터를 가공해서 Widget에 넘겨줍니다. 뇌피셜인데 Provider를 상속받아서 추가적인 기능을 하는 protocol이겠죠.
예정된 이벤트나 속보 같은 관련 기간(period)의 시작 및 종료 날짜를 제공합니다.
여러 provider를 사용하여 둘 이상의 관련 기간을 지정할 수 있다고 합니다. (..? 역시 말로는 너무 어렵네요..)
시스템은 사용자가 위젯의 앱을 사용하고 있을 때, 사용하는 시기를 기준으로 Widget Suggestions을 한다고 합니다.
9분 14초 - Donate INRelevantShortcuts for Widget Suggestions
// Donate INRelevantShortcut for Widget Suggestions in app
// User has just made a purchase
var relevantShortcuts: [INRelevantShortcut] = []
let intent = ViewRecentPurchasesIntent()
intent.card = Card(identifier: card.identifier)
intent.category = .all
if let shortcut = INShortcut(intent: intent) {
let relevantShortcut = INRelevantShortcut(shortcut: shortcut)
relevantShortcut.shortcutRole = .information
relevantShortcut.widgetKind = “CardRecentPurchasesWidget”
let dateProvider = INDateRelevanceProvider(start: Date(),
end: Date(timeIntervalSinceNow: 1800))
relevantShortcut.relevanceProviders = [dateProvider]
relevantShortcuts.append(relevantShortcut)
}
INRelevantShortcutStore.default.setRelevantShortcuts(relevantShortcuts) { (error) in
if let error = error {
print("Failed to set relevant shortcuts. \(error))")
} else {
print("Relevant shortcuts set.")
}
}
코드를 보니 말로만 듣던거보단 훨씬 나아진 것 같아요.
이 코드는 주석에도 나와있듯이 사용자가 구매를 했을 때 실행되는 로직인데, 여기서 유효 기간을 설정하고 INRelevantShortcutStore에 저장하는 방식인 것 같아요.
위에서 생각했던 INDateRelevanceProvider가 위젯 코드에서 쓰는 Provider를 상속받아서 만든거라고 생각했었는데, 이걸보니 조금 다른 것 같네요..
Widget Suggestion을 제어하는게 Widget 코드에서 제어하는 게 아니라 App 코드에서 제어하는게 좀 새롭게 느껴집니다.
만약에 저렇게 어떤 이벤트가 발생했을 때 shortcut array가 제공되는 거라면 충분히 사용성이 좋을 것 같은데요??
TimelineEntryRelevance
- Indication on a widget’s timeline entry about its worthiness of rotation
- Relative to all other timeline entries provided by the widget
꼭 이걸로 생성해!! 이런느낌이 아니라 옵셔널이네요. relevance struct는 보시는 바와 같이 score랑 duration이라는 프로퍼티를 가지고 있습니다. score는 다른 entry와 비교되기 위한 값입니다.
다른 위젯의 score보다 더 높은 값이 rotate 됩니다.
duration은 얼마나 이 score의 값이 유효한지에 대한 기간을 나타냅니다. duration이 지나면, 시스템은 score를 0으로 설정합니다.
12분 35초 - Adopting TimelineEntryRelevance for Smart Rotate
// Appending TimelineEntryRelevance to a TimelineEntry in widget extension for Smart Rotate
struct CardRecentPurchasesEntry: TimelineEntry {
let date: Date
let relevance: TimelineEntryRelevance?
let card: IntentCard?
let category: PurchaseCategory
}
let relevance = TimelineEntryRelevance(score: 16.29, duration: 1800)
let entry = CardRecentPurchasesEntry(date: Date(), relevance: relevance, card: card,
category: category)
card나 category는 데이터 타입을 새로 추가시킨 겁니다.
Entry 자체가 이제 위젯에 제공되는 데이터 타입이라고 보시면 될 듯 한데, relevance를 옵셔널하게 추가시켜서 rotate될 항목을 score 기준으로 entry끼리 비교해서 선정하는 것 같아요..
살짝 이해가 안가는게 entry끼리 비교하면… 음.. 뭐가 달라지나 싶네요.. 같은 위젯에서 보여지는 entry에 대한 중요도?를 설정해서 score가 높은 entry를 우선적으로 보여줍니다.
이게 예시인데요.. 같은 위젯에서 구매 금액이 큰 내역을 우선적으로 보여주고 있습니다. 기준은 개발자가 설정하기 나름이라서 여러 상황에서 적용해볼 수 있을 것 같습니다.
만약에 score 값이 같다면 최근 entry 값을 보여준다고 합니다.
InInteraction
- App donation when the user views information
- Data point for the system’s behavioral model
- Predicted by the system using user’s patterns
- Enables suggestions for a configured widget
어.. 영상 화질이 좀 안좋아서 살짝 흐릿하게 나오네요… 아무튼 앱을 사용할 때 InInteraction이 쌓이고, 이게 즉, 행동 패턴을 분석하는 모델에 제공되는 형태입니다.
17분 01초 - Donate INIntents through INInteraction for Widget Suggestions and Smart Rotations
// Donate INIntent in a card's purchases list in the app
.onAppear {
let intent = ViewRecentPurchasesIntent()
intent.card = Card(identifier: card.id.uuidString, displayString: card.name)
intent.category = .all
let interaction = INInteraction(intent: intent, response: nil)
interaction.donate { error in
if let error = error {
print(error.localizedDescription)
}
}
}
생성한 Intent에 값을 넣어주고 Intent로 INIntercation을 생성한 다음 donate해주는 모습입니다. Intent를 쓰는 위젯을 아직 써보지 않아서 이 코드가 정확히 어디에서 쓰여지는지는 잘 모르겠습니다… 🥲
학습이 좀 더 필요한 부분.. 여기서 말하기로는 onAppear 즉, 앱이 보여지는 시점부터 donate 된다고 하네요..
근데 앱이 보이는 동안 계속 donate하는지는 잘 모르겠네요.. 아마도 처음 Appear될 때만 되는거겠죠?
onAppear 말고도 lock screen, Spotlight, siri suggestion widget에서도 donate될 수 있다고 하네요.