Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
iOS 13におけるSiri Shortcuts 最小実装+α
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Maika Yamada
September 21, 2020
1.9k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
iOS 13におけるSiri Shortcuts 最小実装+α
Maika Yamada
September 21, 2020
More Decks by Maika Yamada
See All by Maika Yamada
対話を頑張らなくても作れるSiri Shortcuts向けIntents App Extension
myamada04
0
710
知っておきたかったUIGestureRecognizerとUITouchの違い
myamada04
1
1.2k
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
1
200
30 Presentation Tips
portentint
PRO
1
330
The Curse of the Amulet
leimatthew05
1
13k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
430
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2k
The SEO identity crisis: Don't let AI make you average
varn
0
490
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
200
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
1.7k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Transcript
J04%$+BQBOEBZ ໌ຑҥՖ !N@ZBNBEB J04ʹ͓͚Δ4JSJ4IPSUDVUT ࠷খ࣮ Ћ
ࣗݾհ w ໌ຑҥՖ w 5XJUUFS!N@ZBNBEB w 4UVEZQMVT *OD w ʙ
w ࣄ৬ˠ4*FSˠݱࡏ w J04&OHJOFFS
4JSJ4IPSUDVUTػೳΛϦϦʔε ͋ͳͨͷؤுΓΛݟ͑ΔԽ͢ΔษڧهΞϓϦ 4UVEZQMVT
ରԠͨ͠ը໘ w Ϣʔβʔͷ23ίʔυը໘ w ॻ੶ͷόʔίʔυಡΈऔΓΧϝ ϥը໘ ͦΕͧΕɺ"QQMF͕4JSJ4IPSUDVUT ͷ࣮ΛקΊΔΞϓϦΛར༻͢Δ ্ͰԿճ܁Γฦ͠ߦΘΕΔૢ࡞ ʹ֘͢Δͱஅ࣮ͯ͠
4JSJ4IPSUDVUTར༻ঢ়گ ˞݄ʙ݄࣌ w γϣʔτΧοτܦ༝ͰΞϓϦΛ։͍ͨ w ճɿ w ਓɿ
w "EEUP4JSJϘλϯ͔ΒΞϓϦΛ։͘γϣʔτΧοτΛొͨ͠ w ճɿ w ਓɿ
ΞδΣϯμ w 4JSJ4IPSUDVUT࠷খ࣮ w 4QPUMJHIUͷl4JSJ͔ΒͷఏҊzʹγϣʔτΧοτΛࡌͤΔ w "EEUP4JSJϘλϯΛஔ͢Δ w ࣮ͯ͠Έͨ͏͑Ͱͷࢲతߟ w
"EEUP4JSJϘλϯΛஔ͢ΔͱΑ͍ը໘ɺஔ͠ͳ͍΄͏͕Α͍ը໘ w ఏҊϑϨʔζͷબͼ͔ͨ
ΞδΣϯμ w 4JSJ4IPSUDVUT࠷খ࣮ w 4QPUMJHIUͷl4JSJ͔ΒͷఏҊzʹγϣʔτΧοτΛࡌͤΔ w "EEUP4JSJϘλϯΛஔ͢Δ w ࣮ͯ͠Έͨ͏͑Ͱͷࢲతߟ w
"EEUP4JSJϘλϯΛஔ͢ΔͱΑ͍ը໘ɺஔ͠ͳ͍΄͏͕Α͍ը໘ w ఏҊϑϨʔζͷબͼ͔ͨ
࠷খ࣮ͱ 4JSJ4IPSUDVUTࣗମʹ࣮ํ๏͕େ͖͘௨Γ͋Δ w *OUFOUT*OUFOUT6*Λ༻͍Δ w ΞϓϦʹͯ܁Γฦ͠ߦ͏ಈ࡞Λ༷ʑͳΛड͚औΓͭͭ࠶ݱՄೳ w /46TFS"DUJWJUZΛ༻͍Δ w ಛఆͷը໘Λ։͍ͨঢ়ଶͷΞϓϦΛىಈ͢ΔͳͲɺ୯७ͳಈ࡞Λ࠶ݱՄೳ
࠷খ࣮ͱ 4JSJ4IPSUDVUTࣗମʹ࣮ํ๏͕େ͖͘௨Γ͋Δ w *OUFOUT*OUFOUT6*Λ༻͍Δ w ΞϓϦʹͯ܁Γฦ͠ߦ͏ಈ࡞Λ༷ʑͳΛड͚औΓͭͭ࠶ݱՄೳ w /46TFS"DUJWJUZΛ༻͍Δ w ಛఆͷը໘Λ։͍ͨঢ়ଶͷΞϓϦΛىಈ͢ΔͳͲɺ୯७ͳಈ࡞Λ࠶ݱՄೳ
࣮ *OGPQMJTUʹΞΫγϣϯͷ*%Λఆٛ <plist version="1.0"> <dict> <!-- தུ --> <key>NSUserActivityTypes</key> <array>
<string>$(BUNDLE_ID).materialBarcodeRead</string> <string>$(BUNDLE_ID).viewQRCode</string> </array> </dict> </plist>
࣮ ֘ͷΞΫγϣϯΛߦ͏/46TFS"DUJWJUZΦϒδΣΫτΛੜ ˞ҎԼόʔίʔυಡΈऔΓΧϝϥը໘༻ͷΦϒδΣΫτੜॲཧ import Intents struct MaterialBarcodeReadAction { static var
actionName: String { return "\(bundleId).materialBarcodeRead" } static var userActivity: NSUserActivity { let userActivity = NSUserActivity(activityType: actionName) userActivity.persistentIdentifier = actionName userActivity.title = "ڭࡐͷόʔίʔυΛಡΈऔΔ" return userActivity } }
࣮ ֘ͷΞΫγϣϯͰ։͘6*7JFX$POUSPMMFSΦϒδΣΫτΛઃఆ final class MaterialBarcodeReaderViewController: UIViewController { override func viewDidLoad()
{ super.viewDidLoad() let activity = MaterialBarcodeReadAction.userActivity userActivity = activity } }
࣮ "QQ%FMFHBUFʹϋϯυϧ࣌ͷॲཧΛ࣮ func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler:
@escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { switch userActivity.activityType { case MaterialBarcodeReadAction.actionName: // όʔίʔυಡΈऔΓΧϝϥը໘දࣔ return true case ViewQRCodeAction.actionName: // QRίʔυը໘දࣔ return true default: return false } }
࠷খ࣮·Ͱࡁ·ͤΔͱʜ ˠlγϣʔτΧοτzΞϓϦʹͯར༻ՄೳͳΞΫγϣϯͱͯ͠બࢶ͕දࣔ͞ΕΔ ˞4JSJ4IPSUDVUT࣮ͨ͠ޙͷରը໘ΛճҎ্։͍͍ͯΔඞཁ͋Γ
γϣʔτΧοτͷొํ๏ J04࣌
None
γϣʔτΧοτΪϟϥϦʔ͔ΒొՄೳ
ΞδΣϯμ w 4JSJ4IPSUDVUT࠷খ࣮ w 4QPUMJHIUͷl4JSJ͔ΒͷఏҊzʹγϣʔτΧοτΛࡌͤΔ w "EEUP4JSJϘλϯΛஔ͢Δ w ࣮ͯ͠Έͨ͏͑Ͱͷࢲతߟ w
"EEUP4JSJϘλϯΛஔ͢ΔͱΑ͍ը໘ɺஔ͠ͳ͍΄͏͕Α͍ը໘ w ఏҊϑϨʔζͷબͼ͔ͨ
࣮ /46TFS"DUJWJUZΦϒδΣΫτʹͯఏҊʹࡌͤΔΛઃఆ #if canImport(CoreSpotlight) import CoreSpotlight import MobileCoreServices #endif /*
লུ */ static var userActivity: NSUserActivity { let userActivity = NSUserActivity(activityType: actionName) userActivity.persistentIdentifier = actionName userActivity.title = "ڭࡐͷόʔίʔυΛಡΈऔΔ" userActivity.isEligibleForPrediction = true #if canImport(CoreSpotlight) let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeContent as String) attributes.title = "ڭࡐͷόʔίʔυΛಡΈऔΔ" attributes.contentDescription = "ొ͍ͨ͠ڭࡐͷόʔίʔυΛಡΈऔΕ·͢" userActivity.contentAttributeSet = attributes #endif return userActivity }
#if canImport(CoreSpotlight) import CoreSpotlight import MobileCoreServices #endif /* লུ */
static var userActivity: NSUserActivity { let userActivity = NSUserActivity(activityType: actionName) userActivity.persistentIdentifier = actionName userActivity.title = "ڭࡐͷόʔίʔυΛಡΈऔΔ" userActivity.isEligibleForPrediction = true #if canImport(CoreSpotlight) let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeContent as String) attributes.title = "ڭࡐͷόʔίʔυΛಡΈऔΔ" attributes.contentDescription = "ొ͍ͨ͠ڭࡐͷόʔίʔυΛಡΈऔΕ·͢" userActivity.contentAttributeSet = attributes #endif return userActivity } ࣮ /46TFS"DUJWJUZΦϒδΣΫτʹͯఏҊʹࡌͤΔΛઃఆ *NQPSUΛՃ 4QPUMJHIUͰ4JSJ͔ΒͷఏҊͱͯ͠දࣔΛ༗ޮʹ͠ɺ දࣔ͢ΔΛઃఆ
࣮ ֘7JFX$POUSPMMFSΛ։͍ͨࡍʹ௨͢Δ final class MaterialBarcodeReaderViewController: UIViewController { override func viewDidLoad()
{ super.viewDidLoad() let activity = MaterialBarcodeReadAction.userActivity userActivity = activity activity.becomeCurrent() } }
࣮ ֘7JFX$POUSPMMFSΛ։͍ͨࡍʹ௨͢Δ final class MaterialBarcodeReaderViewController: UIViewController { override func viewDidLoad()
{ super.viewDidLoad() let activity = MaterialBarcodeReadAction.userActivity userActivity = activity activity.becomeCurrent() } } ࣮ࡁΈͷ/46TFS"DUJWJUJZΦϒδΣΫτͰ࠶ݱͰ͖Δ ૢ࡞Λͨ͜͠ͱΛ௨
௨ͷ࣮·Ͱࡁ·ͤΔͱʜ ˠ֘ͷը໘ΛΑ͘͏߹ɺ ɹl4JSJ͔ΒͷఏҊzʹදࣔ͞ΕΔ ˞બ͢Δͱɺը໘ʹભҠ͢Δ͕γϣʔτΧοτ ͷՃෆՄ ˞σόοάʹɺͷઃఆσϕϩού %JTQMBZ3FDFOU4IPSUDVUTΛ0/
ΞδΣϯμ w 4JSJ4IPSUDVUT࠷খ࣮ w 4QPUMJHIUͷl4JSJ͔ΒͷఏҊzʹγϣʔτΧοτΛࡌͤΔ w "EEUP4JSJϘλϯΛஔ͢Δ w ࣮ͯ͠Έͨ͏͑Ͱͷࢲతߟ w
"EEUP4JSJϘλϯΛஔ͢ΔͱΑ͍ը໘ɺஔ͠ͳ͍΄͏͕Α͍ը໘ w ఏҊϑϨʔζͷબͼ͔ͨ
࣮ ϘλϯΛஔ͢Δ final class MaterialBarcodeReaderViewController: UIViewController { override func viewDidLoad()
{ super.viewDidLoad() let activity = MaterialBarcodeReadAction.userActivity userActivity = activity activity.becomeCurrent() let addToSiriButton = INUIAddVoiceShortcutButton(style: .automaticOutline) addToSiriButton.shortcut = INShortcut(userActivity: activity) addToSiriButton.delegate = self view.addSubview(addToSiriButton) } }
࣮ ϘλϯΛஔ͢Δ final class MaterialBarcodeReaderViewController: UIViewController { override func viewDidLoad()
{ super.viewDidLoad() let activity = MaterialBarcodeReadAction.userActivity userActivity = activity activity.becomeCurrent() let addToSiriButton = INUIAddVoiceShortcutButton(style: .automaticOutline) addToSiriButton.shortcut = INShortcut(userActivity: activity) addToSiriButton.delegate = self view.addSubview(addToSiriButton) } } "EEUP4JSJϘλϯͷΦϒδΣΫτΛੜ γϣʔτΧοτͱͯ͠ొ͢Δૢ࡞ "EEUP4JSJϘλϯΛԡԼͨ͠ࡍʹ ͜Ε͔Βදࣔ͢Δը໘ΦϒδΣΫτΛड͚औΔͨΊઃఆ
࣮ ϘλϯΛԡԼޙͷॲཧΛ࣮ extension MaterialBarcodeReaderViewController: INUIAddVoiceShortcutButtonDelegate { func present(_ addVoiceShortcutViewController: INUIAddVoiceShortcutViewController,
for addVoiceShortcutButton: INUIAddVoiceShortcutButton) { addVoiceShortcutViewController.delegate = self present(addVoiceShortcutViewController, animated: true, completion: nil) } func present(_ editVoiceShortcutViewController: INUIEditVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) { editVoiceShortcutViewController.delegate = self present(editVoiceShortcutViewController, animated: true, completion: nil) } }
None
࣮ 4JSJ4IPSUDVUTͷՃɾฤूྃ࣌ͷॲཧΛ࣮ Ճ extension MaterialBarcodeReaderViewController: INUIAddVoiceShortcutViewControllerDelegate { func addVoiceShortcutViewController( _
controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) { controller.dismiss(animated: true, completion: nil) } func addVoiceShortcutViewControllerDidCancel( _ controller: INUIAddVoiceShortcutViewController) { controller.dismiss(animated: true, completion: nil) } }
࣮ 4JSJ4IPSUDVUTͷՃɾฤूྃ࣌ͷॲཧΛ࣮ ฤू extension MaterialBarcodeReaderViewController: INUIEditVoiceShortcutViewControllerDelegate { func editVoiceShortcutViewController( _
controller: INUIEditVoiceShortcutViewController, didUpdate voiceShortcut: INVoiceShortcut?, error: Error?) { controller.dismiss(animated: true, completion: nil) } func editVoiceShortcutViewController( _ controller: INUIEditVoiceShortcutViewController, didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID) { controller.dismiss(animated: true, completion: nil) } func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) { controller.dismiss(animated: true, completion: nil) } }
"EEUP4JSJϘλϯ͕͋Δͱʜ ˠࣗͷΞϓϦ͔Β4JSJγϣʔτΧοτΛՃ͢Δಋઢ͕Ͱ͖Δ ˠ࣮ࡍʹͦͷը໘ΛΑ͘ར༻͢ΔϢʔβʔ͕ݟ͚ͭ͘͢ͳΔ
ΞδΣϯμ w 4JSJ4IPSUDVUT࠷খ࣮ w 4QPUMJHIUͷl4JSJ͔ΒͷఏҊzʹγϣʔτΧοτΛࡌͤΔ w "EEUP4JSJϘλϯΛஔ͢Δ w ࣮ͯ͠Έͨ͏͑Ͱͷࢲతߟ w
"EEUP4JSJϘλϯΛஔ͢ΔͱΑ͍ը໘ɺஔ͠ͳ͍΄͏͕Α͍ը໘ w ఏҊϑϨʔζͷબͼ͔ͨ
"EEUP4JSJϘλϯΛ ஔ͢ΔͱΑ͍ը໘ w ஔ͢Δ͜ͱͰຊདྷͷׂΛશ͏͢Δͷʹࢧো͕ग़ͳ͍ w ͱͱ༨ന͕ेʹ͋ΓɺӬଓతʹදࣔ͠ଓ͚ͯͳ͍ w Ϋογϣϯϖʔδͱͯ͠ผը໘ΛڬΉܗͰදࣔͯࠩ͠͠ࢧ͑ͳ͍ ஔ͠ͳ͍΄͏͕Α͍ը໘ w
ஔ͢ΔͱຊདྷͷׂΛશ͏͢ΔͨΊͷྖҬ͕ڱ͘ͳΔը໘ w ༷ʑͳใΛݟΔͨΊͷը໘ͳͲ
ΞδΣϯμ w 4JSJ4IPSUDVUT࠷খ࣮ w 4QPUMJHIUͷl4JSJ͔ΒͷఏҊzʹγϣʔτΧοτΛࡌͤΔ w "EEUP4JSJϘλϯΛஔ͢Δ w ࣮ͯ͠Έͨ͏͑Ͱͷࢲతߟ w
"EEUP4JSJϘλϯΛஔ͢ΔͱΑ͍ը໘ɺஔ͠ͳ͍΄͏͕Α͍ը໘ w ఏҊϑϨʔζͷબͼ͔ͨ
ఏҊϑϨʔζͱ /46TFS"DUJWJUZͷTVHHFTUFE*OWPDBUJPO1ISBTF import Intents struct MaterialBarcodeReadAction { static var actionName:
String { return "\(bundleId).materialBarcodeRead" } static var userActivity: NSUserActivity { let userActivity = NSUserActivity(activityType: actionName) userActivity.persistentIdentifier = actionName userActivity.title = “ڭࡐͷόʔίʔυΛಡΈऔΔ” userActivity.suggestedInvocationPhrase = "όʔίʔυΛಡΈऔΔ" return userActivity } }
ఏҊϑϨʔζ͕දࣔ͞ΕΔॴ w "EEUP4JSJϘλϯԡԼޙ w γϣʔτΧοτΪϟϥϦʔܦ༝ ͰͷγϣʔτΧοτొ ԻίϚϯυཝͷσϑΥϧτɻೖΕ ͓ͯ͘ͱϢʔβʔࣗͰʮԿͯݺͼ ͔͚Α͏ʁʯͱߟ͑ΔखؒΛল͍ͯొ Ͱ͖ͯศར
ఏҊϑϨʔζ͕දࣔ͞ΕΔॴ w "EEUP4JSJϘλϯԡԼޙ w γϣʔτΧοτΪϟϥϦʔܦ༝ ͰͷγϣʔτΧοτొ ԻίϚϯυཝͷσϑΥϧτɻೖΕ ͓ͯ͘ͱϢʔβʔࣗͰʮԿͯݺͼ ͔͚Α͏ʁʯͱߟ͑ΔखؒΛল͍ͯొ Ͱ͖ͯศར
ˠ4JSJ͕ฉ͖औΓͮΒ͍ݴ༿ɺϢʔβʔ͕͍ʹ͍͘ݴ༿ΛΛઃఆͯ͠͠·͏ͱɺΘΕͳ͘ͳΔ
ΑΓϢʔβʔ͕ར༻͍͢͠ ϑϨʔζΛબͿʹʁ
w ଞΞϓϦͷγϣʔτΧοτͱॏෳ͠ͳ͍ w ݕূ͢Δ w ݕূ͢Δڥ
ଞΞϓϦͷྨࣅγϣʔτΧοτͱॏෳͤ͞ͳ͍ w ಉ͡ʹڞଘ͍ͯ͠ΔՄೳੑ͕ߴ͍ΞϓϦͷγϣʔτΧοτΛ֬ೝ w ྨࣅͷγϣʔτΧοτ͕͋Δ߹ɺڞଘͯ͠ݺͼ͚Ͱ͖ΔΑ͏ΞϓϦ ໊ΛؚΊΔͷ͕Φεεϝ w ΞϓϦ໊༏ઌͯ͠ฉ͖औΓͯ͘͠ΕΔ༷ࢠ w ΞϓϦ໊ͰུশͳͲཁݕূ
ݕূ͢Δ w αϙʔτ͍ͯ͠Δ04όʔδϣϯͷ͏ͪɺҰ൪͍ϝδϟʔόʔδϣϯͷ Ͱ֬ೝ w 04όʔδϣϯ͕ਐΉຖʹฉ͖औΓੑೳ͕େ্͖͍ͯ͘͠Δ w αϙʔτ͍ͯ͠Δ04όʔδϣϯͷൣғͰۃྗεϖοΫͷ͍Ͱ֬ೝ w ϋʔυ໘Ͱฉ͖औΓੑೳ͕ҟͳΔ
ݕূ͢Δڥ w Ͱ͖Δ͚ͩϢʔβʔ͕࣮ࡍʹར༻͠͏Δڥʹ͍ۙঢ়ଶͰࢼ͢ w εϙʔπδϜͰར༻͢ΔΞϓϦͳΒ࣮ࡍʹ͍͖࣋ͬͯฉ͖औΓΛࢼ͢ͳͲ w صͷ্ʹฏஔ͖ͨ͠ঢ়ଶͰࢼ͢ w ֯ͷ໘ͷ߹͔Β͔ɺखͰ࣋ͭΑΓҙਤ͠ͳ͍ࡶԻ͕रΘ Ε͕ͪ
Α͍4JSJ4IPSUDVUTରԠΛ
ࢀߟ /46TFS"DUJWJUZUJUMF /46TFS"DUJWJUZDPOUFOU"UUSJCVUF4FUDPOUFOU%FTDSJQUJPO γϣʔτΧοτ 4JSJ͔ΒͷఏҊ 4JSJʹՃ /46TFS"DUJWJUZDPOUFOU"UUSJCVUF4FUUIVNCOBJM%BUB /46TFS"DUJWJUZTVHHFTUFE*OWPDBUJPO1ISBTF ᶃ ᶃ
ᶃ ᶃ ᶃ ᶄ ᶄ ᶄ ᶅ ᶅ ᶅ ᶅ ᶅ ᶆ ᶆ
ࢀߟ w "EEJOH6TFS*OUFSBDUJWJUZXJUI4JSJ4IPSUDVUTBOEUIF4IPSUDVUT"QQ w IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTJSJLJU BEEJOH@VTFS@JOUFSBDUJWJUZ@XJUI@TJSJ@TIPSUDVUT@BOE@UIF@TIPSUDVUT@BQ Q w %FTJHOJOH(SFBU4IPSUDVUT w
IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED
ࢀߟ w 4PVQ$IFG αϯϓϧίʔυ w IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOTJSJLJU TPVQ@DIFG@BDDFMFSBUJOH@BQQ@JOUFSBDUJPOT@XJUI@TIPSUDVUT w 4JSJ4IPSUDVUT·ͱΊ
w IUUQTLVSPIBUFOBCMPHDPNFOUSZ w J1IPOFJ1BEͰγϣʔτΧοτ"QQΛ͏c"QQMF w IUUQTTVQQPSUBQQMFDPNKBKQ)5