Wednesday, June 5, 2013

[Tutorial 1] Làm việc với Core Data

Bắt đầu nào
NSManagedObjectModel mà ở đó bạn sẽ định nghĩa cho sơ đồ Core Data. Trong cái model của bạn, bạn định nghĩa Entities, hay những lớp dữ liệu trong sơ đồ. Trong những cái Entities của bạn, bạn thiết lập những cái Attribute, cái này là cái chi tiết dữ liệu của bạn. Cuối cùng, bạn có thể liên kết những cái Entity với nhau thông qua những cái Relationship.
Ví dụ, bạn có thể tạo một model với một entity Label mà nó định nghĩa một nhãn của music, một entity Artist mô tả nghệ sĩ, là một phần của label, và một entity Album mô tả những album được thu âm bới những nghệ sĩ. Mỗi entity sẽ có những thuộc tính chi tiết; tất cả 3 entity sẽ được kết nối thông qua relationships.




Mở Xcode và tạo mới một dự án. Chọn “Empty Application” và click “Next”.

Chúng ta sẽ đặt tên cho dự án này là “MusicLabel” và đặt tên class prefix “MLBL”. Hãy chắc chắn rằng bạn chọn “Use Core Data”. Uncheck “Include Unit Tests”, khi chúng ta không muốn kiểm thử ứng dụng của mình.

Bây giờ chúng ta hãy tập trung vào data model. Chọn file “MusicLabel.xcdatamodeld”, và đảm bảo rằng editor style được thiết lập đến table.

Click “Add Entity” ở dưới màn hình Xcode và đặt tên nó là “Label”. Với entity được chọn, click “Add Atrribute”. Chúng ta sẽ gọi attribute này là “name”, và thiết lập type cho nó là “String”.

Thêm những attribute sau và kiểu tương ứng đến “Label” entity:

Thêm entity khác, “Artist”, và thêm những attribute sau:

Thêm một entity nửa là “Album”, và thêm những attribute sau:

Chuyển đổi Editor Style sang chế độ đồ họa ở phía dưới bên phải của màn hình Xcode.

Với entity “Label” được chọn, click và giữ “Add Attribute” cho đến khi bạn nhìn thấy option “Add Relationship”.

Chọn Add Relationship. Cho nó một cái tên là “artists” và thiết lập những điểm đích đến entity “Artist”. Bằng cách thiết lập relationship này, chúng ta nói rằng “mỗi Label có một Artist”. Label của có nhiều hơn một artist, do đó chúng ta sẽ tạo một relationship “To-Many Relationship”. Tiếp theo, thiêt lập delete rule đến “Cascade”; điều này sẽ đảm bảo rằng khi một đối tượng được xóa, đối tượng con của nó cũng bị xóa theo.

Bây giờ, chúng ta muốn tạo một relationship ngược về lại cha nó. Chọn “Artist” entity và click “Add Relationship”. Đặt tên cho relationship “label” và thiết lập đích cho “Label” entity. Set the inverse to the “artists” relationship.

Sử dụng cùng những bước này để thiết lập relationship giữa “Artist” và “Album” entities. Tạo một relationship từ “Artist” entity đến “Album” entity titled “album”. Tạo cho nó một relationship “To-Many Relationship” và thiết lập delete rule thành “Cascade”. Tạo một relationship từ “Album entity” đến “Artist” entity với tên là “artist” và tạo một cái relationship ngược về “albums”
Use this table for reference:
Tham khảo bảng sau:

Khi nào bạn hoàn thành, model của bạn nên giống như sau:

Cuối cùng, chọn “Label” entity, và click File>New>File. Chọn mẫu “NSManagedObject subclass”.

Việc này sẽ tạo tệp lớp Objective-C cho entity “Label”; bạn nên xem file “Label.h” cũng như file “Label.m”. Sử dụng cùng những bước để tạo những file class cho “Artist” và “Album” entity (đảm bảo rằng để làm nó theo thứ tự Label>Artist>Album). Với file class được tạo cho mỗi entity, những thiết lập của chúng ta sẽ hoàn thành.
NSManagedObjectContext & NSPersistentStoreCoordinator
NSManagedObjectModel chỉ là 1/3 của bức tranh Core Data. Bạn có nghĩ NSManagedObjectContext giống như “scratch pad” mà ở đó xảy ta mọi sự thay đổi. Ở đây bạn tạo, đọc, cập nhật và xóa những đối tượng từ database của bạn. Không có trong số những thay đổi mà bạn tạo thực sự tồn tại cho đến khi bạn gọi phương thức “save” trên những thể hiện của object context được quản lý của bạn.
Do đó khi một lời gọi để save được gọi, điều gì sẽ xảy ta tiếp theo? Ở giữa managed object context và database là NSPersistentStoreCoordinator. Điều phối hoạt động như là một giao diện cho database mà ở đó dữ liệu của bạn đang được tồn tại. Sự điều phối này sẽ lấy bất kì đối tượng nào mà sẽ được lưu từ managed object context và xác minh những tên và kiểu có phù hợp với managed object model. Sau đó nó sẽ gửi những đối tượng theo cách của chúng đến database.

Tạo một đối tượng
Mở file “MLBLAppDelegate.m”. Trong đó, bạn sẽ nhìn thấy những phương thức để cài đặt context, model và persistent store coordinator. Import “Label.h”, “Artist.h”, và “Album.h”. Thêm phương thức sau:

- (void) create {
  // Grab the context
  NSManagedObjectContext *context = [self managedObjectContext];
  
   // Grab the Label entity
   Label *label = [NSEntityDescription insertNewObjectForEntityForName:@"Label" inManagedObjectContext:context];
  
   // Set label name
   label.name = @"Diplomat Records";
  
   // Create a Date
   NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
   [dateFormatter setDateFormat:@"YYYY"];
   NSDate *dateFounded = [dateFormatter dateFromString:@"2003"];
  
   // Set the year founded for the label
   label.founded = dateFounded;
  
   // Set the label genre
   label.genre = @"Rap/Hip-hop";
  
   // Insert the Artist entity
   Artist *artist = [NSEntityDescription insertNewObjectForEntityForName:@"Artist" inManagedObjectContext:context];
  
   // Set the artist attributes
   artist.name = @"Cam'Ron";
   artist.hometown = @"Harlem, NY";
  
   // Insert Album entity
   Album *album = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
  
   // Set album attributes
   album.title = @"Come Home With Me";
   NSDate *releaseDate = [dateFormatter dateFromString:@"2002"];
   album.released = releaseDate;
  
   // Set relationships
   [label addArtistsObject:artist];
   [artist setLabel:label];
   [artist addAlbumsObject:album];
   [album setArtist:artist];
  
   // Save everything
   NSError *error = nil;
   if ([context save:&error]) {
       NSLog(@"The save was successful!");
   } else {
       NSLog(@"The save wasn't successful: %@", [error userInfo]);
   }
}
Make sure to call [self create] in the application:didFinishLaunchingWithOptions: method. Build your project and run it. Check the output in the log navigator to see if it saved properly. You should see this output:
Đảm bảo rằng là gọi [self create] trong phương thức application:didFinishLaunchingWithOptions:. Build dự án của bạn và chạy nó. Kiểm tra output trong màn hình log để thấy nếu nó được lưu thành công hay không.

It worked? Great, now let’s walk through reading data.
Nó đã làm việc? Tuyệt, bây giờ hãy tham quan việc đọc dữ liệu nào.
Đọc một đối tượng
With Core Data, you perform “fetch requests” to access saved objects. These objects are always returned as instances of NSManagedObject. Check out NSFetchRequest for more info. Add the following method to the “MLBLAppDelegate.m” file:
Với Core Data, bạn thực hiện “fetch requests” để truy cập những đối tượng được lưu. Những đối tượng này luôn luôn return những thể hiện của lớp NSManagedObject. Kiểm tra NSFetchRequest để thêm thông tin. Thêm phương thức sau đến file “MLBLAppDelegate.m”:

- (void) read {
    NSManagedObjectContext *context = [self managedObjectContext];
   
    // Construct a fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Label"
                                              inManagedObjectContext:context];
   
    [fetchRequest setEntity:entity];
    NSError *error = nil;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
   
    for (Label *label in fetchedObjects) {
        // Log the label details
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"YYYY"];
       
        NSLog(@"%@, est. %@ (%@)", label.name, [dateFormatter stringFromDate:label.founded], label.genre);
       
        NSLog(@"\tArtists:");
        NSSet *artists = label.artists;
        for (Artist *artist in artists) {
            // Log the artist details
            NSLog(@"\t\t%@ (%@)", artist.name, artist.hometown);
           
            NSLog(@"\t\t\tAlbums:");
            NSSet *albums = artist.albums;
            for (Album *album in albums) {
                // Log the album details
                NSLog(@"\t\t\t\t%@ (%@)", album.title,  [dateFormatter stringFromDate:album.released]);
            }
        }
    }
}
Replace [self create] with [self read] in the application:didFinishLaunchingWithOptions: method. Build and run, and voila! A printout of the objects should appear in the log navigator.
Thay [self create] thành [self read] trong phương thức application:didFinishLaunchingWithOptions:. Build và chạy, một bản in của những đối nên xuất hiện trong màn hình log.
Cập nhật một đối tượng
Hãy cập nhật label của chúng ta và thêm một vài artists và albums. Thêm phương thức này:

- (void) update {
   // Grab the context
   NSManagedObjectContext *context = [self managedObjectContext];
  
   // Perform fetch request
   NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
   NSEntityDescription *entity = [NSEntityDescription entityForName:@"Label"
                                             inManagedObjectContext:context];
   [fetchRequest setEntity:entity];
   NSError *error = nil;
   NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
  
   // Date formatter comes in handy
   NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
   [dateFormatter setDateFormat:@"YYYY"];
  
   // Grab the label
   Label *label = [fetchedObjects objectAtIndex:0];
  
   // Juelz Santana
   Artist *juelz = [NSEntityDescription insertNewObjectForEntityForName:@"Artist" inManagedObjectContext:context];
   juelz.name = @"Juelz Santana";
   juelz.hometown = @"Harlem, NY";
  
   // Juelz Santana albums
   Album *juelzAlbum = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
   juelzAlbum.title = @"From Me to U";
   juelzAlbum.released = [dateFormatter dateFromString:@"2003"];
   [juelzAlbum setArtist:juelz];
  
   Album *juelzAlbum2 = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
   juelzAlbum2.title = @"What The Game's Been Missing!";
   juelzAlbum2.released = [dateFormatter dateFromString:@"2005"];
   [juelzAlbum2 setArtist:juelz];
  
   // Set relationships
   [juelz addAlbums:[NSSet setWithObjects:juelzAlbum, juelzAlbum2, nil]];
  
  
   // Jim Jones
   Artist *jimmy = [NSEntityDescription insertNewObjectForEntityForName:@"Artist" inManagedObjectContext:context];
   jimmy.name = @"Jim Jones";
   jimmy.hometown = @"Harlem, NY";
  
   // Jim Jones albums
   Album *jimmyAlbum = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
   jimmyAlbum.title = @"On My Way to Church";
   jimmyAlbum.released = [dateFormatter dateFromString:@"2004"];
   [jimmyAlbum setArtist:jimmy];
  
   Album *jimmyAlbum2 = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
   jimmyAlbum2.title = @"Harlem: Diary of a Summer";
   jimmyAlbum2.released = [dateFormatter dateFromString:@"2005"];
   [jimmyAlbum2 setArtist:jimmy];
  
   Album *jimmyAlbum3 = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
   jimmyAlbum3.title = @"Hustler's P.O.M.E. (Product of My Environment)";
   jimmyAlbum3.released = [dateFormatter dateFromString:@"2006"];
   [jimmyAlbum3 setArtist:jimmy];
  
   // Set relationships
   [jimmy addAlbums:[NSSet setWithObjects:jimmyAlbum, jimmyAlbum2, jimmyAlbum3, nil]];
  
  
   // Freekey Zekey
   Artist *freekey = [NSEntityDescription insertNewObjectForEntityForName:@"Artist" inManagedObjectContext:context];
   freekey.name = @"Freekey Zekey";
   freekey.hometown = @"Harlem, NY";
  
   Album *freekeyAlbum = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:context];
   freekeyAlbum.title = @"Book of Ezekiel";
   freekeyAlbum.released = [dateFormatter dateFromString:@"2007"];
   [freekeyAlbum setArtist:freekey];
   [freekey addAlbumsObject:freekeyAlbum];
  
   // Set relationships
   [label addArtists:[NSSet setWithObjects:juelz, jimmy, freekey, nil]];
  
   // Save everything
   if ([context save:&error]) {
       NSLog(@"The save was successful!");
   } else {
       NSLog(@"The save wasn't successful: %@", [error localizedDescription]);
   }
}
Replace [self read] with [self update] in the application:didFinishLaunchingWithOptions: method. Build and run, and check the log navigator for a successful save. Now let’s print them to the log again; replace [self update] with [self read]. Build and run, and you should see all the artists/albums under the label. Run it a few more times and compare the log output each time. The order will vary almost every time. Fetch requests return objects unordered, unless specified otherwise. To do so, you need to use NSSortDescriptor to organize your results. Use NSPredicate to grab specific objects.
Thay [self read] thành [self update] trong phương thức application:didFinishLaunchingWithOptions :.Build và chạy, kiểm tra màn hình log để biết nó được lưu thành công hay không. Bây giờ hãy in chúng lên màn hình log một lần nửa; thay [self update] thành [self read]. Build và chạy, bạn nên nhìn thấy tất cả artists/albums phía dưới label. Chạy nó thêm một vài lần và so sánh output ở màn hình log. Thứ tự sẽ khác hầu như mỗi lần. Fetch requests return những đối tượng chưa được sắp xếp, trì khi có gì đặc biệt. Để làm điều này bạn cần sử dụng NSSortDescriptor để tổ chức lại những kết quả của bạn. Sử dụng NSPredicate để lấy những đối tượng xác định.
Xóa một đối tượng
Cuối cùng, chúng ta sẽ xóa một đối tượng. Hãy thêm phương thức này:

- (void) delete {
   // Grab the context
   NSManagedObjectContext *context = [self managedObjectContext];
  
   //  We're looking to grab an artist
   NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
   NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist"
                                             inManagedObjectContext:context];
  
   [fetchRequest setEntity:entity];
  
   // We specify that we only want Freekey Zekey
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", @"Freekey Zekey"];
   [fetchRequest setPredicate:predicate];
  
   NSError *error = nil;
   NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
  
   // Grab the artist and delete
   Artist *freekey = [fetchedObjects objectAtIndex:0];
   [freekey.label removeArtistsObject:freekey];
  
   // Save everything
   if ([context save:&error]) {
       NSLog(@"The save was successful!");
   } else {
       NSLog(@"The save wasn't successful: %@", [error localizedDescription]);
   }
}
Thêm dòng [self delete] bên phải trước [self read] trong phương thức application:didFinishLaunchingWithOptions. Build và chạy, bạn nên thấy Freekey Zekey biến mất từ những kết quả. Album của anh ấy nên “đi” quá, giống như chúng ta thiết lập delete rule cho relationship là Cascade.


Source: https://blog.stackmob.com/2012/11/iphone-database-tutorial-part-1-learning-core-data/

No comments:

Post a Comment