Bagaimana kami meluncurkan 2GIS di bawah CarPlay dan kami masih mengurai


Hai Nama saya Vanya, saya sedang menulis aplikasi seluler 2GIS untuk iOS. Hari ini akan ada cerita tentang bagaimana navigator kami muncul di CarPlay. Saya akan memberi tahu Anda bagaimana dengan dokumentasi dan alat yang belum selesai tersebut kami membuat produk yang berfungsi dan menempatkannya di AppStore.


Beberapa kata tentang CarPlay



Pertama, sedikit bahan untuk memahami beberapa aspek CarPlay dan alasan mengapa kami membuat keputusan tertentu.


CarPlay bukan OS di dalam OS lain, karena begitu banyak artikel menulis tentang itu. Jika kira-kira, maka CarPlay adalah protokol untuk bekerja dengan tampilan eksternal layar unit kepala; suara dari speaker mobil; layar sentuh, panel sentuh, mesin cuci, dan perangkat input lainnya.


Artinya, seluruh kode yang dapat dieksekusi terletak langsung di aplikasi utama (bahkan tidak dalam ekstensi terpisah!) Ini sangat keren: untuk mendapatkan fitur baru, Anda tidak perlu memperbarui radio atau bahkan mesin, Anda hanya perlu memperbarui iOS.


Di WWDC 2018 Keynote, kami diberi kesempatan untuk membuat aplikasi navigasi untuk CarPlay, yang membuat kami sangat bahagia. Segera setelah presentasi, kami mengirim permintaan izin untuk mengembangkan untuk CarPlay. Dalam permintaan itu, perlu untuk menunjukkan bahwa aplikasi kita mampu navigasi.


Sementara kami menunggu jawaban dari Apple, ada sebuah ceramah di mana, menggunakan contoh aplikasi CountryRoads, berbicara tentang bekerja dengan CarPlay.framework. Ceramah tidak berbicara tentang jebakan dan seluk beluk ketika bekerja dengan CarPlay, tetapi menyebutkan bahwa setelah terhubung ke radio CarPlay, aplikasi akan bekerja dalam mode latar belakang.


Tongkat pertama di roda


Aplikasi di latar belakang mengecewakan kami. Ada dua alasan untuk ini:


  1. Kami tidak bekerja di latar belakang. Setelah meninggalkan batasan ini karena alasan teknis dan untuk konservasi energi.
  2. Peta kami ditulis dalam OpenGL (ya, usang, ya, bukan Logam, kita semua tahu itu), dan OpenGL dalam kondisi latar belakang tidak berfungsi. Paling-paling, Anda mendapatkan tampilan hitam, dan paling buruk, crash.

Itu masih mungkin untuk mengatasi pekerjaan di latar belakang, tetapi kartu pasti perlu dipecahkan. Kemudian muncul ide untuk membuatnya melalui standar MKMapView. Sampai Anda mulai melempari kami dengan batu untuk ide menggunakan kartu Apple standar, saya akan jelaskan: kami akan menggunakan MKMapView, tetapi bukan kartu Apple.


Faktanya adalah bahwa MKMapView dapat memuat ubin pihak ketiga. Ubin adalah wadah persegi panjang khusus untuk tekstur. Kami baru saja berubah menjadi servochka yang tahu cara memberi ubin. Ada kode implementasi di GitHub.


Jawaban Apple


Kami menerima jawaban dari Apple, di mana, selain izin untuk mengembangkan, kami juga menerima dokumentasi "untuk elite", kode aplikasi sampel CountryRoads (ditunjukkan pada kuliah WWDC) dan, yang paling penting, kunci kapabilitas pribadi com.apple.developer.carplay-maps . Kunci ini ditulis dalam file hak dengan nilai YA, sehingga sistem memahami bahwa Anda dapat memproses acara dari CarPlay ketika aplikasi Anda mulai.


Tanpa menunggu sprint dengan cerita yang dipilih untuk pengembangan, saya naik untuk mengunduh Xcode Beta. Upaya pertama untuk mengumpulkan 2GIS gagal. Tetapi proyek aplikasi sampel CoutryRoads dapat dirakit untuk simulator.


Sebelum setiap pembukaan jendela simulator CarPlay, yang terakhir harus disesuaikan melalui jendela seperti itu:



Untuk melakukan ini, Anda harus menulis baris di terminal: defaults write com.apple.iphonesimulator CarPlayExtraOptions -bool YES


Untuk beberapa alasan, ini tidak berhasil - saya harus menjalankannya di hampir simulator terkecil dengan resolusi 800 × 480 poin dan skala × 2. Saat ini, pengaturan ini berfungsi dan banyak membantu.


Setelah membuat proyek sampel saya dan dipersenjatai dengan dokumentasi, saya mulai mengerti apa yang terjadi.
Hal pertama yang saya sadari: aplikasi navigasi untuk CarPlay terdiri dari tampilan dasar dan lapisan template.



Tampilan dasar adalah peta Anda. Pada layer ini seharusnya hanya ada peta, tidak ada tampilan dan kontrol lainnya.


Template adalah seperangkat elemen UI wajib yang hampir tidak dapat disesuaikan untuk menampilkan rute, manuver, semua jenis daftar, dan sebagainya.


Pengembangan beta


Mari beralih ke penulisan kode. Hal pertama yang harus dilakukan adalah mengimplementasikan beberapa metode CPApplicationDelegate yang diperlukan dalam file ApplicationDelegate.


 func application( _ application: UIApplication, didConnectCarInterfaceController controller: CPInterfaceController, to window: CPWindow ) {} func application( _ application: UIApplication, didDisconnectCarInterfaceController controller: CPInterfaceController, from window: CPWindow ) {} 

Mari kita lihat tanda tangan:


Dengan aplikasi UIA, semuanya jelas.
CPWindow adalah penerus UIWindow, jendela untuk tampilan eksternal unit kepala radio.
CPInterfaceController - sesuatu seperti analog dari UINavigationController, hanya dari CarPlay.framework.


Sekarang kita melanjutkan langsung ke implementasi metode.


 func application( _ application: UIApplication, didConnectCarInterfaceController controller: CPInterfaceController, to window: CPWindow ) { let carMapViewController = CarMapViewController( interfaceController: controller ) let navigationController = UINavigationController( rootViewController: carMapViewController ) window.rootViewController = navigationController } 

Di didConnect, Anda perlu menulis kode yang mirip dengan yang kita lihat di didFinishLaunching. CarMapViewController adalah tampilan dasar (pengontrol sebenarnya, tapi ok), sesuai dokumentasi.


Inilah gambar yang akhirnya saya dapatkan:



Di suatu tempat saat ini, saya sadar bahwa sistem build baru Xcode baru diaktifkan secara default dan, kemungkinan besar, karena hal ini, 2GIS tidak akan melakukannya.


Saya membuka Xcode, menginstal warisan (atau lebih tepatnya stabil, mari kita sebut sekop sekop) membangun sistem, dan teori saya dikonfirmasi: 2GIS telah dirakit.


Setelah menetapkan kunci kapabilitas yang sama, saya meluncurkan 2GIS di bawah CarPlay dan tidak melihat log tentang pengalihan aplikasi ke mode latar belakang. Itu menjadi lebih tidak bisa dipahami, karena insinyur Apple dari tempat kejadian mengatakan tentang mode latar belakang, tetapi, di sisi lain, mereka menjanjikan kami contentView dari UIAlertView, dan sebagai hasilnya, UIAlertView menjadi usang.


Setelah memutuskan bahwa seharusnya begitu, saya tidak repot-repot dengan MKMapView. Itu akan membuat kita offline dan membuat kita menulis ulang rendering rute.


Masalah kartu tunggal


Saya tidak punya waktu untuk bersukacita karena berita bahwa CarPlay akan memiliki peta kami, karena masalah berikut dihadapi saya: karena fitur teknis hanya ada satu peta.
Solusi cepat untuk masalah ini adalah, meskipun tidak terlalu elegan.


Biasanya, ketika menggunakan 2GIS di CarPlay, telepon terkunci dan terletak di suatu tempat di rak. Jadi peta pada saat ini di telepon tidak benar-benar diperlukan (tidak ada ruginya mencari, tentu saja). Karena itu, ketika kami menghubungkan ponsel ke CarPlay, kami memutuskan untuk mengambil kartu dari aplikasi utama dan menampilkannya di layar CarPlay radio. Dan ketika terputus, masing-masing, kembali ke aplikasi di telepon.


Ya, itu solusi untuk dirinya sendiri, tetapi cepat, masih berfungsi dan tidak perlu menendang beberapa perintah lain untuk memukau MVP.


Kontrol pada peta


Jadi, kami punya peta kami di layar radio. Sekarang perlu untuk melakukan hal-hal pertama dan jelas untuk setiap peta: kontrol untuk zoom, lokasi saat ini dan pergerakan peta.



Mari kita mulai dengan zoom dan lokasi saat ini, karena kontrol ini terletak di peta itu sendiri dan ini bukan UIControl biasa. Seperti yang saya tulis di atas, hanya peta yang ada di tampilan dasar.


Untuk menempatkan kontrol-kontrol ini pada kartu, saya harus masuk ke dokumentasi dan aplikasi sampel lagi. Di sana saya membaca tentang templat pertama - CPMapTemplate.



CPMapTemplate - templat transparan untuk menampilkan beberapa kontrol pada peta dan analog dari navigationBar. Itu dibuat dan diatur seperti ini:


 let mapTemplate = CPMapTemplate() self.interfaceController.setRootTemplate(mapTemplate, animated: false) 

Selanjutnya, Anda perlu membuat kontrol ini dan meletakkannya di kartu.


 let zoomInButton = CPMapButton(…) let zoomOutButton = CPMapButton(…) let myLocationButton = CPMapButton(…) self.mapTemplate.mapButtons = [ zoomInButton, zoomOutButton, myLocationButton ] 

Tetapi array mapButtons ternyata lucu, karena tidak peduli berapa banyak elemen yang Anda masukkan, hanya akan mengambil tiga elemen pertama dan menampilkannya di layar. Anda tidak akan menerima kesalahan dalam log atau pernyataan.


Kemudian saya melihat bagaimana saya bisa membuat peta bergerak, dan saya menemukan ini di dokumentasi:


 Navigation apps are designed to work with a variety of car input devices, and CarPlay does not support direct user interaction in the base view (apps do not directly receive tap or drag events). 

Aneh, pikirku, dan harus menyaksikan bagaimana ini dilakukan dalam aplikasi sampel CountryRoads. Jawabannya adalah melalui antarmuka ini:



Sangat tidak nyaman, tetapi dengan cara yang berbeda, dokumentasi tidak akan berbohong, kan?


Karena tempat untuk kontrol pada peta yang telah kami habis, maka perlu untuk membuat tombol untuk menempatkan peta dalam mode "seret" dalam analog ini dari navigationBar.


 let panButton = CPBarButton(…) self.mapTemplate.leadingNavigationBarButtons = [panButton] self.mapTemplate.trailingNavigationBarButtons = [] 

Tetapi array dari leadingNavigationBarButtons dan trailingNavigationBarButtons juga bukan tanpa lelucon: berapa banyak elemen di dalamnya yang didorong, mereka hanya akan mengambil dua yang pertama. Juga tanpa kesalahan dalam log dan pernyataan.


Dan untuk mengaktifkan dan menonaktifkan mode seret dan lepas kartu, Anda harus menulis:


 self.mapTemplate.showPanningInterface(animated: true) self.mapTemplate.dismissPanningInterface(animated: true) 

Membangun dan menampilkan rute di peta


Selanjutnya, saya mulai menggunakan kembali API kami yang ada untuk membangun rute.


Hanya untuk demo dan memahami apa dan bagaimana melakukannya, saya memutuskan untuk mengambil dua poin dan membangun rute di antara mereka. Titik A adalah lokasi pengguna, dan titik B adalah kantor utama kami di Novosibirsk.


Kode
 let choice0 = CPRouteChoice( summaryVariants: ["46 "], additionalInformationVariants: ["  "], selectionSummaryVariants: ["1  7 "] ) let choice1 = CPRouteChoice( summaryVariants: ["46 "], additionalInformationVariants: ["  "], selectionSummaryVariants: [“1  11 "] ) let startItem = MKMapItem(…) let endItem = MKMapItem(…) endItem.name = ",  ” let trip = CPTrip( origin: startItem, destination: endItem, routeChoices: [choice0, choice1] ) let tripPreviewTextConfiguration = CPTripPreviewTextConfiguration( startButtonTitle: " ”, additionalRoutesButtonTitle: “”, overviewButtonTitle: "" ) self.mapTemplate.showTripPreviews( [trip], textConfiguration: tripPreviewTextConfiguration ) 

Di layar kami mendapat kontrol dengan deskripsi rute:



Mode navigasi


Rute bagus, tetapi fitur utama navigator adalah navigasi. Agar muncul, Anda harus menulis yang berikut:


 func mapTemplate( _ mapTemplate: CPMapTemplate, startedTrip trip: CPTrip, using routeChoice: CPRouteChoice ) { self.navigationSession = self.mapTemplate.startNavigationSession(for: trip) } 

CPNavigationSession - kelas di mana Anda dapat menampilkan beberapa elemen UI yang hanya diperlukan dalam mode navigasi.


Untuk menampilkan manuver, Anda harus:


 let maneuver = CPManeuver() maneuver.symbolSet = CPImageSet( lightContentImage: icon, darkContentImage: darkIcon ) maneuver.instructionVariants = [". "] maneuver.initialTravelEstimates = CPTravelEstimates(…) self.navigationSession?.upcomingManeuvers = [maneuver] 

Kemudian di layar radio kita mendapatkan ini:



Untuk memperbarui rekaman untuk bermanuver, Anda harus:


 let estimates = CPTravelEstimates(…) self.navigationSession?.updateEstimates(estimates, for: maneuver) 

Itu hanya bekerja!


Ketika fungsionalitas dasar untuk navigator siap, saya memutuskan untuk menampilkan kerajinan ini dalam presentasi internal. Presentasi itu sukses: semua orang mendapat ide untuk menyelesaikan, menguji dan meluncurkan navigator sesegera mungkin.


Pertama-tama, kami memesan unit kepala nyata dengan dukungan CarPlay. Dan kemudian, seperti yang mereka katakan, panas mulai.


PIONEER AVH-Z500BT


Profil Penyediaan


Karena penambahan kunci kemampuan baru, profil perlu dibuat ulang. Dalam perkembangan normal, kami tidak memikirkannya, karena Xcode akan melakukan semuanya sendiri. Tetapi tidak dalam kasus kunci pribadi.


 Code Signing Error: Automatic signing is unable to resolve an issue with the "v4ios" target's entitlements. Automatic signing can't add the com.apple.developer.carplay-maps entitlement to your provisioning profile. Switch to manual signing and resolve the issue by downloading a matching provisioning profile from the developer website. 

Itu juga melanggar CI kami, karena untuk distribusi versi aplikasi lokal kami menggunakan akun perusahaan, di mana kami tidak meminta izin untuk mengembangkan aplikasi untuk CarPlay. Tetapi ini adalah kisah yang sangat berbeda.


Debugging


Anda dapat terhubung ke CarPlay melalui Bluetooth atau Lightning. Praktek menunjukkan bahwa metode kedua jauh lebih populer. Radio kami di Bluetooth tidak tahu caranya, jadi selama pengembangan saya harus menggunakan debug Wi-Fi. Jika Anda mencobanya pada proyek yang lebih sulit daripada hello world, maka Anda tahu apa itu.


Dan bagi mereka yang belum mencoba, saya katakan:

Saya mengumpulkan aplikasi melalui kabel ke telepon, dan hanya kemudian, menghubungkan telepon ke CarPlay, melalui Wi-Fi, mengunggahnya ke telepon dan menjalankannya selama beberapa menit.
Menyalin aplikasi ke ponsel adalah sekitar 3 menit, meluncurkan aplikasi selama sekitar satu menit, dan hanya setelah memulai berhenti di breakpoint hanya 15 detik kemudian.


Dan kemudian menjadi sangat menarik bagi saya mengapa Apple tidak membuat DevKit (sehingga cara Apple, hanya berfungsi dan itu saja). Sangat tidak nyaman untuk memasang test stand tanpa itu. Sampai sekarang, setiap dua minggu sekali, ada sesuatu yang jatuh - Anda harus ingat dari foto apa yang harus Anda masukkan. Adalah baik bahwa admin, ketika merakit stand ini, mengatakan apa dan mengapa.


Kerangka kerja terbaik yang pernah kami buat


Pada akhirnya, ketika semuanya dipasang pada perangkat nyata, menjadi jelas bahwa fitur "2GIS untuk CarPlay" pasti akan menjadi. Inilah saatnya untuk melakukan kecantikan.


Masalah viewport


Itu perlu untuk mengkonfigurasi viewport peta untuk menggambar rute di daerah tanpa kontrol yang tidak perlu, dan tidak hanya di tengah. Singkatnya, agar terlihat berbeda:



Jadi:



Saya berharap mendapatkan semacam layoutGuide dengan area yang terlihat saat ini. Sehingga ia memperhitungkan navigasiBar, tampilan dengan rute, dan kontrol pada peta. Padahal, saya tidak mendapatkan apa-apa. Masih belum jelas cara mengkonfigurasi viewport, jadi kami memiliki hardcode seperti:


 let routeControlsWidth = self.view.frame.width * 0.48 let zoomControlWidth = self.view.frame.width * 0.15 

Konstruksi lorong tidak hanya antara dua titik


Dalam rilis pertama, kami memutuskan untuk mengambil rubrikator kami yang dibuat melalui CPGridTemplate:



Favorit dan Rumah / Kerja melalui CPListTemplate.



Dan pencarian keyboard melalui CPSearchTemplate:



Saya tidak akan menunjukkan kode tentang template, karena sederhana dan dokumentasi tentang itu ditulis dengan baik (setidaknya tentang sesuatu).


Namun, perlu disebutkan masalah apa yang ditemukan saat bekerja dengan mereka.

CPInterfaceController dapat di navigasi mirip dengan UIKit. yaitu


 self.interfaceController.pushTemplate(listTemplate, animated: true) self.interfaceController.presentTemplate(alertTemplate, animated: true) 

Tetapi jika Anda mencoba menjalankan, misalnya, CPAlertTemplate, Anda akan menerima penegasan dalam log bahwa CPAlertTemplate hanya dapat diwakili secara modalnya.


Tidak jelas mengapa Apple tidak menyembunyikan logika tahapan di bawah tenda tanpa membuat antarmuka seperti:


 self.interfaceController.showTemplate(listTemplate, animated: true) 

Itu juga mematahkan kemampuan untuk menggunakan pewaris CPTemplate, seperti pengontrol di UIKit.


Ketika Anda mencoba, misalnya, untuk menempatkan pewaris Anda di tumpukan template, Anda mendapatkan ini:


 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported object <YourAwesomeGridTemplate: 0x60000060dce0> <identifier: 6CAC7E3B-FE70-43FC-A8B1-8FC39334A61D, userInfo: (null)> passed to pushTemplate:animated:. Allowed classes: {( CPListTemplate, CPGridTemplate, CPSearchTemplate, CPMapTemplate )}' 

Pengujian dan bug


Diuji oleh artemenko-aa . Salah satu bug pertama yang dia temukan, masih belum bisa kita perbaiki.


Faktanya adalah bahwa ketika Anda memutuskan sambungan telepon dari radio CarPlay, Watchdog memakukan kami secara sporadis - tanpa menjelaskan alasannya. Bahkan syslog dibuka, tidak ada yang jelas. Jadi, jika Anda memiliki ide untuk memperbaiki atau memahami alasannya, silakan berkomentar.


Bug berikutnya berada di tempat yang sama, tetapi dengan perilaku khusus. Saya menulis di atas bahwa metode didDisconnect dari CPApplicationDelegate dipanggil ketika telepon terputus dari CarPlay. Dan dalam metode ini, kami mengembalikan kartu dari layar radio kembali ke aplikasi utama. Bayangkan berapa banyak masalah yang akan kita tangkap jika metode ini tidak dipanggil setidaknya satu dari lima.


Menjadi jelas bahwa ini adalah masalah iOS, dan bukan khusus aplikasi kami, karena seluruh sistem percaya bahwa itu terhubung ke CarPlay.



Saya bahkan melaporkannya sebagai radar (seperti semua bug lainnya). Saya diminta untuk menjatuhkan log dengan profil seperti itu, tetapi saya tidak bisa menjawab dukungan untuk beberapa waktu, jadi mereka menutup radar.


Karena Apple tidak berencana untuk melakukan apa pun, masalahnya harus dilewati sendiri, seperti yang sering direproduksi.


Dan kemudian saya ingat bahwa bagian terbesar dari koneksi ke CarPlay melewati Lightning. Ini berarti bahwa telepon sedang diisi pada saat koneksi, dan pada saat pemutusan, pengisian berhenti. Dan jika demikian, maka Anda dapat berlangganan status baterai dan mencari tahu kapan ponsel berhenti mengisi daya dan terputus dari CarPlay.


Skema ini lemah, tetapi kami tidak punya pilihan. Kami pergi ke sini, dan itu berhasil!



Untungnya, kruk ini telah lama dihapus dari kode: Pengembang Apple memperbaiki semua yang ada di salah satu rilis iOS.


Kisah dua editor


Arahan ulang terkait dengan metadata. Teks editorial mengatakan bahwa deskripsi kami (bukan catatan rilis) tidak mengatakan bahwa kami mendukung CarPlay. Seperti yang bisa Anda tebak, baik pedoman peninjauan, maupun Google Maps yang sama tidak memiliki ini. Kami tidak berdebat (karena biasanya lebih lama dari mengedit metadata), kami menyalin garis dari Catatan Rilis ke Deskripsi dan mulai menunggu tinjauan baru.


Reduksi kedua terjadi karena daftar kota. 2GIS memiliki fitur yang sangat keren - mode operasi offline penuh. Fitur ini menembak kaki kita.


Saat menghubungkan aplikasi tanpa kota yang ditetapkan ke CarPlay, kami tidak menunjukkan peta, karena tidak ada yang ditampilkan. Dan untuk ini kami dijadwalkan. Solusinya sederhana: peringatan tanpa tombol, yang mengatakan bahwa Anda harus mengunduh kota.



Apa yang tidak bisa Anda bicarakan


Gerakan Peta Gerakan


Sekitar waktu yang sama, navigator di bawah CarPlay dari Google Maps keluar - dan di sana Anda dapat memindahkan peta dengan gerakan di sekitar layar. API pribadi, saya pikir, ini jelas! Orang-orang dari Google baru saja datang dari gedung terdekat dan mengatakan apa yang mereka butuhkan. Bagaimanapun, dokumentasi mengatakan:


 Navigation apps are designed to work with a variety of car input devices, and CarPlay does not support direct user interaction in the base view (apps do not directly receive tap or drag events). 

Namun, saya masih memutuskan untuk memastikan dan mendapatkan Google, meskipun hampir tidak ada gunanya, karena tidak ada artikel teknis tentang Aplikasi Navigasi CarPlay. Namun, saya berhasil menemukan sesuatu yang bermanfaat dan, SUDDENLY, di situs web Apple .


Dalam pedoman saya menemukan video yang mengatakan bahwa dokumentasi itu berbohong dengan tidak bijaksana. Video menunjukkan bagaimana Anda masih bisa menyeret peta dengan gerakan. Saya menyadari bahwa saya tidak mengerti apa-apa, dan satu-satunya yang tersisa bagi saya adalah membuka CarPlay.framework dan meninjau semua file .h.


Dan lihatlah! Saya menemukan di CPMapTemplate delegasinya CPMapTemplateDelegate, di mana ada 3 metode yang berteriak bahwa jika Anda menerapkannya, Anda bisa mendapatkan kendali atas gerakan peta.


3 metode

/ * Disebut ketika gerakan panci dimulai. Mungkin tidak dipanggil saat terhubung ke beberapa sistem CarPlay.
/
func publik opsional mapTemplateDidBeginPanGesture (_ mapTemplate: CPMapTemplate)


/ * Dipanggil ketika gerakan panci berubah. Mungkin tidak dipanggil saat terhubung ke beberapa sistem CarPlay.
/
opsional public func mapTemplate (_ mapTemplate: CPMapTemplate, didUpdatePanGestureWith Terjemahan terjemahan: CGPoint, velocity: CGPoint)


/ * Disebut ketika gerakan panci berakhir. Mungkin tidak dipanggil saat terhubung ke beberapa sistem CarPlay.
/
opsional public func mapTemplate (_ mapTemplate: CPMapTemplate, didEndPanGestureWithVelocity velocity: CGPoint
)


Saya menerapkannya dan menjalankan aplikasi pada simulator - tidak ada yang berhasil. Tidak punya waktu untuk kecewa, saya menyadari bahwa simulator dapat memiliki kualitas yang sama dengan dokumentasi, dan meletakkannya di perangkat. Semuanya dimulai, kebahagiaan tidak mengenal batas!


Fakta menyenangkan: radio CarPlay membutuhkan seperempat layar untuk memahami bahwa gerakan panci telah dimulai. Saya ingin mencatat bahwa UIPanGestureRecognizer hanya membutuhkan 10 poin.


Keseragaman UI pada berbagai tape recorder radio


Kami menerima banding dalam dukungan: pengguna hanya memiliki satu sajest merangkak keluar dalam pencarian, meskipun mungkin ada lebih banyak. Aneh, pikirku, karena di semua layar hanya satu baris yang cocok. Telah meminta tangkapan layar:



Dan ini sangat berbeda dari UI CPSearchTemplate yang saya perlihatkan di atas. Dan ini harus diperhitungkan selama pengembangan, meskipun masih tidak mungkin untuk memahami berapa banyak sel dalam plat di bawah ini yang dapat masuk ke layar.


Kontrol Batas Kecepatan


Kami melihat statistik dan menyadari bahwa mereka menggunakan navigator untuk CarPlay dan kami harus membawanya setidaknya ke level navigator di aplikasi utama. Pertama-tama, kami memutuskan untuk menambahkan kontrol batas kecepatan. Tentu saja, ada beberapa masalah.


Pertanyaan nomor satu: tempat ke mana?


Mengaduk-aduk file .h di CPWindow lagi, saya menemukan layoutGuide yang aneh:
var mapTombolSafeAreaLayoutGuide: UILayoutGuide


Dan ternyata itulah yang kami butuhkan. Kontrol kami cocok dengan sempurna:




Pertanyaan nomor dua: apakah ini pada umumnya sah?


Faktanya adalah bahwa secara teknis kontrol ada di tampilan dasar. Dan tampilan dasar menurut dokumentasi tidak dapat berisi apa pun kecuali peta:


 The base view is where the map is drawn. The base view must be used exclusively to draw a map, and may not be used to display other UI elements. Instead, navigation apps overlay UI elements such as the navigation bar and map buttons using the provided templates. 

Tetapi pengulas merindukan kami di AppStore, yang berarti bahwa kontrol yang berkaitan dengan navigasi masih dapat dibuat.


Pencarian suara




Dalam cara yang baik, fitur ini harus dilakukan terlebih dahulu, tetapi kami telah mengakumulasikan beberapa tugas dari hutang teknis yang mencegah implementasi pencarian suara untuk CarPlay. Dan tugas ini tidak sesederhana kelihatannya.


Masalah pertama: animasi. Faktanya adalah bahwa dalam CPVoiceControlTemplate tidak ada cara untuk membuat animasi standar. Animasi untuk pengenalan suara dan pencarian harus dikumpulkan frame-by-frame dari gambar dan menunjukkan berapa lama mereka pergi.


 for i in 1...12 { if let image = UIImage(named: "carplay_searching_\(i)") { images.append(image) } } let image = UIImage.animatedImage(with: images, duration: 0.96) 

Kelihatannya, seperti yang Anda duga, tidak terlalu, tetapi saya tidak ingin mengembang ukuran aplikasi.


Masalah kedua: mengakses. Lansiran untuk akses mikrofon dan pengenalan suara muncul di layar ponsel. Saya harus menulis di layar radio bahwa pengguna perlu mengangkat telepon, memberikan izin dan hanya kemudian menggunakan navigator di radio. Sangat nyaman!


Mobil penggerak kanan.


Kami dikirim tangkapan layar di mana UI seluruh aplikasi terbalik!



Dan, tentu saja, viewport map tetap seperti yang kita lakukan dengan hardcode, karena tidak ada yang berharap bahwa ada pengaturan terpisah untuk mobil drive kanan. Saya tidak menemukan cara untuk mengatasi ini "dengan benar", tetapi saya perhatikan bahwa, karena kontrol batas kecepatan kami terletak pada layoutGuide untuk kontrol peta, ia bergerak ke sisi kiri.


Ultrafix tidak akan datang. Mereka melakukannya dengan kasar, tetapi berhasil.


 let isLeftWheelCar = self.speedControlViewController.view.frame.origin.x > self.view.frame.size.width / 2.0 

, , .


. CarPlay, , . , , Apple .

Source: https://habr.com/ru/post/id452638/


All Articles