Wednesday, June 5, 2013

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

Click here...
Trong phần cuối này, chúng ta sẽ học những chi tiết hơn xung quanh Core Data và xử lý những thao tác CRUD trên data model của bạn. Trong post này, chúng ta sẽ tập trung trên UI, hay giao diện người dùng, lớp này nằm phía trên của view controllers mà nó cho phép một người tương tác với dữ liệu của chúng ta.


Tạo một storyboard
Đầu tiên, chúng ta sẽ cần thêm một storyboard đến dự án của chúng ta. Ấn command + N và chọn “User Interface” từ mẫu hiện có. Chọn Storyboard và click next.

Đặt tên file là “MainStoryboard” và click create. Trong dự án MusicLabel, target select the storyboard we just created to be the Main Storyboard.

Tạo một tableview
Click storyboard và chắc chắn rằng pane “Utilities” được mở.

Kéo một table view controller từ thư viện đối tượng trong storyboard.

With the prototype cell selected, navigate to the attributes inspector. Enter “Cell” as an identifier.

Nhấn command + N, và từ những mẫu “Cocoa touch”, chọn lớp “Objective-C”.



Đặt tên file “MLBLLabelViewController” và subclass của UITableViewController.

Back in the storyboard, select the table view controller and navigate to the identity inspector. Thay đổi custom class thành “MLBLLabelViewController”.

Thay đổi một số cái trong MLBLLabelViewController.h:

#import <UIKit/UIKit.h>
#import "MLBLAppDelegate.h"
#import "Label.h"

@interface MLBLLabelViewController : UITableViewController

// An array to house all of our fetched Label objects
@property (strong, nonatomic) NSArray *labelArray;

@end
Thay đổi file MLBLLabelViewController.m:

/* Make these changes to MLBLLabelViewController.M */

@implementation MLBLLabelViewController

@synthesize labelArray;
 

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
 
    /* Here we call the method to load the table data */
    [self loadTableData];
}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // We only need to return 1 for this table view
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // We'll return the count of the objects in labelArray
    return [labelArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
   
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
   
    // Configure the cell...
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
   
    // Grab the label
    Label *label = [self.labelArray objectAtIndex:indexPath.row];
    // Set the text of the cell to the label name
    cell.textLabel.text = label.name;
   
    return cell;
}

#pragma mark - Private methods
- (MLBLAppDelegate *)appDelegate {
    return (MLBLAppDelegate *)[[UIApplication sharedApplication] delegate];
}

// This method executes a fetch request and reloads the table view.
- (void) loadTableData {
   
    NSManagedObjectContext *context = [[self appDelegate] managedObjectContext];
   
    // Construct a fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Label"
                                              inManagedObjectContext:context];
   
    [fetchRequest setEntity:entity];
   
    // Add an NSSortDescriptor to sort the labels alphabetically
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
   
   
    NSError *error = nil;
    self.labelArray = [context executeFetchRequest:fetchRequest error:&error];
    [self.tableView reloadData];
}

@end
Build và chạy. Dựa vào dữ liệu chúng ta nhập vào ở bài hướng dẫn cuối này, bàn nên nhìn thấy như sau:



Tạo một Navigation Controller
Bây giờ hãy thêm cho thiết lập của chúng ta: với “MLBLLabelViewController” được chọn trong storyboard, chọn Editor>Embed In>Navigation Controller. Một navigation controller là một chuẩn UI được cung cấp bởi Apple để hướng luồng đi của ứng dụng. Nó bao gồm logic cho việc quay lại view controller trước cũng như giao tiếp giữa các màn hình với nhau. Chúng ta tạo “MLBLLabelViewController” như là root view controller trong navigation controller của chúng ta.

Drag another table view controller onto the storyboard. Create a new file “MLBLArtistViewController” that subclasses UITableViewController. Change the custom class of the new table view controller to “MLBLArtistViewController”. Give it a storyboard ID of “ArtistViewController”
Kéo table view khác vào trong storyboard. Tạo một file mới “MLBLArtistViewController” mà subclass của UITableViewController. Thay đổi custom class của table view mới này thành “MLBLArtistViewController”.  Cho nó một storyboard ID của “ArtistViewController”.
Thay đổi trong file MLBLArtistViewController.h:

#import <UIKit/UIKit.h>
#import "MLBLAppDelegate.h"
#import "Label.h"
#import "Artist.h"

@interface MLBLArtistViewController : UITableViewController

// An array to house all of our fetched Artist objects
@property (strong, nonatomic) NSArray *artistArray;

//The id of the parent object
@property (strong, nonatomic) NSManagedObjectID *labelID;

@end
Thay đổi trong file MLBLArtistViewController.m:
  
/* Make these changes to MLBArtistViewController.m */

@implementation MLBLArtistViewController

@synthesize artistArray;

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
   
    [self loadTableData];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // We only need to return 1 for this table view
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // We'll return the count of the objects in artistArray
    return [artistArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    
    // Configure the cell...
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
   
    // Grab the artist
   Artist *artist = [self.artistArray objectAtIndex:indexPath.row];
   cell.textLabel.text = artist.name;
   
    return cell;
}

#pragma mark - Private methods

- (MLBLAppDelegate *)appDelegate {
    return (MLBLAppDelegate *)[[UIApplication sharedApplication] delegate];
}

- (void) loadTableData {
   
    NSManagedObjectContext *context = [[self appDelegate] managedObjectContext];
   
    // Construct a fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist"
                                              inManagedObjectContext:context];
   
    [fetchRequest setEntity:entity];
   
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label == %@", [context objectWithID:self.labelID]];
    [fetchRequest setPredicate:predicate];
   
    // Add an NSSortDescriptor to sort the labels alphabetically
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
   
   
    NSError *error = nil;
    self.artistArray = [context executeFetchRequest:fetchRequest error:&error];
    [self.tableView reloadData];
}

@end
 #import MLBLArtistViewController.h to the MLBLLabelViewController.m file. In the - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method, make the following changes:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
   
    MLBLArtistViewController *artistViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"ArtistViewController"];
   
    // Grab the label
    Label *label = [self.labelArray objectAtIndex:indexPath.row];
   
    artistViewController.labelID = [label objectID];
   
    [self.navigationController pushViewController:artistViewController animated:YES];
}
Build và chạy, và bạn nên có thể xem những artists mà nó liên quan đến một label.
Tiếp theo, làm tương tự với albums. Tạo một file gọi là “MLBLAlbumViewController” mà subclass là UITableViewController, và lặp những bước này cho “MLBLArtistViewController”.
Tạo một Input View
Bây giờ chúng ta tạo một màn hình input để chèn dữ liệu vào trong database của chúng ta. Thêm 2 dòng code sau đến -(void)viewDidLoad method in MLBLLabelViewController.m:
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addItem)];
self.navigationItem.rightBarButtonItem = item;
Tạo một file gọi là “MLBLLabelEntryViewController”, mà subclass là UIViewController. Kéo một view controller từ thư việc đối tượng vào trong storyboard. Thay đổi custom class đến “MLBLLabelEntryViewController”. Kéo một text field vào trong view controller. Trong những attributs inspector bạn có thể customize text field; thiết lập placeholder (chữ mờ) là “Enter the Label Name”.

Giữ option key và lick vào MLBLLabelEntryViewController.h. Cái này sẽ mở file bên cạnh storyboard.

Giữ control key, click vào text field đầu tiên và kéo dòng màu xanh đến tệp MLBLLabelEntryViewController.h.

Điều này sẽ thiết lập một outlet connection giữa các storyboard nib file và view controller class. Đặt tên outlet “labelField” và click connect.
Thêm những code sau đến MLBLLabelEntryViewController.m:

/* Make these changes to  MLBLLabelEntryViewController.m */

#import "MLBLLabelEntryViewController.h"
#import "MLBLAppDelegate.h"
#import "Label.h"

@implementation MLBLLabelEntryViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
  // Do any additional setup after loading the view.
   
    // This will call our
    UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonItemStyleBordered target:self action:@selector(addLabel)];
    self.navigationItem.rightBarButtonItem = item;
   
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(dismiss)];
    self.navigationItem.leftBarButtonItem = item2;
}

#pragma mark - private methods

- (MLBLAppDelegate *)appDelegate {
    return (MLBLAppDelegate *)[[UIApplication sharedApplication] delegate];
}

- (void) addLabel {
   
    // Grab the context
    NSManagedObjectContext *context = [[self appDelegate] managedObjectContext];
   
    // Grab the Label entity
    Label *label = [NSEntityDescription insertNewObjectForEntityForName:@"Label" inManagedObjectContext:context];
   
    // Set label name
    label.name = self.labelField.text;
   
      
    // Save everything
    NSError *error = nil;
    if ([context save:&error]) {
        NSLog(@"The save was successful!");
    } else {
        NSLog(@"The save wasn't successful: %@", [error userInfo]);
    }

    [self dismiss];
}

- (void) dismiss {

    [self dismissViewControllerAnimated:YES completion:nil];
}

@end
Trong tệp MLBLLabelViewController.m, thêm #import "MLBLLabelEntryViewController.h", thêm code sau vào:


// Add this method for slide to delete
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
   
   
    return UITableViewCellEditingStyleDelete;
   
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
       
         NSManagedObjectContext *context = [[self appDelegate] managedObjectContext];
       
        // Grab the label
        Label *label = [self.labelArray objectAtIndex:indexPath.row];
       
        [context deleteObject:[context objectWithID:[label objectID]]];
       
        // Save everything
        NSError *error = nil;
        if ([context save:&error]) {
            NSLog(@"The save was successful!");
        } else {
            NSLog(@"The save wasn't successful: %@", [error userInfo]);
        }
       
        NSMutableArray *array = [self.labelArray mutableCopy];
        [array removeObjectAtIndex:indexPath.row];
        self.labelArray = array;
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }  
}

// Add this method under our private methods pragma mark

- (void) addItem {
   
    MLBLLabelEntryViewController *labelEntryViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"LabelEntryViewController"];
   
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:labelEntryViewController];
   
    [self presentViewController:navigationController animated:YES completion:nil];
   
}
Build và chạy, bạn có thể add Labels đến cơ sở dữ liệu. Bạn cũng có thể slide để xóa Labels từ table, và remove chúng từ database. Bạn có thể dễ dàng mở rộng điều này bằng cách thêm input views cho Artists và Albums.

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

No comments:

Post a Comment