Advertisement
  1. Code
  2. iOS SDK

Bekerja dengan iCloud: Penyimpanan Dokumen

Scroll to top
Read Time: 19 min

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

Menyinkronkan data aplikasi di seluruh perangkat adalah tugas yang rumit dan menakutkan. Untungnya, itulah mengapa Apple membangun iCloud. Dalam seri Tuts+ Premium ini, Anda akan mempelajari cara kerja iCloud dan bagaimana aplikasi Anda dapat berbagi data secara lancar di berbagai perangkat.


Juga tersedia dalam seri ini:

  1. Bekerja dengan iCloud: Pendahuluan
  2. Bekerja dengan iCloud: Penyimpanan Nilai-Kunci
  3. Bekerja dengan iCloud: Penyimpanan Dokumen
  4. Bekerja dengan iCloud: Integrasi Data Inti

Dalam angsuran kedua dari seri ini, saya menunjukkan kepada Anda bagaimana cara memanfaatkan Key-Value Storage iCloud untuk menjaga sejumlah kecil data pengguna disinkronkan di beberapa perangkat. Meskipun Key-Value Storage mudah digunakan dan diadopsi, salah satu kelemahannya adalah keterbatasan jumlah data yang dapat disimpan. Ingatlah bahwa setiap aplikasi hanya dapat menyimpan data 1MB dan jumlah pasangan kunci-nilai dibatasi hingga 1024. Seperti yang saya sebutkan di akhir tutorial sebelumnya, pengelola bookmark kita mungkin mengalami keterbatasan ini jika ada pengguna yang ingin menyimpan banyak bookmark.

Solusi untuk masalah ini adalah beralih dari Penyimpanan Nilai-Kunci iCloud ke Penyimpanan Dokumen iCloud untuk menyimpan bookmark. Dalam hal ruang disk, Penyimpanan Dokumen iCloud hanya dibatasi oleh penyimpanan iCloud pengguna. Mengetahui bahwa akun gratis dilengkapi dengan penyimpanan data 5GB, iCloud Document Storage adalah solusi ideal untuk pengelola bookmark kita. Dalam tutorial ini, kita akan menolak pengelola bookmark agar tidak menggunakan iCloud Key-Value Storage untuk mengadopsi iCloud Document Storage.


Sebelum kita mulai

Saya ingin menekankan bahwa Anda harus membaca angsuran pertama dan kedua dalam seri ini sebelum membaca bagian ini. Dalam tutorial ini, kita akan memperbaiki pengelola bookmark dengan membangun fondasi yang dibuat di bagian 2 dari seri ini.


Beberapa kata tentang UIDocument

Dengan diperkenalkannya iCloud, Apple juga membuat UIDocument tersedia untuk pengembang. Para insinyur di Apple menciptakan UIDocument dengan mempertimbangkan iCloud. UIDocument membuat integrasi iCloud untuk aplikasi berbasis dokumen jauh lebih mudah. Namun, penting untuk dicatat bahwa UIDocument melakukan lebih dari sekadar menyediakan API yang mudah digunakan untuk integrasi iCloud.

Aplikasi berbasis dokumen harus berhadapan dengan sejumlah tantangan, seperti (1) membaca dan menulis data dari dan ke disk tanpa menghalangi interface pengguna, (2) menyimpan data ke disk pada interval yang sesuai, dan (3) secara opsional mengintegrasikan dengan iCloud . UIDocument menyediakan solusi bawaan untuk tantangan ini.

Sebelum kita mulai bekerja dengan UIDocument, saya ingin menjelaskan apa itu UIDocument dan apa yang tidak. UIDocument adalah objek pengontrol yang mengelola satu atau lebih model seperti halnya kontrol UIViewController dan mengelola satu atau beberapa tampilan. UIDocument tidak menyimpan data apa pun, tetapi mengelola objek model yang menyimpan data pengguna. Ini adalah konsep penting untuk dipahami, yang akan menjadi lebih jelas ketika kita mulai refactoring aplikasi kita untuk menggunakan UIDocument.

Konsep penting lainnya untuk dipahami adalah bagaimana operasi baca dan tulis bekerja saat menggunakan UIDocument. Jika Anda memutuskan untuk menggunakan UIDocument di aplikasi Anda, Anda tidak perlu khawatir tentang memblokir utas saat membaca atau menulis data ke disk. Saat menggunakan UIDocument, sistem operasi akan secara otomatis menangani sejumlah tugas untuk Anda di antrian backgound dan memastikan bahwa utas utama tetap responsif. Saya ingin mengambil waktu sejenak dan menjelaskan setiap operasi secara lebih rinci untuk memberi Anda pemahaman yang baik tentang berbagai bagian bergerak yang terlibat.

Mari kita mulai dengan membaca data dari disk. Operasi baca dimulai dengan operasi terbuka yang dimulai pada antrian panggilan. Operasi terbuka dimulai ketika dokumen dibuka dengan mengirimkannya pesan openWithCompletionHandler:. Kita melewati penangan penyelesaian yang dipanggil saat seluruh operasi baca selesai. Ini adalah aspek penting dari operasi baca dan tulis. Diperlukan waktu yang tidak sepele untuk membaca atau menulis data dari atau ke disk, dan kita tidak ingin melakukan ini pada utas utama dan memblokir interface pengguna. Operasi baca yang sebenarnya terjadi dalam antrian background yang dikelola oleh sistem operasi. Ketika operasi baca selesai, metode loadFromContents:ofType:error: dipanggil pada dokumen. Metode ini mengirimkan UIDocument data yang diperlukan untuk menginisialisasi model yang dikelolanya. Handler penyelesaian dipanggil saat proses ini selesai, yang berarti bahwa kita dapat menanggapi pemuatan dokumen dengan, misalnya, memperbarui interface pengguna dengan konten dokumen.


Operasi penulisan serupa. Ini dimulai dengan operasi simpan yang dimulai dalam antrian panggilan dengan mengirimkan saveToURL:forSaveOperation:completionHandler: ke objek dokumen. Seperti operasi baca, kita melewati penangan penyelesaian yang dipanggil saat operasi penulisan selesai. Menulis data ke disk terjadi dalam antrian background. Sistem operasi meminta UIDocument untuk snapshot data modelnya dengan mengirimkannya pesan ContentForType:error:. Handler penyelesaian dipanggil saat operasi penulisan selesai, yang memberi kita kesempatan untuk memperbarui interface pengguna.


UIDocument adalah kelas dasar dan tidak dimaksudkan untuk digunakan secara langsung. Kita perlu subkelas UIDocument dan menyesuaikannya dengan kebutuhan kita. Dengan kata lain, mensubklasifikasikan UIDocument sehingga tahu tentang model kita dan cara mengelolanya. Dalam bentuknya yang paling mendasar, subklasifikasi UIDocument hanya mengharuskan kita untuk menimpa loadFromContents:ofType:error: untuk membaca and contentForType:error:for writing.

Bingung? Anda harus. Meskipun UIDocument membuat hidup lebih mudah, ini adalah kelas yang maju dan kita sedang berhadapan dengan topik yang kompleks. Namun, saya yakin Anda akan mendapatkan pemahaman yang baik tentang aplikasi berbasis dokumen setelah kita melakukan refactored aplikasi.

Sebelum kita melanjutkan, saya ingin memperjelas apa tujuan kita untuk tutorial ini. Tujuan utamanya adalah untuk memperbaiki aplikasi kita untuk menggunakan Penyimpanan Dokumen iCloud alih-alih Penyimpanan Nilai-Kunci iCloud. Ini berarti bahwa kita akan menggunakan UIDocument dan subklasnya sesuai dengan kebutuhan. Selain itu, kita akan membuat kelas model khusus untuk bookmark yang akan digunakan dan dikelola oleh subkelas UIDocument.


Langkah 1: Mengkonfigurasi Hak

Saat ini, aplikasi kita dikonfigurasikan untuk hanya menggunakan Penyimpanan Nilai-Kunci. Untuk mengaktifkan Penyimpanan Dokumen, pertama-tama kita perlu mengkonfigurasi hak aplikasi kita. Buka Target Editor dengan memilih aplikasi kita di Project Navigator dan pilih satu-satunya target dari daftar target. Di bagian Entitlements, Anda harus melihat iCloud Containers di bawah iCloud Key-Value Store. Daftar di sebelah iCloud Containers kosong saat ini. Klik tombol tambah di bagian bawah daftar dan Anda akan melihat bahwa Xcode membuat pengidentifikasi wadah iCloud untuk Anda yang cocok dengan pengidentifikasi bundel aplikasi Anda.

Apa itu wadah iCloud? Seperti namanya, ini adalah wadah dalam penyimpanan data iCloud pengguna. Dengan menentukan satu (atau lebih) wadah iCloud dalam file hak aplikasi, kita memberi tahu sistem operasi wadah apa yang dapat diakses oleh aplikasi.



Langkah 2: Membuat Kelas Bookmark

Dalam tutorial sebelumnya, kita menyimpan setiap bookmark sebagai instance dari NSDictionary, tetapi ini bukan solusi yang baik untuk aplikasi berbasis dokumen. Sebagai gantinya, kita akan membuat kelas bookmark khusus yang memungkinkan kita untuk mengarsipkan datanya dengan mudah.

Buat subkelas NSObject baru dengan memilih File dari menu, memilih New, dan kemudian File.... Pilih Cocoa Touch dari panel kiri dan pilih Objective-C class dari daftar template di sebelah kanan. Beri kelas nama Bookmark dan pastikan itu adalah subkelas dari NSObject. Tentukan di mana Anda ingin menyimpan kelas baru dan tekan Create.



Dalam file header model, kita menambahkan dua properti model bookmark yang digunakan dalam tutorial sebelumnya, name dan URL. Kedua properti adalah instance dari NSString. Kita juga mendeklarasikan initializer yang ditunjuk, yang mengambil nama dan URL sebagai parameternya. Akhirnya, penting untuk memastikan bahwa kelas Bookmark kita sesuai dengan protokol NSCoding.

1
 
2
#import <Foundation/Foundation.h> 

3
 
4
@interface Bookmark : NSObject <NSCoding> { 
5
    NSString *_name; 
6
    NSString *_url; 
7
} 
8
 
9
@property (nonatomic, copy) NSString *name; 
10
@property (nonatomic, copy) NSString *url; 
11
 
12
- (id)initWithName:(NSString *)name andURL:(NSString *)url; 
13
 
14
@end

Dalam file implementasi model, pertama-tama kita mendefinisikan dua konstanta untuk nama dan URL bookmark. Ini adalah praktik yang baik karena akan meminimalkan kemungkinan kita salah ketik kunci yang akan digunakan segera. Selanjutnya, kita menerapkan metode inisialisasi. Metode ini sangat mudah. Kita menginisialisasi instance kita dan menetapkan nama dan URL ke variabel instance bookmark.

Bagian penting adalah menerapkan metode yang diperlukan untuk membuat kelas Bookmark sesuai dengan protokol NSCoding. Jika protokol NSCoding baru bagi Anda, maka saya mendorong Anda untuk membaca Panduan Pemrograman Arsip dan Serialisasi karena ini merupakan topik penting bagi pengembang Cocoa-Touch. Intinya adalah bahwa protokol NSCoding memungkinkan kita untuk dengan mudah mengarsipkan dan mengurai contoh kelas Bookmark.

1
 
2
#import "Bookmark.h" 

3
 
4
#define kBookmarkName   @"Bookmark Name" 

5
#define kBookmarkURL    @"Bookmark URL" 

6
 
7
@implementation Bookmark 
8
 
9
@synthesize name = _name, url = _url; 
10
 
11
#pragma mark - 

12
#pragma mark Initialization 

13
- (id)initWithName:(NSString *)name andURL:(NSString *)url { 
14
    self = [super init]; 
15
     
16
    if (self) { 
17
        self.name = name; 
18
        self.url = url; 
19
    } 
20
     
21
    return self; 
22
} 
23
 
24
#pragma mark - 

25
#pragma mark NSCoding Protocol 

26
- (void)encodeWithCoder:(NSCoder *)coder { 
27
    [coder encodeObject:self.name forKey:kBookmarkName]; 
28
    [coder encodeObject:self.url forKey:kBookmarkURL]; 
29
} 
30
 
31
- (id)initWithCoder:(NSCoder *)coder  { 
32
    self = [super init]; 
33
     
34
    if (self != nil) { 
35
        self.name = [coder decodeObjectForKey:kBookmarkName]; 
36
        self.url = [coder decodeObjectForKey:kBookmarkURL]; 
37
    } 
38
     
39
    return self; 
40
} 
41
 
42
@end

Langkah 3: Subclassing UIDocument

Subclassing UIDocument tidak sesulit yang Anda bayangkan. Seperti yang saya sebutkan sebelumnya, yang perlu kita lakukan hanyalah mengganti dua metode dan membuat properti untuk model bookmark yang akan dikelola.

Buat kelas baru seperti yang dilakukan untuk kelas Bookmark kita dan beri nama BookmarkDocument. Pastikan bahwa itu adalah subkelas dari UIDocument. Dalam file header subkelas UIDocument, kita menambahkan deklarasi maju untuk kelas Bookmark dan kita membuat properti untuk model bookmark. Jangan lupa untuk mensintesis aksesor untuk properti ini.

1
 
2
#import <UIKit/UIKit.h> 

3
 
4
@class Bookmark; 
5
 
6
@interface BookmarkDocument : UIDocument { 
7
    Bookmark *_bookmark; 
8
} 
9
 
10
@property (nonatomic, strong) Bookmark *bookmark; 
11
 
12
@end

Dalam file implementasi kita mengimpor file header dari kelas Bookmark dan mendefinisikan konstanta lain untuk berfungsi sebagai kunci untuk pengarsipan dan penghapusan pengarsipan model bookmark. Seperti yang saya sebutkan sebelumnya, kita hanya perlu mengganti dua metode dalam subkelas UIDocument, (1) loadFromContents:ofType:error: dan (2) contentForType:error:. Metode pertama akan dipanggil ketika kita membuka dokumen sedangkan metode kedua akan dipanggil ketika dokumen disimpan. Kedua metode ini disebut oleh sistem operasi. Kita tidak perlu memanggil metode ini secara langsung.

1
 
2
#import "BookmarkDocument.h" 

3
 
4
#import "Bookmark.h" 

5
 
6
#define kArchiveKey @"Bookmark" 

7
 
8
@implementation BookmarkDocument 
9
 
10
@synthesize bookmark = _bookmark;

Biarkan saya memandu Anda melalui loadFromContents:ofType:error:. Argumen pertama adalah isi id tipe. Ini bisa berupa instance dari NSData atau NSFileWrapper. Yang terakhir ini hanya berlaku ketika aplikasi menggunakan paket file. Dalam kasus, kita dapat mengharapkan instance NSData. Kita pertama-tama memeriksa apakah panjang instance NSData tidak sama dengan nol. Kita menginisialisasi instance NSKeyedUnarchiver dan menyediakannya dengan objek konten. Dengan mendekode data, kita mendapatkan instance kelas Bookmark kembali. Ini adalah alasan mengapa kelas Bookmark sesuai dengan protokol NSCoding. Jika panjang instance NSData sama dengan nol, kita menginisialisasi bookmark baru dengan nilai default untuk nama dan URL. Perhatikan bahwa kita mengembalikan YES pada akhir metode.

1
 
2
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
3
    if ([contents length] > 0) { 
4
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:contents]; 
5
        self.bookmark = [unarchiver decodeObjectForKey:kArchiveKey]; 
6
        [unarchiver finishDecoding]; 
7
         
8
    } else { 
9
        self.bookmark = [[Bookmark alloc] initWithName:@"Bookmark Name" andURL:@"www.example.com"]; 
10
    } 
11
     
12
    return YES; 
13
}

The contentForType:error: metode melakukan yang sebaliknya. Artinya, kita menyediakan data yang perlu ditulis ke disk. Objek data ini adalah snapshot yang disebut data model kita. Kita melakukan ini dengan menginisialisasi instance NSMutableData dan menggunakannya untuk menginisialisasi instance NSKeyedArchiver. Kita kemudian dapat mengarsipkan contoh bookmark sehingga dapat ditulis ke disk. Metode ini mengharapkan kita untuk mengembalikan instance NSData dan itulah yang dilakukan. Subkelas UIDocument kita sekarang siap untuk digunakan.

1
 
2
- (id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
3
    NSMutableData *data = [[NSMutableData alloc] init]; 
4
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
5
    [archiver encodeObject:self.bookmark forKey:kArchiveKey]; 
6
    [archiver finishEncoding]; 
7
     
8
    return data; 
9
}

Langkah 4: Pengontrol Tampilan Refactoring

Ada empat elemen aplikasi kita yang perlu di refactored jika kita ingin memanfaatkan Penyimpanan Dokumen iCloud:
(1) memuat, (2) menampilkan, (3) menyimpan, dan (4) menghapus bookmark. Mari kita mulai dengan memuat bookmark.

Sebelum kita melihat metode loadBookmarks, kita perlu mendeklarasikan properti pribadi, turunan dari NSMetadataQuery. Ini akan menjadi jelas mengapa kita perlu melakukan ini hanya dalam beberapa menit. Jangan lupa untuk menambahkan dua pernyataan impor tambahan ke file implementasi view controller, satu untuk kelas Bookmark dan satu untuk kelas BookmarkDocument.

1
 
2
#import "ViewController.h" 

3
 
4
#import "Bookmark.h" 

5
#import "BookmarkDocument.h" 

6
#import "AddBookmarkViewController.h" 

7
 
8
@interface ViewController () { 
9
    NSMetadataQuery *_query; 
10
} 
11
 
12
@property (nonatomic, strong) NSMetadataQuery *query; 
13
 
14
@end 
15
 
16
@implementation ViewController 
17
 
18
@synthesize bookmarks = _bookmarks; 
19
@synthesize tableView = _tableView; 
20
@synthesize query = _query;

Langkah 4A: Memuat Bookmark

Alih-alih instance NSDictionary, array bookmark, sumber data dari tampilan tabel kita akan berisi instance dari kelas BookmarkDocument. Mari kita lihat metode loadBookmarks yang sudah di refactored. Kita mulai dengan menginisialisasi array bookmark. Selanjutnya, kita meminta NSFileManager untuk URL wadah iCloud yang akan digunakan untuk menyimpan bookmark. Jangan dibuang dengan nama penuh warna dari metode ini. URLForUbiquityContainerIdentifier: menerima satu argumen, pengidentifikasi wadah iCloud yang ingin kita akses. Dengan melewatkan nil sebagai argumen, NSFileManager akan secara otomatis memilih wadah iCloud pertama yang dideklarasikan dalam file hak aplikasi kita. Perhatikan bahwa jika Anda menentukan pengidentifikasi wadah iCloud, Anda harus memberikan pengidentifikasi tim juga. Format yang benar adalah <Team Identifer>.<Container>.

1
 
2
- (void)loadBookmarks { 
3
    if (!self.bookmarks) { 
4
        self.bookmarks = [[NSMutableArray alloc] init]; 
5
    } 
6
     
7
    NSURL *baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 
8
     
9
    if (baseURL) { 
10
        self.query = [[NSMetadataQuery alloc] init]; 
11
        [self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]]; 
12
         
13
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K like '*'", NSMetadataItemFSNameKey]; 
14
        [self.query setPredicate:predicate]; 
15
         
16
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
17
        [nc addObserver:self selector:@selector(queryDidFinish:) name:NSMetadataQueryDidFinishGatheringNotification object:self.query]; 
18
        [nc addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:self.query]; 
19
         
20
        [self.query startQuery]; 
21
    } 
22
}

Metode ini bukan hanya untuk mencari tahu di mana kita dapat menyimpan dokumen iCloud kita. Dengan berhasil memanggil metode ini, sistem operasi akan memperluas kotak pasir aplikasi untuk memasukkan direktori kontainer iCloud yang ditentukan. Ini berarti bahwa kita perlu memanggil metode ini sebelum kita dapat mulai membaca atau menulis data ke direktori ini. Jika Anda mencatat URL yang dikembalikan ke konsol, Anda akan melihat dua keanehan, (1) URL yang dikembalikan untuk wadah iCloud adalah URL lokal (terletak di perangkat itu sendiri), dan (2) URL lokal ini tidak hidup di kotak pasir aplikasi kita. Cara iCloud bekerja, adalah bahwa kita menyimpan dokumen yang ingin disimpan di iCloud di direktori lokal yang disediakan oleh NSFileManager kepada kita. Daemon iCloud, yang berjalan pada perangkat kita di background, akan menangani aspek sinkronisasi dokumen dan itu akan melakukan ini bahkan jika aplikasi kita tidak berjalan.

Karena URL lokal tinggal di luar kotak pasir aplikasi, kita perlu mengaktifkan metode ini sebelum kita membaca atau menulis ke direktori ini. Dengan memohon metode ini kita meminta izin sistem operasi untuk membaca dan menulis ke direktori ini.

Mari kita lanjutkan membedah metode loadBookmarks. Kita memverifikasi bahwa URL yang didapatkan dari NSFileManager tidak sama dengan nol. Yang terakhir menyiratkan dua hal penting, (1) kita memiliki lokasi yang dapat dibaca dan tulis, dan (2) iCloud diaktifkan di perangkat. Poin kedua sangat penting karena tidak semua perangkat akan mengaktifkan iCloud.

Jika NSFileManager memang mengembalikan URL yang valid, kita menginisialisasi instance NSMetadataQuery dan menetapkannya ke variabel instance yang dinyatakan sebelumnya. Kelas NSMetadataQuery memungkinkan kita untuk mencari wadah iCloud untuk dokumen. Setelah menginisialisasi instance NSMetadataQuery, kita menentukan cakupan pencarian. Dalam kasus ini, kita akan mencari di direktori Documents dari wadah iCloud karena itu adalah lokasi di mana kita akan menyimpan dokumen bookmark. Anda dapat memperbaiki query dengan menetapkan predikat pencarian. Jika Anda terbiasa dengan Core Data, maka ini bukan hal baru bagi Anda. Pencarian kita akan sederhana, akan mencari semua dokumen di direktori dokumen wadah iCloud kita, karenanya tanda bintang dalam predikat.

Sebelum memulai permintaan kita, penting untuk menyadari bahwa kita seharusnya tidak mengharapkan hasil langsung dari permintaan kita. Sebagai gantinya, kita akan mendaftarkan view controller kita sebagai pengamat untuk notifikasi NSMetadataQueryDidUpdateNotification dan NSMetadataQueryDidFinishGatheringNotification dengan instance query kita sebagai pengirim. Ini berarti bahwa kita akan diberitahu ketika permintaan telah mengembalikan hasil apa pun atau ketika hasilnya telah diperbarui. Akhirnya, kita memulai query.

Penting bahwa kita menyimpan referensi ke instance query untuk mencegah agar tidak dirilis. Ini adalah alasan bahwa pengontrol tampilan kita menyimpan referensi ke query (sebagai variabel instance) selama query berjalan.

Mari kita lihat queryDidFinish: dan queryDidUpdate: metode callback notifikasi untuk melihat bagaimana menangani hasil dari query. Kedua metode melewati objek pengirim pemberitahuan, contoh NSMetadataQuery, ke metode kenyamanan, processQueryResults:. Ketika kita melihat metode ini, kita melihat bahwa kita pertama mulai dengan menonaktifkan pembaruan untuk query. Ini penting karena hasil query dapat menerima pembaruan langsung ketika perubahan terjadi dan kita harus mencegahnya selama kita memproses hasil query. Selanjutnya, kita menghapus semua objek dari larik bookmark kita dan menghitung hasil query. Setiap item dalam array hasil adalah turunan dari NSMetadataItem, yang berisi metadata yang terkait dengan setiap dokumen bookmark, termasuk URL file yang kita perlukan untuk membuka dokumen. Kita meminta setiap item metadata untuk file URL dan menginisialisasi dokumen masing-masing.

Perhatikan bahwa menginisialisasi dokumen bookmark tidak berarti bahwa kita telah memuatnya dari disk. Ingat bahwa ini dilakukan dengan mengirimkan dokumen bookmark kita pesan dari openWithCompletionHandler:. Jika operasi terbuka berhasil dan dokumen dimuat, kita menambahkannya ke array bookmark dan menampilkannya dalam tampilan tabel. Akhirnya, kita perlu menghapus pengontrol tampilan kita sebagai pengamat karena kita tidak perlu lagi menerima pemberitahuan pada saat ini.

1
 
2
- (void)queryDidFinish:(NSNotification *)notification { 
3
    NSMetadataQuery *query = [notification object]; 
4
     
5
    // Stop Updates 

6
    [query disableUpdates]; 
7
     
8
    // Stop Query 

9
    [query stopQuery]; 
10
     
11
    // Clear Bookmarks 

12
    [self.bookmarks removeAllObjects]; 
13
     
14
    [query.results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
15
        NSURL *documentURL = [(NSMetadataItem *)obj valueForAttribute:NSMetadataItemURLKey]; 
16
        BookmarkDocument *document = [[BookmarkDocument alloc] initWithFileURL:documentURL]; 
17
         
18
        [document openWithCompletionHandler:^(BOOL success) { 
19
            if (success) { 
20
                [self.bookmarks addObject:document]; 
21
                [self.tableView reloadData]; 
22
            } 
23
        }]; 
24
    }]; 
25
     
26
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
27
}

Langkah 4B: Menampilkan Bookmark di Tampilan Tabel

Kode untuk menampilkan bookmark dalam tampilan tabel kita tidak perlu banyak berubah. Alih-alih mengambil instance NSDictionary yang benar dari sumber data, kita mengambil instance kelas BookmarkDocument. Mengakses nama dan URL bookmark juga perlu diperbarui.

1
 
2
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
3
    static NSString *CellIdentifier = @"Cell Identifier"; 
4
     
5
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
6
     
7
    if (cell == nil) { 
8
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; 
9
    } 
10
     
11
    // Fetch Bookmark 

12
    BookmarkDocument *document = [self.bookmarks objectAtIndex:indexPath.row]; 
13
     
14
    // Configure Cell 

15
    cell.textLabel.text = document.bookmark.name; 
16
    cell.detailTextLabel.text = document.bookmark.url; 
17
     
18
    return cell; 
19
}

Langkah 4C: Menyimpan Bookmark

Buka metode save: di AddBookmarkViewController. Alih-alih membuat NSDictionary dan mengirimkannya ke view cotroller utama, kita membuat instance Bookmark baru. Itu dia. Sisanya ditangani dalam metode saveBookmark: dari view controller utama kita. Jangan lupa untuk menambahkan pernyataan impor untuk kelas Bookmark.

1
 
2
- (IBAction)save:(id)sender { 
3
    Bookmark *bookmark = [[Bookmark alloc] initWithName:self.nameField.text andURL:self.urlField.text]; 
4
     
5
    [self.viewController saveBookmark:bookmark]; 
6
     
7
    [self dismissViewControllerAnimated:YES completion:nil]; 
8
}

Menyimpan bookmark ke wadah iCloud kita hampir semudah menyimpannya ke kotak pasir aplikasi. Pertama, kita meminta NSFileManager URL dari wadah iCloud seperti yang dilakukan sebelumnya. Berdasarkan URL itu, kita membuat URL yang benar untuk menyimpan dokumen bookmark di direktori Documents dari wadah iCloud. Nama dokumen yang dapat berupa apa pun yang diinginkan asalkan namanya unik. Saya telah memilih untuk menggunakan nama bookmark dan cap waktu. Pengguna tidak akan melihat nama file ini sehingga nama itu tidak terlalu penting. Yang penting itu unik.

Kita memiliki instance bookmark, tetapi belum memiliki dokumen bookmark. Kita membuat dokumen bookmark baru dengan menginisialisasi dengan URL yang baru saja kita buat. Selanjutnya, kita menetapkan bookmark baru kita ke properti bookmark dokumen. Akhirnya, menambahkan dokumen ke array bookmark dan memuat kembali tampilan tabel.

Menyimpan dokumen ke wadah iCloud mudah. Kita memulai operasi save yang saya bicarakan sebelumnya dengan mengirimkan dokumen baru kita pesan saveToURL:forSaveOperation:completionHandler:. Parameter kedua dari metode ini menentukan jenis operasi simpan. Dalam kasus, kita melewati UIDocumentSaveForCreating, yang berarti membuat dokumen bookmark baru. Karena kita tidak perlu melakukan sesuatu yang istimewa dalam contoh kita, kita cukup mencatat pesan ke konsol ketika operasi penyimpanan selesai.

Anda mungkin telah memperhatikan bahwa deklarasi metode kita sedikit berubah. Kita tidak lagi meneruskan instance NSDictionary sebagai satu-satunya argumen. Alih-alih, meneruskan turunan dari kelas Bookmark. Pastikan Anda memperbarui file header untuk mencerminkan perubahan ini. Anda juga perlu menambahkan deklarasi kelas foward untuk mencegah peringatan kompiler muncul. Ini adalah tugas yang harus Anda ketahui sekarang.

1
 
2
- (void)saveBookmark:(Bookmark *)bookmark { 
3
    // Save Bookmark 

4
    NSURL *baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 
5
     
6
    if (baseURL) { 
7
        NSURL *documentsURL = [baseURL URLByAppendingPathComponent:@"Documents"]; 
8
        NSURL *documentURL = [documentsURL URLByAppendingPathComponent:[NSString stringWithFormat:@"Bookmark_%@-%f", bookmark.name, [[NSDate date] timeIntervalSince1970]]]; 
9
         
10
        BookmarkDocument *document = [[BookmarkDocument alloc] initWithFileURL:documentURL]; 
11
        document.bookmark = bookmark; 
12
         
13
        // Add Bookmark To Bookmarks 

14
        [self.bookmarks addObject:document]; 
15
         
16
        // Reload Table View 

17
        [self.tableView reloadData]; 
18
         
19
        [document saveToURL:documentURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { 
20
            if (success) { 
21
                NSLog(@"Save succeeded."); 
22
            } else { 
23
                NSLog(@"Save failed."); 
24
            } 
25
        }]; 
26
    } 
27
}

Langkah 4D: Menghapus Bookmark

Potongan puzzle terakhir yang hilang adalah penghapusan bookmark. Ini sangat mudah dibandingkan dengan apa yang telah dilakukan sejauh ini. Kita mengambil dokumen bookmark yang benar dari sumber data dan memberitahu NSFileManager untuk menghapusnya dari wadah iCloud dengan mengirimkan URL yang benar. Ini juga akan menghapus dokumen di iCloud. Begitulah mudahnya. Tentu saja, kita juga memperbarui sumber data dan tampilan tabel.

1
 
2
- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 
3
    if (editingStyle == UITableViewCellEditingStyleDelete) { 
4
        // Fetch Document 

5
        BookmarkDocument *document = [self.bookmarks objectAtIndex:indexPath.row]; 
6
         
7
        // Delete Document 

8
        NSError *error = nil; 
9
        if (![[NSFileManager defaultManager] removeItemAtURL:document.fileURL error:&error]) { 
10
            NSLog(@"An error occurred while trying to delete document. Error %@ with user info %@.", error, error.userInfo); 
11
        } 
12
         
13
        // Update Bookmarks 

14
        [self.bookmarks removeObjectAtIndex:indexPath.row]; 
15
         
16
        // Update Table View 

17
        [aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
18
    } 
19
}

Kesimpulan

Dalam tutorial ini, kita telah refactored aplikasi kita untuk menggunakan Penyimpanan Dokumen iCloud bukan Penyimpanan Nilai-Kunci iCloud. Meskipun kita telah melakukan refactored sedikit kode, prosesnya cukup mudah. Kita sekarang memiliki aplikasi berbasis dokumen yang jauh lebih cocok untuk menangani data pengguna dalam jumlah yang lebih besar. Komponen dasar sudah ada dan memperluas aplikasi membutuhkan sedikit usaha dari pihak kami. Perhatikan bahwa aplikasi kita masih merupakan implementasi minimal dari pengelola bookmark. Misalnya, tidak ada opsi untuk mengedit bookmark. Kita juga harus melakukan lebih banyak pengecekan kesalahan jika kita ingin menjadikan aplikasi kita menjadi aplikasi yang kuat dan andal yang siap untuk dirilis.

Anda juga mungkin telah memperhatikan bahwa kita memiliki sejumlah metode yang tidak lagi diperlukan. Saya telah menghapus metode ini dari sampel kode akhir dan saya sarankan Anda melakukan hal yang sama. Menghapus kode usang juga merupakan bagian dari proses refactoring dan penting ketika Anda ingin menjaga kode Anda terpelihara.

Lain Kali

Dalam tutorial ini, kita melihat lebih dekat pada Penyimpanan Dokumen iCloud serta kelas UIDocument. Dalam tutorial berikutnya, kita akan memperbesar pada UIManagedDocument, subkelas diskrit dari UIDocument yang dirancang untuk bekerja sama dengan Core Data.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
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.