Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. iOS SDK

Bekerja dengan NSURLSession: Bagian 4

by
Read Time:21 minsLanguages:
This post is part of a series called Working with NSURLSession.
Working with NSURLSession: Part 3
Working with NSURLSession: AFNetworking 2.0

Indonesian (Bahasa Indonesia) translation by Yudha Zubair (you can also view the original English article)

Dalam tutorial sebelumnya, kami mulai membuat klien podcast sederhana untuk menerapkan apa yang telah kami pelajari tentang NSURLSession. Sejauh ini, klien podcast kami dapat menanyakan API Pencarian iTunes, mengunduh feed podcast, dan menampilkan daftar episode. Dalam tutorial ini, kami memperbesar aspek menarik lain dari NSURLSession, unduhan yang tidak diproses. Mari saya tunjukkan cara kerjanya.


Pengenalan

Dalam tutorial keempat dan terakhir tentang NSURLSession ini, kita akan melihat lebih dekat tugas out-of-process, khususnya tugas mengunduh. Klien podcast kami sudah dapat menampilkan daftar episode, tetapi saat ini tidak memiliki kemampuan untuk mengunduh masing-masing episode. Itu akan menjadi fokus tutorial ini.

Unggahan dan Unduhan Latar Belakang

Menambahkan dukungan untuk unggahan latar belakang dan unduhan ternyata mudah dengan NSURLSession. Apple menyebutnya sebagai unggahan dan unduhan out-of-process  dalam proses karena tugas dikelola oleh daemon latar belakang, bukan aplikasi Anda. Sekalipun aplikasi Anda berhenti saat tugas unggah atau unduh, tugas itu berlanjut di latar belakang.

Ikhtisar

Saya ingin mengambil beberapa saat untuk melihat lebih dekat bagaimana tugas out-of-process berjalan. Ini sangat sederhana setelah Anda memiliki gambaran lengkap prosesnya. Mengaktifkan unggahan dan unduhan latar belakang tidak lebih dari membalik saklar dalam konfigurasi sesi Anda. Dengan objek sesi yang dikonfigurasikan dengan benar, Anda siap menjadwalkan pengunggahan dan mengunduh tugas di latar belakang.

Saat unggahan atau unduhan dimulai, daemon latar belakang ada. Daemon menangani tugas dan mengirimkan pembaruan ke aplikasi melalui protokol delegasi yang dideklarasikan dalam API NSURLSession. Jika aplikasi Anda berhenti berjalan karena suatu alasan, tugas berlanjut di latar belakang karena itu adalah daemon yang mengelola tugas. Saat tugas selesai, aplikasi yang membuat tugas tersebut diberitahukan. Itu berhubungan kembali dengan sesi latar belakang yang menciptakan tugas dan daemon mengelola tugas menginformasikan sesi bahwa tugas selesai dan, dalam kasus tugas pengunduhan, menyerahkan file ke sesi. Sesi ini kemudian memanggil metode delegasi yang tepat untuk memastikan aplikasi Anda dapat mengambil tindakan yang sesuai, seperti memindahkan file ke lokasi yang lebih permanen. Sudah cukup teori untuk saat ini. Mari kita lihat apa yang perlu kita lakukan untuk mengimplementasikan unduhan out-of-process di Singlecast.


1. Subkelas UITableViewCell

Langkah 1: Perbarui Storyboard Utama

Saat ini, kami menggunakan sel prototipe untuk mengisi tampilan tabel. Untuk memberi kami sedikit lebih banyak fleksibilitas, kita perlu membuat subkelas UITableViewCell. Buka storyboard utama, pilih tampilan tabel instance MTViewController dan atur jumlah sel prototipe ke 0.

Update the project's main storyboard.Update the project's main storyboard.Update the project's main storyboard.

Langkah 2: Membuat Subkelas

Buka menu File Xcode dan pilih New > File .... Buat kelas Objective-C baru, beri nama MTEpisodeCell, dan pastikan itu mewarisi dari UITableViewCell. Beri tahu Xcode di mana Anda ingin menyimpan file kelas dan tekan Create.

Create a subclass of UITableViewCell.Create a subclass of UITableViewCell.Create a subclass of UITableViewCell.

Langkah 3: Perbarui Interface Kelas

interface MTEpisodeCell sederhana seperti yang Anda lihat dalam snippet kode di bawah ini. Yang kami lakukan hanyalah mendeklarasikan progress properti tipe float. Kami akan menggunakan ini untuk memperbarui dan menampilkan progres tugas unduhan yang akan kami gunakan untuk mengunduh sebuah episode.

Langkah 4: Menerapkan kelas

Implementasi MTEpisodeCell sedikit lebih terlibat, tetapi tidak rumit. Alih-alih menggunakan instance UIProgressView, kami akan mengisi tampilan konten sel dengan warna solid untuk menunjukkan progres tugas pengunduhan. Kami melakukan ini dengan menambahkan subview ke tampilan konten sel dan memperbarui lebarnya setiap kali properti progress sel berubah. Mulailah dengan mendeklarasikan properti private progressView jenis UIView.

Kami mengganti penginisialisasi kelas yang ditunjuk seperti yang ditunjukkan di bawah ini. Perhatikan bagaimana kita mengabaikan argumen style dan meneruskan UITableViewCellStyleSubtitle ke initializer yang ditunjuk superclass. Ini penting, karena tampilan tabel akan memasukan UITableViewCellStyleDefault sebagai gaya sel ketika kami meminta sel baru.

Di penginisialisasi, kami mengatur warna latar belakang teks dan label teks detail ke [UIColor clearColor] dan membuat tampilan progres. Dua detail sangat penting. Pertama, kami menyisipkan tampilan progress sebagai subview dari tampilan konten sel di index 0 untuk memastikan bahwa itu dimasukkan di bawah label teks. Kedua, kami meminta updateView untuk memastikan bahwa kerangka tampilan progres diperbarui untuk mencerminkan nilai progress, yang ditetapkan ke 0 selama inisialisasi sel.

Sebelum kita melihat implementasi dari updateView, kita perlu mengganti metode setter dari properti progress. Satu-satunya perubahan yang kami lakukan pada implementasi default setProgress: menjalankan updateView ketika variabel instance _progress diperbarui. Ini memastikan bahwa tampilan progres diperbarui setiap kali kami memperbarui properti progress sel.

Dalam updateView, kami menghitung lebar baru dari tampilan progres berdasarkan nilai properti progress sel.

Langkah 5: Menggunakan MTEpisodeCell

Untuk menggunakan MTEpisodeCell, kita perlu membuat beberapa perubahan di kelas MTViewController. Mulailah dengan menambahkan pernyataan impor untuk MTEpisodeCell.

Dalam metode viewDidLoad view controller, aktifkan setupView, metode pembantu yang akan kami terapkan selanjutnya.

Di setupView, kami memanggil setupTableView, metode pembantu lain di mana kami memberi tahu tampilan tabel untuk menggunakan kelas MTEpisodeCell setiap kali dibutuhkan sel dengan pengidentifikasi ulang EpisodeCell.

Sebelum kita membangun proyek dan menjalankan aplikasi, kita perlu memperbarui implementasi tableView:cellForRowAtIndexPath: seperti yang ditunjukkan di bawah ini.

Langkah 6: Bangun dan Jalankan

Jalankan aplikasi Anda di Simulator iOS atau pada perangkat uji untuk melihat hasilnya. Jika tidak ada yang berubah, maka Anda telah mengikuti langkah-langkah dengan benar. Semua yang telah kami lakukan sejauh ini adalah mengganti sel prototipe dengan instance MTEpisodeCell.


2. Membuat Sesi Latar Belakang

Untuk mengaktifkan unduhan out-of-process, kami memerlukan sesi yang dikonfigurasi untuk mendukung unduhan out-of-process. Ini sangat mudah dilakukan dengan API NSURLSession. Ada beberapa gotcha sekalipun.

Langkah 1: Buat Properti session

Mulailah dengan mendeklarasikan properti session baru tipe NSURLSession di kelas MTViewController dan buat kelas sesuai dengan protokol NSURLSessionDelegate dan NSURLSessionDownloadDelegate.

Di viewDidLoad, kami menetapkan properti session dengan mengaktifkan backgroundSession pada instance view controller. Ini adalah salah satu gotcha yang saya bicarakan.

Mari kita lihat implementasi backgroundSession. Di backgroundSession, kami mendeklarasikan variabel session secara statis dan menggunakan dispatch_once (Grand Central Dispatch) untuk membuat instance sesi latar belakang. Meskipun ini tidak sepenuhnya diperlukan, ini menekankan fakta bahwa kita hanya perlu satu sesi latar belakang kapan saja. Ini adalah praktik terbaik yang juga disebutkan dalam sesi WWDC di NSURLSession API.

Di blok dispatch_once, kita mulai dengan membuat objek NSURLSessionConfiguration dengan memanggil backgroundSessionConfiguration: dan memasukan string sebagai pengidentifikasi. Pengidentifikasi yang kami berikan secara unik mengidentifikasi sesi latar belakang, yang merupakan kunci seperti yang akan kita lihat nanti. Kami kemudian membuat instance session dengan menjalankan sessionWithConfiguration:delegate:delegateQueue: dan memasukan objek konfigurasi session, mengatur properti delegate session, dan memberikan nil sebagai argumen ketiga.

Dengan memasukan nil sebagai argumen ketiga dari sessionWithConfiguration:delegate:delegateQueue:, sesi membuat antrian operasi serial untuk kita. Antrian operasi ini digunakan untuk melakukan panggilan metode delegasi dan panggilan completion handler.

3. Unduh Episode

Langkah 1: Buat Tugas Unduhan

Sudah waktunya untuk memanfaatkan sesi latar belakang yang kami buat dan menggunakan MTEpisodeCell untuk digunakan. Mari kita mulai dengan mengimplementasikan metode tableView:didSelectRowAtIndexPath:, protokol UITableViewDelegate. Implementasinya sangat mudah seperti yang Anda lihat di bawah ini. Kami mengambil instance MWFeedItem yang benar dari instance array episodes dan memasukannya untuk mengunduh EpisodeWithFeedItem :.

Dalam downloadEpisodeWithFeedItem :, kami mengekstrak URL remote dari item feed dengan memanggil urlForFeedItem:, buat tugas unduhan dengan memanggil downloadTaskWithURL: pada sesi latar belakang, dan kirimkan pesan resume untuk memulai tugas unduhan.

Seperti yang mungkin sudah Anda duga, urlForFeedItem: adalah metode nyaman yang kami gunakan. Kami akan menggunakannya beberapa kali lagi dalam proyek ini. Kami memperoleh referensi ke array feed item enclosures, mengekstrak enclosure pertama, dan menarik objek untuk kunci url. Kami membuat dan mengembalikan instance NSURL.

Kami belum selesai. Apakah kompiler memberi Anda tiga peringatan? Itu tidak mengherankan karena kami belum mengimplementasikan metode yang diperlukan dari protokol NSURLSessionDelegate dan NSURLSessionDownloadDelegate. Kita juga perlu mengimplementasikan metode ini jika kita ingin menunjukkan progres tugas pengunduhan.

Langkah 2: Menerapkan Protokol

Metode pertama yang perlu kita terapkan adalah metode URLSession:downloadTask:didResumeAtOffset:. ini dipanggil jika tugas unduhan dilanjutkan. Karena ini adalah sesuatu yang tidak akan kita bahas dalam tutorial ini, kita cukup mencatat pesan ke konsol Xcode.

Yang lebih menarik adalah implementasi URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:. Metode ini dipanggil setiap kali beberapa byte diunduh oleh sesi. Dalam metode delegasi ini, kami menghitung progres, mengambil sel yang benar, dan memperbarui properti progress sel, yang pada gilirannya memperbarui tampilan progres sel. Sudahkah Anda melihat panggilan dispatch_async? Tidak ada jaminan bahwa metode delegasi dipanggil pada thread utama. Karena kami memperbarui antarmuka pengguna dengan mengatur progres sel, kami perlu memperbarui properti progress sel pada thread utama.

Implementasi cellForForDownloadTask: sangat mudah. Kami menarik URL remote dari tugas unduhan menggunakan properti originalRequest aslinya dan mengulangi item feed dalam array episodes hingga kami menemukan kecocokan. Ketika kami menemukan kecocokan, kami meminta tampilan tabel untuk sel yang sesuai dan mengembalikannya.

Metode delegasi ketiga dari protokol NSURLSessionDownloadDelegate yang perlu kita implementasikan adalah URLSession:downloadTask:didFinishDownloadingToURL:. Seperti yang saya sebutkan dalam tutorial sebelumnya, salah satu kelebihan API NSURLSession adalah bahwa unduhan langsung ditulis ke disk. Hasilnya adalah kita memberikan URL lokal di URLSession:downloadTask:didFinishDownloadingToURL:. Namun, URL lokal yang kami terima, menunjuk ke file sementara. Adalah tanggung jawab kami untuk memindahkan file ke lokasi yang lebih permanen dan itulah yang kami lakukan di URLSession:downloadTask:didFinishDownloadingToURL:.

Di moveFileWithUR:downloadTask:, kami mengekstrak nama file episode dari tugas unduhan dan membuat URL di direktori Documents aplikasi dengan menggunakan URLForEpisodeWithName:. Jika file sementara yang kami terima dari sesi latar belakang menunjuk ke file yang valid, kami memindahkan file itu ke rumah barunya di direktori Documents aplikasi.

Saya menggunakan banyak metode helper dalam proyek iOS saya, karena itu membuat kode DRY. Ini juga praktik yang baik untuk membuat metode yang hanya melakukan satu hal. Pengujian menjadi lebih mudah seperti itu.

URLForEpisodeWithName: adalah metode helper lain, yang memanggil episodesDirectory. Di URLForEpisodeWithName:, kami menambahkan argumen name ke direktori Episodes, yang terletak di direktori Documents aplikasi.

Di episodesDirectory, kami membuat URL untuk direktori Episodes dan membuat direktori jika belum ada.

Langkah 3: Bangun dan Jalankan

Jalankan aplikasi dan uji hasilnya dengan mengunduh satu episode dari daftar episode. Anda akan melihat kemajuan tampilan sel tampilan tabel dari kiri ke kanan yang mencerminkan progres tugas pengunduhan. Namun ada beberapa masalah. Sudahkah Anda mencoba scroll tampilan tabel? Itu tidak benar. Mari kita perbaiki itu.


4. Membuat Buffer Progress

Karena tampilan tabel menggunakan ulang sel sebanyak mungkin, kami perlu memastikan bahwa setiap sel mencerminkan keadaan unduhan episode yang diwakilinya dengan benar. Kami dapat memperbaikinya dengan beberapa cara. Salah satu pendekatan adalah menggunakan objek yang melacak kemajuan setiap tugas unduhan, termasuk tugas unduhan yang telah selesai.

Langkah 1: Deklarasi Properti

Mari kita mulai dengan mendeklarasikan properti private progressBuffer tipe NSMutableDictionary di kelas MTViewController.

Langkah 2: Menginisialisasi Buffer

Di viewDidLoad, kami menginisialisasi buffer progress seperti yang ditunjukkan di bawah ini.

Langkah 3: Perbarui Sel Tampilan Tabel

Kunci yang akan kami gunakan dalam dictionary adalah URL remote dari item feed yang sesuai. Dengan mengingat hal ini, kita dapat memperbarui metode tableView:cellForRowAtIndexPath: seperti yang ditunjukkan di bawah ini. Kami menarik URL remote dari item feed dan meminta nilai progressBuffer untuk kunci yang sesuai dengan URL remote. Jika nilainya tidak nil, kami mengatur properti progress sel ke nilai itu, jika tidak, kami mengatur properti progress sel ke 0,0, yang menyembunyikan tampilan progres dengan mengatur lebarnya menjadi 0,0.

Langkah 4: Hindari Duplikat

Kami juga dapat menggunakan buffer progress untuk mencegah pengguna mengunduh episode yang sama dua kali. Lihatlah implementasi tableView:didSelectRowAtIndexPath: yang diperbarui. Kami mengambil langkah yang sama dengan yang kami ambil di tableView:cellForRowAtIndexPath: untuk mengekstrak nilai kemajuan dari buffer progress. Hanya ketika nilai kemajuannya nil, kami mengunduh episode.

Langkah 5: Perbarui Buffer

Buffer progres hanya berfungsi dalam penerapannya saat ini jika kami terus memperbarui. Ini berarti bahwa kita perlu memperbarui  metode URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:. Yang kami lakukan adalah menyimpan nilai kemajuan baru di buffer progress

Di downloadEpisodeWithFeedItem:, kami menetapkan nilai progres menjadi 0,0 saat tugas unduhan dimulai.

Delegasi sesi diberitahu ketika tugas pengunduhan selesai. Di URLSession:downloadTask:didFinishDownloadingToURL:, kami menetapkan nilai progres menjadi 1.0.

Langkah 6: Kembalikan Buffer

Saat ini, buffer progress hanya disimpan dalam memori, yang berarti sudah dihapus di antara peluncuran aplikasi. Kita dapat menulis kontennya ke disk, tetapi untuk menyederhanakan aplikasi ini kita akan memulihkan atau membuat ulang buffer dengan memeriksa episode mana yang telah diunduh. Meotde feedParser:didParseFeedItem:, bagian dari protokol MWFeedParserDelegate, dipanggil untuk setiap item dalam feed. Dalam metode ini, kami menarik URL remote dari item feed, membuat URL lokal yang sesuai, dan memeriksa apakah file tersebut ada. Jika ya, maka kami menetapkan nilai progres yang sesuai untuk item feed itu ke 1.0 untuk menunjukkan bahwa item itu sudah diunduh.

Langkah 7: Bilas dan Ulangi

Jalankan aplikasi sekali lagi untuk melihat apakah masalah dengan tampilan tabel diselesaikan. Aplikasi sekarang juga harus ingat episode mana yang sudah diunduh.


5. Menjadi Warga Negara Yang Baik

Sangat penting bahwa aplikasi kita adalah warga negara yang baik dengan tidak membuang lebih banyak siklus CPU atau mengkonsumsi daya baterai lebih dari yang dibutuhkan. Apa artinya ini bagi klien podcast kami. Ketika tugas pengunduhan dimulai oleh aplikasi kami dan aplikasi berpindah ke latar belakang, daemon latar belakang yang mengelola tugas pengunduhan aplikasi kami memberi tahu aplikasi kami melalui sesi latar belakang bahwa tugas pengunduhan telah selesai. Jika perlu, daemon latar belakang akan meluncurkan aplikasi kami sehingga dapat menanggapi pemberitahuan ini dan memproses file yang diunduh.

Dalam contoh kita, kita tidak perlu melakukan sesuatu yang istimewa untuk memastikan aplikasi kita terhubung kembali ke sesi latar belakang asli. Ini diurus oleh instance MTViewController. Namun, kami harus memberi tahu sistem operasi ketika aplikasi kami selesai memproses unduhan dengan memanggil penangan penyelesaian latar belakang.

Ketika aplikasi kita dibangunkan oleh sistem operasi untuk menanggapi notifikasi dari sesi latar belakang, delegasi aplikasi akan mengirim pesan aplikasi: handleEventsForBackgroundURLSession:completionHandler:. Dalam metode ini, kita dapat menyambung kembali ke sesi latar belakang, jika perlu, dan memanggil completion handler yang diteruskan kepada kita. Dengan memanggil completion handler, sistem operasi tahu bahwa aplikasi kita tidak perlu lagi berjalan di latar belakang. Ini penting untuk mengoptimalkan masa pakai baterai. Bagaimana kita melakukan ini dalam praktik?

Langkah 1: Mendeklarasikan Properti

Pertama-tama kita perlu mendeklarasikan properti di kelas MTAppDelegate untuk menyimpan referensi ke completion handler yang kita dapatkan dari application:handleEventsForBackgroundURLSession:completionHandler. Properti harus bersifat publik. Alasan untuk ini akan menjadi jelas sebentar lagi.

Langkah 2: Implementasi Callback

Dalam application:handleEventsForBackgroundURLSession:completionHandler:, kami menyimpan completion handler di backgroundSessionCompletionHandler, yang kami nyatakan beberapa saat yang lalu.

Langkah 3: Aktifkan Handler Completion Latar Belakang

Di kelas MTViewController, kita mulai dengan menambahkan pernyataan impor untuk kelas MTAppDelegate.

Kami kemudian menerapkan metode helper lain, invokeBackgroundSessionCompletionHandler, yang memanggil completion handler latar belakang yang disimpan dalam properti backgroundSessionCompletionHandler delegasi aplikasi. Dalam metode ini, kami meminta sesi latar belakang untuk semua tugasnya yang berjalan. Jika tidak ada tugas yang berjalan, kami mendapatkan referensi ke completion handler latar belakang delegasi aplikasi dan, jika tidak nil, kami menjalankannya dan mengaturnya menjadi nil.

Tunggu sebentar. Kapan kita menjalankan invokeBackgroundSessionCompletionHandler? Kami melakukan ini setiap kali tugas pengunduhan selesai. Dengan kata lain, kami memanggil metode ini di URLSession:downloadTask:didFinishDownloadingToURL seperti yang ditunjukkan di bawah ini.


6. Membungkus

Saya harap Anda setuju bahwa klien podcast kami belum siap untuk App Store karena salah satu fitur utama, memutar podcast, masih belum ada. Seperti yang saya sebutkan dalam tutorial sebelumnya, fokus proyek ini bukan membuat klien podcast berfitur lengkap. Tujuan dari proyek ini adalah mengilustrasikan bagaimana memanfaatkan NSURLSession API untuk mencari di iTunes Search API dan mengunduh episode podcast menggunakan data dan tugas out-of-process berurutan . Anda sekarang harus memiliki pemahaman dasar tentang API NSURLSession serta tugas out-of-process.


Kesimpulan

Dengan membuat klien podcast sederhana, kami telah melihat dari dekat pada data dan tugas unduhan. Kami juga telah belajar betapa mudahnya menjadwalkan tugas unduhan di latar belakang. API NSURLSession adalah langkah maju yang penting untuk iOS dan OS X, dan saya mendorong Anda untuk memanfaatkan paket kelas yang mudah digunakan dan fleksibel ini. Dalam bagian terakhir dari seri ini, saya akan melihat AFNetworking 2.0. Mengapa ini merupakan rilis tonggak sejarah? Kapan sebaiknya Anda menggunakannya? Dan bagaimana cara membandingkannya dengan API NSURLSession?

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.