Akankah Intent SiriKit Sesuai dengan Aplikasi Anda? Jika Ya, Inilah Cara Menggunakannya
Diterbitkan: 2022-03-10Sejak iOS 5, Siri telah membantu pengguna iPhone mengirim pesan, mengatur pengingat, dan mencari restoran dengan aplikasi Apple. Mulai di iOS 10, kami juga dapat menggunakan Siri di beberapa aplikasi kami sendiri.
Untuk menggunakan fungsi ini, aplikasi Anda harus sesuai dengan "domain dan maksud" Siri yang telah ditentukan sebelumnya oleh Apple. Dalam artikel ini, kita akan mempelajari tentang apa itu dan melihat apakah aplikasi kita dapat menggunakannya. Kami akan menggunakan aplikasi sederhana yang merupakan pengelola daftar tugas dan mempelajari cara menambahkan dukungan Siri. Kami juga akan membaca panduan situs web pengembang Apple tentang konfigurasi dan kode Swift untuk jenis ekstensi baru yang diperkenalkan dengan SiriKit: ekstensi Intents .
Saat Anda masuk ke bagian pengkodean artikel ini, Anda akan memerlukan Xcode (setidaknya versi 9.x), dan akan lebih baik jika Anda terbiasa dengan pengembangan iOS di Swift karena kami akan menambahkan Siri ke perangkat kecil yang berfungsi. aplikasi. Kami akan melalui langkah-langkah menyiapkan ekstensi di situs web pengembang Apple dan menambahkan kode ekstensi Siri ke aplikasi.
"Hei Siri, Mengapa Aku Membutuhkanmu?"
Terkadang saya menggunakan ponsel saat di sofa, dengan kedua tangan bebas, dan saya dapat memberikan perhatian penuh pada layar. Mungkin saya akan mengirim pesan kepada saudara perempuan saya untuk merencanakan ulang tahun ibu kami atau membalas pertanyaan di Trello. Saya bisa melihat aplikasinya. Saya bisa mengetuk layar. Saya bisa mengetik.
Tapi saya mungkin sedang berjalan-jalan di kota saya, mendengarkan podcast, ketika sebuah teks masuk di jam tangan saya. Ponsel saya ada di saku saya, dan saya tidak dapat dengan mudah menjawab sambil berjalan.
Dengan Siri, saya dapat menahan tombol kontrol headphone saya dan berkata, "Kirim pesan kepada saudara perempuan saya bahwa saya akan berada di sana pada pukul dua." Siri sangat bagus saat Anda bepergian dan tidak dapat memberikan perhatian penuh pada ponsel Anda atau saat interaksinya kecil, tetapi Siri memerlukan beberapa ketukan dan banyak pengetikan.
Ini bagus jika saya ingin menggunakan aplikasi Apple untuk interaksi ini. Tetapi beberapa kategori aplikasi, seperti perpesanan, memiliki alternatif yang sangat populer. Aktivitas lain, seperti memesan tumpangan atau memesan meja di restoran, bahkan tidak dapat dilakukan dengan aplikasi bawaan Apple tetapi sempurna untuk Siri.
Pendekatan Apple Untuk Asisten Suara
Untuk mengaktifkan Siri di aplikasi pihak ketiga, Apple harus memutuskan mekanisme untuk mengambil suara dari suara pengguna dan entah bagaimana membawanya ke aplikasi dengan cara yang dapat memenuhi permintaan. Untuk memungkinkan ini, Apple mengharuskan pengguna untuk menyebutkan nama aplikasi dalam permintaan, tetapi mereka memiliki beberapa opsi tentang apa yang harus dilakukan dengan permintaan lainnya.
- Itu bisa mengirim file suara ke aplikasi.
Manfaat dari pendekatan ini adalah bahwa aplikasi dapat mencoba menangani secara harfiah setiap permintaan yang mungkin dimiliki pengguna untuk itu. Amazon atau Google mungkin menyukai pendekatan ini karena mereka sudah memiliki layanan pengenalan suara yang canggih. Tetapi sebagian besar aplikasi tidak akan dapat menangani ini dengan sangat mudah. - Itu bisa mengubah pidato menjadi teks dan mengirimkannya.
Karena banyak aplikasi tidak memiliki implementasi bahasa alami yang canggih, pengguna biasanya harus berpegang pada frasa yang sangat khusus, dan dukungan non-Inggris akan diserahkan kepada pengembang aplikasi untuk diterapkan. - Itu bisa meminta Anda untuk memberikan daftar frasa yang Anda pahami.
Mekanisme ini lebih dekat dengan apa yang dilakukan Amazon dengan Alexa (dalam kerangka "keterampilan"), dan memungkinkan lebih banyak penggunaan Alexa daripada yang dapat ditangani SiriKit saat ini. Dalam keterampilan Alexa, Anda memberikan frasa dengan variabel placeholder yang akan diisi Alexa untuk Anda. Misalnya, “Alexa, ingatkan saya pada$TIME$
to$REMINDER$
” — Alexa akan menjalankan frasa ini terhadap apa yang telah dikatakan pengguna dan memberi tahu Anda nilai untukTIME
danREMINDER
. Seperti mekanisme sebelumnya, pengembang perlu melakukan semua terjemahan, dan tidak ada banyak fleksibilitas jika pengguna mengatakan sesuatu yang sedikit berbeda. - Itu bisa menentukan daftar permintaan dengan parameter dan mengirim aplikasi permintaan terstruktur.
Ini sebenarnya yang dilakukan Apple, dan manfaatnya adalah dapat mendukung berbagai bahasa, dan melakukan semua pekerjaan untuk mencoba memahami semua cara yang mungkin dilakukan pengguna untuk mengajukan permintaan. Kelemahan besar adalah Anda hanya dapat mengimplementasikan penangan untuk permintaan yang ditentukan Apple. Ini bagus jika Anda memiliki, misalnya, aplikasi perpesanan, tetapi jika Anda memiliki layanan streaming musik atau pemutar podcast, Anda tidak dapat menggunakan SiriKit sekarang.
Demikian pula, ada tiga cara bagi aplikasi untuk berbicara kembali kepada pengguna: dengan suara, dengan teks yang dikonversi, atau dengan mengekspresikan hal yang ingin Anda katakan dan membiarkan sistem mencari cara yang tepat untuk mengekspresikannya. Solusi terakhir (yang dilakukan Apple) memberikan beban terjemahan pada Apple, tetapi ini memberi Anda cara terbatas untuk menggunakan kata-kata Anda sendiri untuk menggambarkan sesuatu.
Jenis permintaan yang dapat Anda tangani ditentukan dalam domain dan maksud SiriKit. Intent adalah jenis permintaan yang mungkin dibuat pengguna, seperti mengirim SMS ke kontak atau menemukan foto. Setiap maksud memiliki daftar parameter — misalnya, SMS memerlukan kontak dan pesan.
Domain hanyalah sekelompok maksud terkait. Membaca teks dan mengirim teks keduanya berada dalam domain perpesanan. Memesan perjalanan dan mendapatkan lokasi berada dalam domain pemesanan perjalanan. Ada domain untuk melakukan panggilan VoIP, memulai latihan, mencari foto, dan beberapa hal lainnya. Dokumentasi SiriKit berisi daftar lengkap domain dan maksudnya.
Kritik umum terhadap Siri adalah bahwa Siri tampaknya tidak dapat menangani permintaan seperti halnya Google dan Alexa, dan ekosistem suara pihak ketiga yang diaktifkan oleh pesaing Apple lebih kaya.
Saya setuju dengan kritik-kritik itu. Jika aplikasi Anda tidak sesuai dengan maksud saat ini, maka Anda tidak dapat menggunakan SiriKit, dan tidak ada yang dapat Anda lakukan. Meskipun aplikasi Anda cocok, Anda tidak dapat mengontrol semua kata yang diucapkan atau dipahami Siri; jadi, jika Anda memiliki cara tertentu untuk membicarakan berbagai hal di aplikasi Anda, Anda tidak selalu dapat mengajarkannya kepada Siri.
Harapan pengembang iOS adalah bahwa Apple akan memperluas daftar maksud dan pemrosesan bahasa alaminya menjadi jauh lebih baik. Jika demikian, maka kami akan memiliki asisten suara yang berfungsi tanpa pengembang harus menerjemahkan atau memahami semua cara untuk mengatakan hal yang sama. Dan menerapkan dukungan untuk permintaan terstruktur sebenarnya cukup mudah dilakukan — jauh lebih mudah daripada membangun parser bahasa alami.
Manfaat besar lainnya dari kerangka maksud adalah tidak terbatas pada Siri dan permintaan suara. Bahkan sekarang, aplikasi Maps bisa menghasilkan permintaan berbasis maksud dari aplikasi Anda (misalnya, reservasi restoran). Ia melakukan ini secara terprogram (bukan dari suara atau bahasa alami). Jika Apple mengizinkan aplikasi untuk menemukan maksud terbuka satu sama lain, kami akan memiliki cara yang jauh lebih baik agar aplikasi dapat bekerja bersama, (sebagai lawan dari URL gaya x-callback).
Terakhir, karena intent adalah permintaan terstruktur dengan parameter, ada cara sederhana bagi aplikasi untuk menyatakan bahwa parameter tidak ada atau memerlukan bantuan untuk membedakan beberapa opsi. Siri kemudian dapat mengajukan pertanyaan lanjutan untuk menyelesaikan parameter tanpa aplikasi perlu melakukan percakapan.
Domain Pemesanan Perjalanan
Untuk memahami domain dan maksud, mari kita lihat domain pemesanan kendaraan. Ini adalah domain yang akan Anda gunakan untuk meminta Siri membelikan Anda mobil Lyft.
Apple mendefinisikan cara meminta tumpangan dan cara mendapatkan informasi tentangnya, tetapi sebenarnya tidak ada aplikasi bawaan Apple yang benar-benar dapat menangani permintaan ini. Ini adalah salah satu dari sedikit domain yang memerlukan aplikasi berkemampuan SiriKit.
Anda dapat memanggil salah satu maksud melalui suara atau langsung dari Maps. Beberapa maksud untuk domain ini adalah:
- Minta tumpangan
Gunakan yang ini untuk memesan tumpangan. Anda harus menyediakan lokasi penjemputan dan pengantaran, dan aplikasi mungkin juga perlu mengetahui jumlah rombongan Anda dan jenis perjalanan yang Anda inginkan. Contoh frasa mungkin, “Pesankan saya tumpangan dengan <nama aplikasi>”. - Dapatkan status perjalanan
Gunakan maksud ini untuk mengetahui apakah permintaan Anda diterima dan untuk mendapatkan informasi tentang kendaraan dan pengemudi, termasuk lokasinya. Aplikasi Maps menggunakan maksud ini untuk menampilkan gambar mobil yang diperbarui saat mendekati Anda. - Membatalkan perjalanan
Gunakan ini untuk membatalkan perjalanan yang telah Anda pesan.
Untuk semua maksud ini, Siri mungkin perlu mengetahui lebih banyak informasi. Seperti yang akan Anda lihat saat kami menerapkan pengendali maksud, ekstensi Intent Anda dapat memberi tahu Siri bahwa parameter yang diperlukan tidak ada, dan Siri akan meminta pengguna untuk melakukannya.
Fakta bahwa maksud dapat dipanggil secara terprogram oleh Maps menunjukkan bagaimana maksud dapat mengaktifkan komunikasi antar-aplikasi di masa mendatang.
Catatan : Anda bisa mendapatkan daftar lengkap domain dan maksud mereka di situs web pengembang Apple. Ada juga contoh aplikasi Apple dengan banyak domain dan maksud yang diterapkan, termasuk pemesanan kendaraan.
Menambahkan Daftar Dan Catatan Dukungan Domain Ke Aplikasi Anda
Oke, sekarang setelah kita memahami dasar-dasar SiriKit, mari kita lihat bagaimana Anda akan menambahkan dukungan untuk Siri di aplikasi yang melibatkan banyak konfigurasi dan kelas untuk setiap maksud yang ingin Anda tangani.
Sisa artikel ini terdiri dari langkah-langkah mendetail untuk menambahkan dukungan Siri ke aplikasi. Ada lima hal tingkat tinggi yang perlu Anda lakukan:
- Bersiaplah untuk menambahkan ekstensi baru ke aplikasi dengan membuat profil penyediaan dengan hak baru untuk itu di situs web pengembang Apple.
- Konfigurasikan aplikasi Anda (melalui
plist
) untuk menggunakan hak. - Gunakan template Xcode untuk memulai dengan beberapa contoh kode.
- Tambahkan kode untuk mendukung niat Siri Anda.
- Konfigurasikan kosakata Siri melalui
plist
s.
Jangan khawatir: Kami akan membahas masing-masing ini, menjelaskan ekstensi dan hak di sepanjang jalan.
Untuk fokus hanya pada bagian Siri, saya telah menyiapkan pengelola daftar tugas sederhana, List-o-Mat.

Anda dapat menemukan sumber lengkap dari sampel, List-o-Mat, di GitHub.
Untuk membuatnya, yang saya lakukan hanyalah memulai dengan template aplikasi Xcode Master-Detail dan membuat kedua layar menjadi UITableView
. Saya menambahkan cara untuk menambah dan menghapus daftar dan item, dan cara untuk menandai item yang sudah selesai. Semua navigasi dihasilkan oleh template.
Untuk menyimpan data, saya menggunakan protokol Codable
, (diperkenalkan di WWDC 2017), yang mengubah struct menjadi JSON dan menyimpannya dalam file teks di folder documents
.
Saya sengaja menyimpan kodenya dengan sangat sederhana. Jika Anda memiliki pengalaman dengan Swift dan membuat pengontrol tampilan, maka Anda seharusnya tidak memiliki masalah dengan itu.
Sekarang kita dapat melalui langkah-langkah menambahkan dukungan SiriKit. Langkah-langkah tingkat tinggi akan sama untuk aplikasi apa pun dan domain serta maksud mana pun yang Anda rencanakan untuk diterapkan. Kami sebagian besar akan berurusan dengan situs web pengembang Apple, mengedit plist
s dan menulis sedikit Swift.
Untuk List-o-Mat, kami akan fokus pada domain daftar dan catatan, yang secara luas berlaku untuk hal-hal seperti aplikasi pencatat dan daftar tugas.
Dalam domain daftar dan catatan, kami memiliki maksud berikut yang masuk akal untuk aplikasi kami.
- Dapatkan daftar tugas.
- Tambahkan tugas baru ke daftar.
Karena interaksi dengan Siri sebenarnya terjadi di luar aplikasi Anda (mungkin bahkan saat aplikasi Anda tidak berjalan), iOS menggunakan ekstensi untuk menerapkan ini.
Ekstensi Niat
Jika Anda belum pernah bekerja dengan ekstensi, Anda harus mengetahui tiga hal utama:
- Perpanjangan adalah proses yang terpisah. Itu dikirimkan di dalam bundel aplikasi Anda, tetapi berjalan sepenuhnya sendiri, dengan kotak pasirnya sendiri.
- Aplikasi dan ekstensi Anda dapat berkomunikasi satu sama lain dengan berada dalam grup aplikasi yang sama. Cara termudah adalah melalui folder kotak pasir bersama grup (jadi, mereka dapat membaca dan menulis ke file yang sama jika Anda meletakkannya di sana).
- Ekstensi memerlukan ID aplikasi, profil, dan haknya sendiri.
Untuk menambahkan ekstensi ke aplikasi Anda, mulailah dengan masuk ke akun pengembang Anda dan buka bagian “Sertifikat, Pengidentifikasi, & Profil”.
Memperbarui Data Akun Aplikasi Pengembang Apple Anda
Di akun pengembang Apple kami, hal pertama yang perlu kami lakukan adalah membuat grup aplikasi. Buka bagian "Grup Aplikasi" di bawah "Pengidentifikasi" dan tambahkan satu.

Itu harus dimulai dengan group
, diikuti oleh pengenal berbasis domain terbalik seperti biasa. Karena memiliki awalan, Anda dapat menggunakan pengenal aplikasi Anda untuk sisanya.
Kemudian, kami perlu memperbarui ID aplikasi kami untuk menggunakan grup ini dan mengaktifkan Siri:
- Buka bagian "ID Aplikasi" dan klik ID aplikasi Anda;
- Klik tombol "Edit";
- Aktifkan grup aplikasi (jika tidak diaktifkan untuk ekstensi lain).
Aktifkan grup aplikasi (Pratinjau besar) - Kemudian konfigurasikan grup aplikasi dengan mengklik tombol "Edit". Pilih grup aplikasi dari sebelumnya.
Setel nama grup aplikasi (Pratinjau besar) - Aktifkan SiriKit.
Aktifkan SiriKit (Pratinjau besar) - Klik "Selesai" untuk menyimpannya.
Sekarang, kita perlu membuat ID aplikasi baru untuk ekstensi kita:
- Di bagian "ID Aplikasi" yang sama, tambahkan ID aplikasi baru. Ini akan menjadi pengenal aplikasi Anda, dengan akhiran. Jangan hanya menggunakan
Intents
sebagai sufiks karena nama ini akan menjadi nama modul Anda di Swift dan kemudian akan bertentangan denganIntents
sebenarnya.Buat ID aplikasi untuk ekstensi Intents (Pratinjau besar) - Aktifkan ID aplikasi ini untuk grup aplikasi juga (dan atur grup seperti yang kita lakukan sebelumnya).
Sekarang, buat profil penyediaan pengembangan untuk ekstensi Intents, dan buat ulang profil penyediaan aplikasi Anda. Unduh dan instal seperti biasa.
Sekarang setelah profil kita terinstal, kita perlu membuka Xcode dan memperbarui hak aplikasi.
Memperbarui Hak Aplikasi Anda Di Xcode
Kembali ke Xcode, pilih nama proyek Anda di navigator proyek. Kemudian, pilih target utama aplikasi Anda, dan buka tab "Kemampuan". Di sana, Anda akan melihat tombol untuk mengaktifkan dukungan Siri.

Lebih jauh ke bawah daftar, Anda dapat mengaktifkan grup aplikasi dan mengonfigurasinya.

Jika Anda telah menyiapkannya dengan benar, Anda akan melihat ini di file .entitlements
aplikasi Anda:

Sekarang, kami akhirnya siap untuk menambahkan target ekstensi Intents ke proyek kami.
Menambahkan Ekstensi Intent
Kami akhirnya siap untuk menambahkan ekstensi. Di Xcode, pilih "File" → "Target Baru." Lembar ini akan muncul:

Pilih "Intents Extension" dan klik tombol "Next". Isi layar berikut:

Nama produk harus cocok dengan apa pun yang Anda buat akhiran di ID aplikasi maksud di situs web pengembang Apple.
Kami memilih untuk tidak menambahkan ekstensi UI maksud. Ini tidak tercakup dalam artikel ini, tetapi Anda dapat menambahkannya nanti jika Anda membutuhkannya. Pada dasarnya, ini adalah cara untuk menempatkan merek Anda sendiri dan gaya tampilan ke dalam hasil visual Siri.
Setelah selesai, Xcode akan membuat kelas pengendali maksud yang dapat kita gunakan sebagai bagian awal untuk implementasi Siri kita.
Pengendali Maksud: Selesaikan, Konfirmasi, dan Tangani
Xcode menghasilkan target baru yang memiliki titik awal bagi kami.
Hal pertama yang harus Anda lakukan adalah menyiapkan target baru ini untuk berada di grup aplikasi yang sama dengan aplikasi. Seperti sebelumnya, buka tab "Kemampuan" target, dan aktifkan grup aplikasi, dan konfigurasikan dengan nama grup Anda. Ingat, aplikasi dalam grup yang sama memiliki kotak pasir yang dapat digunakan untuk berbagi file satu sama lain. Kami membutuhkan ini agar permintaan Siri masuk ke aplikasi kami.
List-o-Mat memiliki fungsi yang mengembalikan folder dokumen grup. Kita harus menggunakannya kapan pun kita ingin membaca atau menulis ke file bersama.
func documentsFolder() -> URL? { return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.app-o-mat.ListOMat") }
Misalnya, ketika kami menyimpan daftar, kami menggunakan ini:
func save(lists: Lists) { guard let docsDir = documentsFolder() else { fatalError("no docs dir") } let url = docsDir.appendingPathComponent(fileName, isDirectory: false) // Encode lists as JSON and save to url }
Template ekstensi Intents membuat file bernama IntentHandler.swift
, dengan kelas bernama IntentHandler
. Itu juga mengonfigurasinya menjadi titik masuk maksud di plist
ekstensi.

Dalam daftar yang sama plist
, Anda akan melihat bagian untuk mendeklarasikan maksud yang kami dukung. Kita akan mulai dengan yang memungkinkan pencarian daftar, yang bernama INSearchForNotebookItemsIntent
. Tambahkan ke array di bawah IntentsSupported
.


Sekarang, buka IntentHandler.swift
dan ganti isinya dengan kode ini:
import Intents class IntentHandler: INExtension { override func handler(for intent: INIntent) -> Any? { switch intent { case is INSearchForNotebookItemsIntent: return SearchItemsIntentHandler() default: return nil } } }
Fungsi handler
dipanggil untuk membuat objek menangani maksud tertentu. Anda cukup mengimplementasikan semua protokol di kelas ini dan mengembalikan self
, tetapi kami akan menempatkan setiap maksud di kelasnya sendiri agar tetap terorganisir dengan lebih baik.
Karena kami bermaksud memiliki beberapa kelas yang berbeda, mari beri mereka kelas dasar umum untuk kode yang perlu kita bagikan di antara mereka:
class ListOMatIntentsHandler: NSObject { }
Kerangka maksud mengharuskan kita untuk mewarisi dari NSObject
. Kami akan mengisi beberapa metode nanti.
Kami memulai implementasi pencarian kami dengan ini:
class SearchItemsIntentHandler: ListOMatIntentsHandler, INSearchForNotebookItemsIntentHandling { }
Untuk menyetel pengendali maksud, kita perlu menerapkan tiga langkah dasar
- Selesaikan parameternya.
Pastikan parameter yang diperlukan diberikan, dan samarkan semua yang tidak Anda pahami sepenuhnya. - Konfirmasikan bahwa permintaan dapat dilakukan.
Ini sering opsional, tetapi meskipun Anda tahu bahwa setiap parameter baik, Anda mungkin masih memerlukan akses ke sumber daya luar atau memiliki persyaratan lain. - Menangani permintaan.
Lakukan hal yang diminta.
INSearchForNotebookItemsIntent
, maksud pertama yang akan kita terapkan, dapat digunakan sebagai pencarian tugas. Jenis permintaan yang dapat kami tangani dengan ini adalah, "Di List-o-Mat, tunjukkan daftar toko kelontong" atau "Di List-o-Mat, tunjukkan daftar toko."
Selain: "List-o-Mat" sebenarnya adalah nama yang buruk untuk aplikasi SiriKit karena Siri mengalami kesulitan dengan tanda hubung di aplikasi. Untungnya, SiriKit memungkinkan kita untuk memiliki nama alternatif dan memberikan pengucapan. Di Info.plist
aplikasi, tambahkan bagian ini:

Ini memungkinkan pengguna untuk mengatakan "daftar oh mat" dan untuk itu dipahami sebagai satu kata (tanpa tanda hubung). Itu tidak terlihat ideal di layar, tetapi tanpa itu, Siri terkadang berpikir "Daftar" dan "Mat" adalah kata yang terpisah dan menjadi sangat bingung.
Putuskan: Mencari Tahu Parameter
Untuk pencarian item notebook, ada beberapa parameter:
- jenis item (tugas, daftar tugas, atau catatan),
- judul barang,
- isi barang,
- status penyelesaian (apakah tugas ditandai selesai atau tidak),
- lokasi yang terkait dengannya,
- tanggal yang terkait dengannya.
Kami hanya membutuhkan dua yang pertama, jadi kami harus menulis fungsi penyelesaian untuk mereka. INSearchForNotebookItemsIntent
memiliki metode untuk kita terapkan.
Karena kami hanya peduli untuk menampilkan daftar tugas, kami akan mengkodekannya ke dalam resolusi untuk tipe item. Di SearchItemsIntentHandler
, tambahkan ini:
func resolveItemType(for intent: INSearchForNotebookItemsIntent, with completion: @escaping (INNotebookItemTypeResolutionResult) -> Void) { completion(.success(with: .taskList)) }
Jadi, apa pun yang dikatakan pengguna, kami akan mencari daftar tugas. Jika kami ingin memperluas dukungan pencarian kami, kami akan membiarkan Siri mencoba mencari tahu ini dari frasa asli dan kemudian hanya menggunakan completion(.needsValue())
jika jenis item tidak ada. Atau, kita bisa mencoba menebak dari judulnya dengan melihat apa yang cocok dengannya. Dalam hal ini, kami akan menyelesaikan dengan sukses ketika Siri tahu apa itu, dan kami akan menggunakan completion(.notRequired())
ketika kami akan mencoba beberapa kemungkinan.
Resolusi judul sedikit lebih rumit. Yang kami inginkan adalah Siri menggunakan daftar jika menemukan daftar yang sama persis dengan apa yang Anda katakan. Jika tidak yakin atau jika ada lebih dari satu kemungkinan, maka kami ingin Siri meminta bantuan kami untuk mencari tahu. Untuk melakukan ini, SiriKit menyediakan satu set enum resolusi yang memungkinkan kita mengekspresikan apa yang kita inginkan terjadi selanjutnya.
Jadi, jika Anda mengatakan "Toko Kelontong", maka Siri akan memiliki kecocokan yang sama persis. Tetapi jika Anda mengatakan "Store," maka Siri akan menyajikan menu daftar yang cocok.
Kita akan mulai dengan fungsi ini untuk memberikan struktur dasar:
func resolveTitle(for intent: INSearchForNotebookItemsIntent, with completion: @escaping (INSpeakableStringResolutionResult) -> Void) { guard let title = intent.title else { completion(.needsValue()) return } let possibleLists = getPossibleLists(for: title) completeResolveListName(with: possibleLists, for: title, with: completion) }
Kami akan mengimplementasikan getPossibleLists(for:)
dan completeResolveListName(with:for:with:)
di kelas dasar ListOMatIntentsHandler
.
getPossibleLists(for:)
perlu mencoba mencocokkan judul yang diberikan Siri kepada kami dengan nama daftar sebenarnya.
public func getPossibleLists(for listName: INSpeakableString) -> [INSpeakableString] { var possibleLists = [INSpeakableString]() for l in loadLists() { if l.name.lowercased() == listName.spokenPhrase.lowercased() { return [INSpeakableString(spokenPhrase: l.name)] } if l.name.lowercased().contains(listName.spokenPhrase.lowercased()) || listName.spokenPhrase.lowercased() == "all" { possibleLists.append(INSpeakableString(spokenPhrase: l.name)) } } return possibleLists }
Kami mengulang semua daftar kami. Jika kami mendapatkan kecocokan yang tepat, kami akan mengembalikannya, dan jika tidak, kami akan mengembalikan serangkaian kemungkinan. Dalam fungsi ini, kami hanya memeriksa untuk melihat apakah kata yang diucapkan pengguna terkandung dalam nama daftar (jadi, kecocokan yang cukup sederhana). Ini memungkinkan "Toko Kelontong" cocok dengan "Toko Kelontong". Algoritme yang lebih maju mungkin mencoba mencocokkan berdasarkan kata-kata yang terdengar sama (misalnya, dengan algoritme Soundex),
completeResolveListName(with:for:with:)
bertanggung jawab untuk memutuskan apa yang harus dilakukan dengan daftar kemungkinan ini.
public func completeResolveListName(with possibleLists: [INSpeakableString], for listName: INSpeakableString, with completion: @escaping (INSpeakableStringResolutionResult) -> Void) { switch possibleLists.count { case 0: completion(.unsupported()) case 1: if possibleLists[0].spokenPhrase.lowercased() == listName.spokenPhrase.lowercased() { completion(.success(with: possibleLists[0])) } else { completion(.confirmationRequired(with: possibleLists[0])) } default: completion(.disambiguation(with: possibleLists)) } }
Jika kami mendapatkan kecocokan yang tepat, kami memberi tahu Siri bahwa kami berhasil. Jika kami mendapatkan satu kecocokan yang tidak tepat, kami memberi tahu Siri untuk bertanya kepada pengguna apakah tebakan kami benar.
Jika kami mendapatkan beberapa kecocokan, maka kami menggunakan completion(.disambiguation(with: possibleLists))
untuk memberi tahu Siri agar menampilkan daftar dan membiarkan pengguna memilih satu.
Sekarang kita tahu apa permintaannya, kita perlu melihat semuanya dan memastikan kita bisa menanganinya.
Konfirmasi: Periksa Semua Ketergantungan Anda
Dalam hal ini, jika kami telah menyelesaikan semua parameter, kami selalu dapat menangani permintaan tersebut. Implementasi confirm()
tipikal mungkin memeriksa ketersediaan layanan eksternal atau memeriksa tingkat otorisasi.
Karena confirm()
adalah opsional, kami tidak dapat melakukan apa-apa, dan Siri akan menganggap kami dapat menangani permintaan apa pun dengan parameter yang diselesaikan. Untuk lebih jelasnya, kita bisa menggunakan ini:
func confirm(intent: INSearchForNotebookItemsIntent, completion: @escaping (INSearchForNotebookItemsIntentResponse) -> Void) { completion(INSearchForNotebookItemsIntentResponse(code: .success, userActivity: nil)) }
Ini berarti kita bisa menangani apa saja.
Menangani: Lakukan
Langkah terakhir adalah menangani permintaan.
func handle(intent: INSearchForNotebookItemsIntent, completion: @escaping (INSearchForNotebookItemsIntentResponse) -> Void) { guard let title = intent.title, let list = loadLists().filter({ $0.name.lowercased() == title.spokenPhrase.lowercased()}).first else { completion(INSearchForNotebookItemsIntentResponse(code: .failure, userActivity: nil)) return } let response = INSearchForNotebookItemsIntentResponse(code: .success, userActivity: nil) response.tasks = list.items.map { return INTask(title: INSpeakableString(spokenPhrase: $0.name), status: $0.done ? INTaskStatus.completed : INTaskStatus.notCompleted, taskType: INTaskType.notCompletable, spatialEventTrigger: nil, temporalEventTrigger: nil, createdDateComponents: nil, modifiedDateComponents: nil, identifier: "\(list.name)\t\($0.name)") } completion(response) }
Pertama, kami menemukan daftar berdasarkan judul. Pada titik ini, resolveTitle
telah memastikan bahwa kita akan mendapatkan kecocokan yang sama persis. Tetapi jika ada masalah, kami masih dapat mengembalikan kegagalan.
Ketika kami mengalami kegagalan, kami memiliki opsi untuk meneruskan aktivitas pengguna. Jika aplikasi Anda menggunakan Handoff dan memiliki cara untuk menangani jenis permintaan yang tepat ini, maka Siri mungkin mencoba menunda aplikasi Anda untuk mencoba permintaan di sana. Itu tidak akan melakukan ini ketika kita berada dalam konteks suara saja (misalnya, Anda mulai dengan "Hai Siri"), dan itu tidak menjamin bahwa itu akan melakukannya dalam kasus lain, jadi jangan mengandalkannya.
Ini sekarang siap untuk diuji. Pilih ekstensi maksud dalam daftar target di Xcode. Tetapi sebelum Anda menjalankannya, edit skemanya.

Itu memunculkan cara untuk memberikan kueri secara langsung:

Perhatikan, saya menggunakan "ListOMat" karena masalah tanda hubung yang disebutkan di atas. Untungnya, pengucapannya sama dengan nama aplikasi saya, jadi seharusnya tidak menjadi masalah.
Kembali ke aplikasi, saya membuat daftar "Toko Kelontong" dan daftar "Toko Perangkat Keras". Jika saya meminta Siri untuk daftar "toko", itu akan melalui jalur disambiguasi, yang terlihat seperti ini:

Jika Anda mengatakan "Toko Kelontong", maka Anda akan mendapatkan kecocokan persis, yang langsung menuju ke hasil.
Menambahkan Item Melalui Siri
Sekarang setelah kita mengetahui konsep dasar dari penyelesaian, konfirmasi, dan penanganan, kita dapat dengan cepat menambahkan maksud untuk menambahkan item ke daftar.
Pertama, tambahkan INAddTasksIntent
ke daftar ekstensi:

Kemudian, perbarui fungsi handle
IntentHandler
kami.
override func handler(for intent: INIntent) -> Any? { switch intent { case is INSearchForNotebookItemsIntent: return SearchItemsIntentHandler() case is INAddTasksIntent: return AddItemsIntentHandler() default: return nil } }
Tambahkan rintisan untuk kelas baru:
class AddItemsIntentHandler: ListOMatIntentsHandler, INAddTasksIntentHandling { }
Menambahkan item memerlukan resolve
yang sama untuk pencarian, kecuali dengan daftar tugas target, bukan judul.
func resolveTargetTaskList(for intent: INAddTasksIntent, with completion: @escaping (INTaskListResolutionResult) -> Void) { guard let title = intent.targetTaskList?.title else { completion(.needsValue()) return } let possibleLists = getPossibleLists(for: title) completeResolveTaskList(with: possibleLists, for: title, with: completion) }
completeResolveTaskList
sama seperti completeResolveListName
, tetapi dengan tipe yang sedikit berbeda (daftar tugas alih-alih judul daftar tugas).
public func completeResolveTaskList(with possibleLists: [INSpeakableString], for listName: INSpeakableString, with completion: @escaping (INTaskListResolutionResult) -> Void) { let taskLists = possibleLists.map { return INTaskList(title: $0, tasks: [], groupName: nil, createdDateComponents: nil, modifiedDateComponents: nil, identifier: nil) } switch possibleLists.count { case 0: completion(.unsupported()) case 1: if possibleLists[0].spokenPhrase.lowercased() == listName.spokenPhrase.lowercased() { completion(.success(with: taskLists[0])) } else { completion(.confirmationRequired(with: taskLists[0])) } default: completion(.disambiguation(with: taskLists)) } }
Ia memiliki logika disambiguasi yang sama dan berperilaku dengan cara yang persis sama. Mengatakan "Toko" perlu disamarkan, dan mengatakan "Toko Kelontong" akan sama persis.
Kami akan membiarkan confirm
tidak diterapkan dan menerima default. Untuk handle
, kita perlu menambahkan item ke daftar dan menyimpannya.
func handle(intent: INAddTasksIntent, completion: @escaping (INAddTasksIntentResponse) -> Void) { var lists = loadLists() guard let taskList = intent.targetTaskList, let listIndex = lists.index(where: { $0.name.lowercased() == taskList.title.spokenPhrase.lowercased() }), let itemNames = intent.taskTitles, itemNames.count > 0 else { completion(INAddTasksIntentResponse(code: .failure, userActivity: nil)) return } // Get the list var list = lists[listIndex] // Add the items var addedTasks = [INTask]() for item in itemNames { list.addItem(name: item.spokenPhrase, at: list.items.count) addedTasks.append(INTask(title: item, status: .notCompleted, taskType: .notCompletable, spatialEventTrigger: nil, temporalEventTrigger: nil, createdDateComponents: nil, modifiedDateComponents: nil, identifier: nil)) } // Save the new list lists[listIndex] = list save(lists: lists) // Respond with the added items let response = INAddTasksIntentResponse(code: .success, userActivity: nil) response.addedTasks = addedTasks completion(response) }
Kami mendapatkan daftar item dan daftar target. Kami mencari daftar dan menambahkan item. Kami juga perlu menyiapkan respons untuk Siri untuk ditampilkan dengan item yang ditambahkan dan mengirimkannya ke fungsi penyelesaian.
Fungsi ini dapat menangani frasa seperti, "Di ListOMat, tambahkan apel ke daftar belanjaan." Itu juga dapat menangani daftar barang-barang seperti, "nasi, bawang, dan zaitun."

Hampir Selesai, Hanya Beberapa Pengaturan Lagi
Semua ini akan berfungsi di simulator atau perangkat lokal Anda, tetapi jika Anda ingin mengirimkan ini, Anda harus menambahkan kunci NSSiriUsageDescription
ke daftar aplikasi plist
, dengan string yang menjelaskan untuk apa Anda menggunakan Siri. Sesuatu seperti "Permintaan Anda tentang daftar akan dikirim ke Siri" baik-baik saja.
Anda juga harus menambahkan panggilan ke:
INPreferences.requestSiriAuthorization { (status) in }
Letakkan ini di viewDidLoad
pengontrol tampilan utama Anda untuk meminta akses Siri kepada pengguna. This will show the message you configured above and also let the user know that they could be using Siri for this app.

Finally, you'll need to tell Siri what to tell the user if the user asks what your app can do, by providing some sample phrases:
- Create a
plist
file in your app (not the extension), namedAppIntentVocabulary.plist
. - Fill out the intents and phrases that you support.

AppIntentVocabulary.plist
to list the sample phrases that will invoke the intent you handle. (Pratinjau besar)There is no way to really know all of the phrases that Siri will use for an intent, but Apple does provide a few samples for each intent in its documentation. The sample phrases for task-list searching show us that Siri can understand “Show me all my notes on <appName>,” but I found other phrases by trial and error (for example, Siri understands what “lists” are too, not just notes).
Ringkasan
As you can see, adding Siri support to an app has a lot of steps, with a lot of configuration. But the code needed to handle the requests was fairly simple.
There are a lot of steps, but each one is small, and you might be familiar with a few of them if you have used extensions before.
Here is what you'll need to prepare for a new extension on Apple's developer website:
- Make an app ID for an Intents extension.
- Make an app group if you don't already have one.
- Use the app group in the app ID for the app and extension.
- Add Siri support to the app's ID.
- Regenerate the profiles and download them.
And here are the steps in Xcode for creating Siri's Intents extension:
- Add an Intents extension using the Xcode template.
- Update the entitlements of the app and extension to match the profiles (groups and Siri support).
- Add your intents to the extension's
plist
.
And you'll need to add code to do the following things:
- Use the app group sandbox to communicate between the app and extension.
- Add classes to support each intent with resolve, confirm and handle functions.
- Update the generated
IntentHandler
to use those classes. - Ask for Siri access somewhere in your app.
Finally, there are some Siri-specific configuration settings:
- Add the Siri support security string to your app's
plist
. - Add sample phrases to an
AppIntentVocabulary.plist
file in your app. - Run the intent target to test; edit the scheme to provide the phrase.
OK, that is a lot, but if your app fits one of Siri's domains, then users will expect that they can interact with it via voice. And because the competition for voice assistants is so good, we can only expect that WWDC 2018 will bring a bunch more domains and, hopefully, much better Siri.
Bacaan lebih lanjut
- “SiriKit,” Apple
The technical documentation contains the full list of domains and intents. - “Guides and Sample Code,” Apple
Includes code for many domains. - “Introducing SiriKit” (video, Safari only), WWDC 2016 Apple
- “What's New in SiriKit” (video, Safari only), WWDC 2017, Apple
Apple introduces lists and notes - “Lists and Notes,” Apple
The full list of lists and notes intents.