Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WidgetKitで良い体験を作るには / Good experience with Wid...

Tatsuya Tanaka
September 19, 2021

WidgetKitで良い体験を作るには / Good experience with WidgetKit

Tatsuya Tanaka

September 19, 2021
Tweet

More Decks by Tatsuya Tanaka

Other Decks in Programming

Transcript

  1. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ాத ୡ໵

    / ͨͳͨͭ • Ϡϑʔגࣜձࣾ ɹɾiOSΞϓϦͷԣஅత։ൃ΍ٕज़త՝୊ͷղܾ @tattn @tanakasan2525 @tattn
  2. ©︎ 2021 Yahoo Japan Corporation All rights reserved. iOS 14͔ΒϗʔϜը໘ͳͲʹ΢ΟδΣοτ͕ઃஔՄೳʹ

    ΞϓϦΛ։͔ͳͯ͘΋ΞϓϦͷػೳͷҰ෦ΛఏڙͰ͖Δ IUUQTBCPVUZBIPPDPKQQSSFMFBTFC
  3. ©︎ 2021 Yahoo Japan Corporation All rights reserved. WidgetKit ΢ΟδΣοτΛ࡞੒͢Δʹ͸WidgetKitϑϨʔϜϫʔΫΛ࢖͏

    ΢ΟδΣοτͷUI͸SwiftUIͰ࡞Δ @main struct WidgetExtension: Widget { let kind: String = "CatWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in WidgetEntryView(entry: entry) } .configurationDisplayName("ೣ΢ΟδΣοτ") .description("ೣͷࣸਅ͕ϥϯμϜͰ੾ΓସΘΔ΢ΟδΣοτ") } }
  4. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ઃఆͷ͋Δ΢ΟδΣοτͱͳ͍΢ΟδΣοτ StaticCon

    fi guration ̎छྨͷઃఆ͕͋Γɺݸผઃఆͷ͋Δͳ͠ʹΑͬͯ࢖͍෼͚Δ
  5. ©︎ 2021 Yahoo Japan Corporation All rights reserved. Timeline ΢ΟδΣοτͷࣗಈߋ৽͸ࣄલʹઃఆͨ͠TimelineʹΑͬͯߦΘΕΔ

    8:00 10:00 12:00 14:00 16:00 18:00 20:00 Timeline ※SwiftUIͷ@State౳Ͱͷߋ৽͸Ͱ͖ͳ͍
  6. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ߴ͍ස౓Ͱͷߋ৽͸Ͱ͖ͳ͍ ΢ΟδΣοτͷߋ৽ස౓ʹ͸੍ݶ͕͋Γɺຖඵߋ৽͸Ͱ͖ͳ͍

    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF ※Entryؒ͸5෼ִؒҎ্Λਪ঑
  7. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ΢ΟδΣοτͷ༧ࢉ ֤΢ΟδΣοτʹ͸༧ࢉ͕͋Γɺ༧ࢉΛ࢖༻ͯ͠Ϧϩʔυ͞ΕΔ

    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF ߋ৽ ༧ࢉ: X ༧ࢉ: X - a ίετ (a)
  8. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ΢ΟδΣοτͷ༧ࢉ ֤΢ΟδΣοτʹ͸༧ࢉ͕͋Γɺ༧ࢉΛ࢖༻ͯ͠Ϧϩʔυ͞ΕΔ

    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF ߋ৽ ༧ࢉ: X ༧ࢉ: X - a ίετ (a) ༧ࢉ͕ͳ͘ͳΔ (X - a < 0) ৔߹͸΢ΟδΣοτΛߋ৽Ͱ͖ͳ͍ 
 ༧ࢉ͸24࣌ؒͰϦηοτ͞ΕΔ
  9. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ΢ΟδΣοτͷ༧ࢉ ༧ࢉ͸֤΢ΟδΣοτ͝ͱʹҟͳΓɺར༻ঢ়گʹΑܾͬͯ·Δ

    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF ༧ࢉ: X ʹ ໿40ʙ70ճ/day → ໿15ʙ30෼ִؒͷϦϩʔυ͕ݶք Α͘දࣔ͞ΕΔ΢ΟδΣοτͷ৔߹
  10. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ΢ΟδΣοτͷ༧ࢉର৅֎ ҎԼͷ৔߹ʹ͸༧ࢉΛ࢖ΘͣʹϦϩʔυͰ͖Δ

    IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF ɾΞϓϦຊମ͕ϑΥΞάϥ΢ϯυ࣌ ɾΞϓϦຊମͰԻָ࠶ੜத΍Ґஔ৘ใऔಘத ɾγεςϜʹΑΔߋ৽ ɹɾ୺຤ͷݴޠมߋ࣌ ɹɾDynamicType΍Accessibilityͷઃఆมߋ࣌ ɹɾσʔλ͕ݹ͍Մೳੑͷ͋Δ΢ΟδΣοτͷදࣔ࣌
  11. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ڊେͳσʔλΛѻ͏΢ΟδΣοτ ɾຊମΞϓϦͰ࢖͍ͬͯΔڊେͳWeb

    APIΛෳ਺૊Έ߹Θͤͯѻ͏ ɾຊମΞϓϦͰ࡞੒ͨ͠ڊେͳอଘσʔλΛಡΈࠐΉ ྫ͑͹
  12. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ΢ΟδΣοτʹඞཁͳσʔλ͚ͩΛѻ͓͏ ɾ΢ΟδΣοτ༻ʹσʔλྔͷগͳ͍Web

    APIΛ༻ҙ͢Δ ɾ΢ΟδΣοτ༻ʹ੾Γग़ͨ͠σʔλΛอଘͯͦ͠ΕΛಡΈࠐΉ ΢ΟδΣοτ͸ϝϞϦ੍ݶ͕ݫ͍͠ (࠷େ30MB) IUUQTEFWFMPQFSBQQMFDPNGPSVNTUISFBE ※࣮ػͰಈ͔͢ͱྫ֎ʹͳΔ ޻෉͕ඞཁ
  13. ©︎ 2021 Yahoo Japan Corporation All rights reserved. όοΫάϥ΢ϯυηογϣϯ ࣌ؒͷ͔͔Δ௨৴΍ѱ͍௨৴؀ڥ౳Λαϙʔτ͢ΔͨΊʹ

    
 όοΫάϥ΢ϯυ௨৴΋׆༻Ͱ͖Δ @main struct WidgetExtension: Widget { private let kind = "CatWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in CatWidget(entry: entry) } .onBackgroundURLSessionEvents(matching: "get_huge_data") { identifier, completion in BackgroundFetcher.shared.completion = completion BackgroundFetcher.shared.restoreURLSessionIfNeeded() } .configurationDisplayName("ೣ΢ΟδΣοτ") .description("ೣͷࣸਅ͕ϥϯμϜͰ੾ΓସΘΔ΢ΟδΣοτ") } }
  14. final class BackgroundFetcher: NSObject, URLSessionDownloadDelegate { static let shared =

    BackgroundFetcher() var completion: (() -> Void)? private lazy var session: URLSession = { let config = URLSessionConfiguration.background(withIdentifier: "get_huge_data") config.isDiscretionary = true // ిݯ઀ଓத΍WiFi઀ଓதͳͲͷྑ͍λΠϛϯάͰDL return URLSession(configuration: config, delegate: self, delegateQueue: nil) }() func restoreURLSessionIfNeeded() { _ = session } // getTimeline౳͔Βݺͼग़͢ func setDownloadSchedule(completion: (() -> Void)? = nil) { session.getTasksWithCompletionHandler { _, _, downloadTasks in defer { completion?() } guard downloadTasks.isEmpty else { return } let task = Self.shared.session.downloadTask(with: URL(string: "https://****")!) task.earliestBeginDate = <࣍ͷϦϩʔυλΠϛϯάΑΓલʹઃఆ> task.countOfBytesClientExpectsToSend = 500 task.countOfBytesClientExpectsToReceive = 8 * 1024 * 1024 task.resume() } } func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { // DLͨ͠σʔλΛDocumentsσΟϨΫτϦͳͲʹҠಈͯ͠ޙ͔ΒऔಘͰ͖ΔΑ͏ʹ͢Δ } func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { completion?() completion = nil WidgetCenter.shared.reloadTimelines(ofKind: "CatWidget") } } ɾσʔλΛࣄલDL͢ΔͱಡΈࠐΈ଴ͪΛ࡟ݮͰ͖Δ 
 ɾϦτϥΠॲཧ౳ͰΑΓ࣮֬ʹϑΣονͰ͖Δ
  15. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ద੾ͳߋ৽࣮૷Λ͠Α͏ ΢ΟδΣοτʹ͓͍ͯେ੾ͳͷ͸৘ใͷߋ৽

    ͨͩ͠ɺա౓ͳߋ৽͸௨৴ྔ΍όοςϦʔফඅɺαʔόʔෛՙʹؔΘΔ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF
  16. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ద੾ͳߋ৽࣮૷Λ͠Α͏ ɾEntry

    
 ɹɹɾͰ͖Δ͚ͩઌ·Ͱઃఆ͢Δ 
 ɹɹɾEntry͸ִؒΛ௕Ίʹ (࠷௿5෼ִؒҎ্) 
 
 ɾϦϩʔυϙϦγʔ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOXJEHFULJULFFQJOHBXJEHFUVQUPEBUF ΢ΟδΣοτʹ͓͍ͯେ੾ͳͷ͸৘ใͷߋ৽ ͨͩ͠ɺա౓ͳߋ৽͸௨৴ྔ΍όοςϦʔফඅɺαʔόʔෛՙʹؔΘΔ
  17. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (atEnd)

    .atEnd 6:00 12:00 19:00 6:00 12:00 19:00 6:00 Timelineʹ͋ΔEntryΛॱʹදࣔ͢Δ ࠷ޙͷEntry͕දࣔ͞ΕΔͱϦϩʔυϑϥά͕ONʹͳΔ Timeline
  18. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (atEnd)

    .atEnd 6:00 12:00 19:00 6:00 12:00 19:00 6:00 Timeline γεςϜʹΑͬͯࣗಈతʹϦϩʔυ͕࣮ߦ͞ΕΔ 
 ͨͩ͠ɺਖ਼֬ͳ࣌ࠁʹϦϩʔυ͞ΕΔΘ͚Ͱ͸ͳ͍
  19. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (atEnd)

    .atEnd 6:00 12:00 19:00 6:00 12:00 19:00 6:00 Timeline γεςϜʹΑͬͯࣗಈతʹϦϩʔυ͕࣮ߦ͞ΕΔ 
 ͨͩ͠ɺਖ਼֬ͳ࣌ࠁʹϦϩʔυ͞ΕΔΘ͚Ͱ͸ͳ͍
  20. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (atEnd)

    .atEnd 6:00 12:00 19:00 6:00 12:00 19:00 6:00 Timeline γεςϜʹΑͬͯࣗಈతʹϦϩʔυ͕࣮ߦ͞ΕΔ 
 ͨͩ͠ɺਖ਼֬ͳ࣌ࠁʹϦϩʔυ͞ΕΔΘ͚Ͱ͸ͳ͍
  21. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (atEnd)

    .atEnd 6:00 12:00 19:00 6:00 12:00 19:00 6:00 ɾະདྷͷ಺༰͕༧ଌͰ͖Δ΋ͷ ɾ࣌ؒܦաʹΑͬͯؔ࿈ੑ΍ਖ਼֬ੑ͕ࣦΘΕʹ͍͘΋ͷ Timeline ༻్
  22. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (afterDate)

    .afterDate ࢦఆͨ࣌ؒ͠ʹߋ৽͞ΕΔ Timeline 6:00 19:00 12:00 19:00 6:00 12:00
  23. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (afterDate)

    .afterDate Timeline 6:00 19:00 12:00 19:00 6:00 12:00 let nextDate = [6, 12, 19].compactMap { calendar.nextDate(after: Date(), matching: .init(hour: $0, minute: 0), matchingPolicy: .nextTime) } .min()! let timeline = Timeline(entries: entries, policy: .after(nextDate))
  24. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (afterDate)

    .afterDate Timeline 6:00 12:00 19:00 12:00 19:00 6:00 αʔόʔ΁ͷϦΫΤετ͕ूத͢ΔͨΊɺ 
 ཚ਺౳Ͱߋ৽λΠϛϯάΛ෼ࢄͤͨ͞΄͏͕ྑ͍
  25. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (afterDate)

    .afterDate Timeline 6:00 12:00 19:00 12:00 19:00 6:00 αʔόʔ΁ͷϦΫΤετ͕ूத͢ΔͨΊɺ 
 ཚ਺౳Ͱߋ৽λΠϛϯάΛ෼ࢄͤͨ͞΄͏͕ྑ͍
  26. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (afterDate)

    .afterDate ස౓ߴ͘ߋ৽ͯ͠͠·͏ͱ༧ࢉ͕ͳ͘ͳΓɺ 
 ϦϩʔυͰ͖ͳ͘ͳΔͷͰ஫ҙ Timeline 6:00 12:00 19:00 12:00 19:00 6:00
  27. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (afterDate)

    .afterDate Timeline 6:00 12:00 19:00 12:00 19:00 6:00 ɾະདྷͷ಺༰͕༧ଌͰ͖ͳ͍΋ͷ ɾਫ਼౓΍ؔ࿈ੑ͕࣌ؒʹΑͬͯมԽ͢Δ΋ͷ ༻్
  28. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (never)

    reloadTimelines .never ϦϩʔυAPIΛΞϓϦ͔Βݺͼग़͢͜ͱͰߋ৽Ͱ͖Δ
  29. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ϦϩʔυϙϦγʔ (never)

    reloadTimelines .never ɾΞϓϦͷૢ࡞΍ϓογϡ௨஌౳Λى఺ʹߋ৽͢Δ΋ͷ ༻్
  30. ©︎ 2021 Yahoo Japan Corporation All rights reserved. Human Interface

    GuidelinesΛ֬ೝ͠Α͏ ɾΞϓϦͷϝΠϯػೳʹؔ࿈ͨ͠৘ใΛఏڙ͢Δ ɾΞϓϦΛىಈ͢Δ͚ͩͷ΢ΟδΣοτ͸ආ͚Δ ɾҰ೔Λ௨ͯ͠มԽ͢Δίϯςϯπ͕͓͢͢Ί ɾΠϯλϥΫγϣϯ෦෼͸গͳΊʹ ɾϑΥϯτ͸SF ProɺαΠζ͸11ptҎ্ਪ঑ IUUQTEFWFMPQFSBQQMFDPNEFTJHOIVNBOJOUFSGBDFHVJEFMJOFTXJEHFUTPWFSWJFXJOUSPEVDUJPO ͔ͳΓ۩ମతʹࢦ਑͕ࣔ͞Ε͍ͯΔ
  31. ©︎ 2021 Yahoo Japan Corporation All rights reserved. Ϋϥογϡ΍λΠϜΞ΢τʹىҼ͍ͯ͠Δ͜ͱ͕ଟ͍ Image(uiImage:

    UIImage(data: try! Data(contentsOf: .imageURL))!) .resizable() .scaledToFill() ௨৴౳ͷ஗ԆͳͲͰgetTimeline͕λΠϜΞ΢τͨ͠Γɺ 
 ࣮૷ͷ໰୊౳ͰΫϥογϡͨ͠Γ͢Δͱൃੜ͢Δ ΦϑϥΠϯ࣌ʹΫϥογϡͯ͠͠·͏ʂ 
 Data(contentsOf:_)͸஗͍௨৴؀ڥͷ৔߹ɺ 
 ਺ेඵεϨουΛࢭΊͯ͠·͍ɺϓϩηε͕མͱ͞Εͯ͠·͏͜ͱ΋... IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOGPVOEBUJPOOTEBUBJOJU
  32. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ΤϥʔϋϯυϦϯά͸େࣄ ΢ΟδΣοτ͸Ϣʔβʔʹ࢖͍ํΛઆ໌͠ʹ͍͘

    جຊ͸ઃஔ͢Δ͚ͩͰಈ͘Α͏ʹ͠ɺ 
 ਖ਼͘͠ಈ͍͍ͯͳ͍࣌͸ݪҼΛ఻͑ΒΕΔ࣮૷ʹ͠·͠ΐ͏ ɾઃఆ͕଍Γͳ͍or௨৴Τϥʔ౳ͷ৔߹͸ 
 ɹঢ়گ͝ͱʹద੾ͳରॲํ๏·ͨ͸ݪҼΛදࣔ͢Δ ɾData(contentsOf:_)͸Ͱ͖Δ͚ͩආ͚ͯɺgetTimeline౳Ͱ 
 ɹURLSessionΛ࢖ͬͯϦϞʔτͷը૾౳Λऔಘ͢Δ ಛʹ
  33. ©︎ 2021 Yahoo Japan Corporation All rights reserved. γεςϜͱΞϓϦͷ࿈ܞ ɾεϚʔτϩʔςʔγϣϯ

    ɾ΢ΟδΣοτͷఏҊ ɾϩοΫը໘ͰͷఏҊ ɾεϙοτϥΠτͰͷఏҊ ɾSiriγϣʔτΧοτͷఏҊ ɾQuick Note ࠷ۙ͸γεςϜʹΑΔϨίϝϯυ͕ڧԽ͞Ε͍ͯΔ εϚʔτελοΫ NSUserActivity΍Intents ExtensionͰ࣮૷
  34. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ྑ͍ମݧΛ࡞ΔͨΊʹ͸࢓༷Λཧղ͢Δ͜ͱ͕େࣄ ΢ΟδΣοτ͸ಛʹԼهͷཧղ͕େ੾

    ະ஌ͷ࢓༷͸Ͳ͔͜ͰόάΛੜΈग़͢ ߋ৽ස౓ ϝϞϦ ϦϩʔυϙϦγʔ HIG σβΠϯ͢Δલʹ஌͓͖͍ͬͯͨ
  35. ©︎ 2021 Yahoo Japan Corporation All rights reserved. ࢀߟจݙ ɾKeeping

    a Widget Up To Date 
 ɹɹɾhttps://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date 
 ɾPrinciples of great widgets 
 ɹɹɾhttps://developer.apple.com/videos/play/wwdc2021/10048/ ɾAdd con fi guration and intelligence to your widgets ɹɹɾhttps://developer.apple.com/videos/play/wwdc2020/10194 ɾAdd intelligence to your widgets ɹɹɾhttps://developer.apple.com/videos/play/wwdc2021/10049/ ɾDonate intents and expand your app’s presence ɹɹɾhttps://developer.apple.com/videos/play/wwdc2021/10231 ɾDownloading Files in the Background ɹɹɾhttps://developer.apple.com/documentation/foundation/url_loading_system/downloading_ fi les_in_the_background 
 ɾHuman Interface Guidelines 
 ɹɹɾhttps://developer.apple.com/design/human-interface-guidelines/widgets/overview/introduction/