Hướng dẫn sử dụng Coredata trong ios

Mình đã từng giới thiệu các bạn sử dụng Sqlite trong trong ios. Bài này mình sẽ giới thiệu một công cụ lưu trữ dữ liệu có cấu trúc khác, chỉ có trong lập trình  IOS framework CoreData. Core data khác gì so với sqlite?  Core data không sử dụng các câu truy vấn của sql để gọi dữ liệu của các trường mà gọi từng đối tượng với các thông tin của đối tượng đó.  Coredata làm việc trên context như một ảnh chụp của dataBase, chúng ta truy vấn xử lý trên context cuối cùng chúng ta mới save database xuống, sqlite làm việc trực tiếp với database thay đổi trên database, như thế sử dụng coredata chúng ta có thể thay đổi dữ liệu tuỳ ý nếu chưa cho phép save thì không ảnh hưởng đến dữ liệu. Ngoài ra core data còn được xcode suport cho cả hệ quản trị cơ sở dữ liệu dành riêng để thiết kế . Ưu điểm, nhược điểm core data so với sqlite còn rất nhiều các bạn có thể tìm hiểm thêm, mình sẽ đi vào cụ thể cách sử dụng coredata.

Trước tiên chúng ta tạo dự án mới và đặt tên coreData:

Screen Shot 2016-08-02 at 09.45.47

 

– Giới thiệu về coreData:

Core Data lưu trữ dữ liệu qua các phiên làm việc, khi ứng dụng kết thúc dữ liệu vẫn tồn tại. Core Data lưu dữ liệu dưới tầng vật lý có 4 dạng: Binary,Xml,Sqlite, InMemory. Khi load dữ liệu lên thông qua core data sẽ chuyển tất cả dữ liệu thành đối tượng để chúng ta truy vấn. Core data là hệ quản trị ORM (Object-relational mapping) ánh xạ dữ liệu quan hệ từ phía lưu trữ vật lý lên thành các đối tượng phía trên để chúng ta làm việc. Core Data suport  một thứ rất quý đó là context như mình đã giải thích phía trên.

Một số đối tượng quản lý core data:

  • NSManagedObjectModel: Chứa toàn bộ về mặt ngữ nghĩa, format của csdl, tạo model bằng cách kéo thả, design, tạo thành một file thiết kế.
  • NSPersistentStoreCoordinator: Ghi dữ liệu từ phía trên xuống thành dữ liệu vật lý lưu trữ ở phía dưới và chuyển đọc dữ liệu lên.
  • NSManagedObjectContext: Là một ngữ cảnh, ảnh của database tại thời điểm đó, chúng ta có thể làm việc trên Context, cuối cùng chúng ta mới save dữ liệu xuống. Nếu chưa save thì dữ liệu data không bị ảnh hưởng. Snapshot of database  ảnh của Database, vì sao cần chúng ta cần làm trên context ? Khi dữ liệu vật lý có nhiều User cùng chọc vào, khi đó có user đọc, có user ghi phần này, có user ghi phần kia, khi đó dữ liệu sẽ bị xung đột, nên sinh ra khái niệm context, chỉ khi nào chúng ta save data mới ảnh hưởng đến dữ liệu vật lý, tất cả thao tác xử lý xung đột sẽ được xử lý tự động, chỉ trừ trường hợp một user đã thực delete dữ liệu, một user khác save dữ liệu đó khi đó dữ liệu vật lý thật đã bị xoá khi đó hệ thống sẽ thông báo lỗi và chúng ta cần xử lý thủ công.
  • NSManagedObject: Cho phép Update entity, Insert entity,Delete entity trên Model design.
  • NSFetchRequest:  Đọc dữ liệu ra.

-Thêm Framework:

Screen Shot 2016-08-02 at 17.32.56

– Thiết kế mô hình coreData:

Mình sẽ tạo ra một mô hình Student gồm: name, studentId.

Vào File->New->File: chọn vào Core Data-> chọn vào Data Model.

Screen Shot 2016-08-02 at 15.36.20

Chọn next-> đặt tên là “studentModel”-> chọn vào nút create như vậy chúng ta đã tạo ra model coredata.Screen Shot 2016-08-02 at 15.39.18

 

Thiết kế:

Đặt tên ENTITIES là “Student”, Thêm thuộc tính cho entities “Student” :

Attribute : studentId kiểu dữ liệu Integer 16, name kiểu dữ liệu String. sau khi thêm chúng ta sẽ trông như ảnh sau:

Ralationships:Quan hệ giữa các bảng và Fetched Properties, các bạn có thể tham khảo thêm ở đây mình chỉ đơn giản giúp cácbạn truy vấn một bảng Student cơ bản.

Screen Shot 2016-08-02 at 15.43.40 Một số lựa chọn của thuộc tính:

click vào tên thuộc tính ví dụ như name, bên phải sẽ xuất hiện các lựa chọn thuộc tính:

Transient : Nếu tích vào thì giá trị cho thuộc tính, sẽ là dữ liệu nháp, không được lưu vào database, ví dụ như thuộc tính tuổi được suy ra từ thuộc tính ngày tháng năm sinh. khi đó ta không cần lưu tuổi mà chỉ cần lấy ra để so sánh tuổi chẳng hạn.

Optional: Khi tick vào  thì giá trị thuộc tính có thể không cần truyền giá trị vào.

Indexed: Khi tick vào thì giá trị thuộc tính là duy nhất dùng cho thuộc tính key.

Index in Spotlight: đánh chỉ mục tăng khả năng tìm kiếm

Store in External Record File: Ghi dữ liệu ra file ngoài. không ghi vào database.

Screen Shot 2016-08-02 at 15.48.30

 

 

 

Cuối hệ csdl có các thông tin: Add entity thêm thực thể( thêm bảng mới), Add Attribute( thêm thuộc tính cho bảng) nào đó chúng ta lựa chọn.

Có 2 kiểu xem Editor (bảng), và Style (giao diện trực quan).

Screen Shot 2016-08-02 at 16.11.46

 

Nếu có nhu cầu Update, insert thông tin hệ csdl core data, Chọn File -> new->File->Core Data->NSManagedObject subclass.

Screen Shot 2016-08-02 at 16.17.36

 

Chọn vào model cần update,insert->next-> chọn vào entity cần thay đổi ->next->create -> như thế là chúng ta đã update insert thành công.

có thể minh hoạ:

Screen Shot 2016-08-02 at 16.22.37 Screen Shot 2016-08-02 at 16.22.41

 

Như vậy chúng ta đã tạo được mô hình Core Data: “Student”.

-Kết nối mở model  để đọc ghi dữ liệu:

Trong ViewController.m!

Vào ViewDidload: Khởi tạo hàm kết nối mở model CoreData:”initializeCoreData”.

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initializeCoreData];
}

Định nghĩa  initializeCoreData:

Thêm đoạn mã sau: Để sao lưu model vào thư mục documents, và mở model “đơn giản thư mục Resource chỉ readonly không cho thay đổi thông tin”.

Trong mã code mình đã giải thích rất cụ thể từng dòng lệnh:

-(void) initializeCoreData{
    // Lấy đường dẫn Resource.
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"studentModel" withExtension:@"momd"];
    // Khởi tạo đối tượng Model lên theo url resource -> Đối tượng lưu lại Model.
    NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    // Có thể sinh ra lỗi như sai tên file or đuôi file.
    if (mom == nil) {
        NSLog(@"Error initializing Managed Object Model");
        return;
    }
    // Cầu nối dữ liệu hiện tại với nơi lưu trữ vật lý. Đọc và Load Model lên cũng như ghi xuống.
    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
    // Đối tượng quản lý file
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // lấy đường dẫn đến thư mục docments của ứng dụng.
    NSURL *documentsURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
    // Tạo đường dẫn đích đến file , tạo file infor null.
    NSURL *storeURL = [documentsURL URLByAppendingPathComponent:@"Student.sqlite"];
    
    NSError *error = nil;
    //NSPersistentStoreCoordinator lớp gộp sử dụng NSPersistentStore-> đối tượng thông tin lưu trữ model, để lưu trữ theo kiểu type nào, Tên file, Đưa ra lỗi khi lưu, cấu hình bổ xung cho file sqite, options tuỳ chọn khác. khác vs sqlite chỉ copy bởi vì ở đây resource lưu model.
    NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
    //  Nếu lỗi file.
    if (store == nil) {
        NSLog(@"Error initializing PSC: %@\n%@", [error localizedDescription], [error userInfo]);
    }
    // tạo một đối tượng context
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    // set model cho đối tượng  (context) moc
    [moc setPersistentStoreCoordinator:psc];
    // set context cho property.
    self.ManagedObjectContext = moc;

}

Tiếp theo là truy vấn thông tin Entity Student:

Trong main.StoryBoard, thiết kế giao diện như sau:

Đưa vào 5 button đặt tên như hình, minh hoạ cho 5 chức năng cơ bản của thực thể Student.

Screen Shot 2016-08-02 at 16.38.50Ánh xạ button và đặt tên trong file ViewController.h:

 

- (IBAction)Update:(id)sender;
- (IBAction)Show:(id)sender;
- (IBAction)Add:(id)sender;
- (IBAction)Delete:(id)sender;
- (IBAction)Filter:(id)sender;

Thêm đối tượng để lưu context tiện truy vấn:

@property(nonatomic,strong)NSManagedObjectContext *ManagedObjectContext;

– Add: Thêm 100 đối tượng Student: mình đã giải thích trong code.

// Thêm 100 đối tượng student.
- (IBAction)Add:(id)sender {
    for (int i=0; i<100;i++) {
        // Giống như đối tượng=[kiểudữliệu new]  tạo mới một đối tượng  trỏ vào vùng nhớ.
        // Ở đây tương tự, đó là tạo mới một đối tượng s vào trong Entity Student, Trên context.
        Student *s=[NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.ManagedObjectContext];
        // Gán giá trị cho thuộc tính studentId,name.
        s.studentId=@(i);
        s.name=[[NSString alloc]initWithFormat:@"name %d",i];
    }
    NSError *error=nil;
    // Lưu không thành công thì trả về mô tả về lỗi đó!.
    if ([self.ManagedObjectContext save:&error]==NO) {
        NSLog(@"Error saving context %@\n%@",[error localizedDescription],[error userInfo]);
    }
}

– Show: hiển thị danh sách tất cả bản ghi  Student:

-(IBAction)Show:(id)sender{
    // tạo một đối tượng  FetchRequest để đọc thông tin Entity Student.
    NSFetchRequest *request=[NSFetchRequest fetchRequestWithEntityName:@"Student"];
    NSError *error=nil;
    // Truy vấn trả về mảng đối tượng lưu trong results.
    NSArray *results=[self.ManagedObjectContext executeFetchRequest:request error:&error];
    // không có bản ghi thì trả vể error.
    if (!results) {
        NSLog(@"Error fetching Student object %@\n%@",[error localizedDescription],[error userInfo]);
        abort();
    }
    // trả về số lượng phần tử trong mảng results.
    NSLog(@"%d results ",results.count);
    for (Student *s in results) {
        //  log ra thông tin Student
        NSLog(@"%@- %@",s.studentId,s.name);
    }
    
}

– Delete: xoá tât cả các bản bản ghi:

- (IBAction)Delete:(id)sender {
    // đối tượng cho phép lấy dữ liệu
    NSFetchRequest *request=[NSFetchRequest fetchRequestWithEntityName:@"Student"];
    NSError *error=nil;
      // Truy vấn trả về mảng đối tượng lưu trong results.
    NSArray *results=[self.ManagedObjectContext executeFetchRequest:request error:&error];
    // không có bản ghi thì trả vể error.
    if (!results) {
        NSLog(@"Error fetching Student object %@\n%@",[error localizedDescription],[error userInfo]);
        abort();
    }
    // trả về số lượng phần tử trong mảng results.
    NSLog(@"%d results ",results.count);
    for (Student *s in results) {
        // xoá tất cả các đối tượng
        [self.ManagedObjectContext deleteObject:s];
        
    }
    // save context khi đã chỉnh sửa bản ghi
    if ([self.ManagedObjectContext save:&error]==NO) {
        NSLog(@"Error saving context %@\n%@",[error localizedDescription],[error userInfo]);
    }
}

– Update: thay đổi “name” thành chữ hoa:

- (IBAction)Update:(id)sender {
    // Tạo một đối tượng  FetchRequest để đọc thông tin Entity Student.
    NSFetchRequest *request=[NSFetchRequest fetchRequestWithEntityName:@"Student"];
    NSError *error=nil;
    // Truy vấn trả về mảng đối tượng lưu trong results.
    NSArray *results=[self.ManagedObjectContext executeFetchRequest:request error:&error];
    // không có bản ghi thì trả vể error.
    if (!results) {
        NSLog(@"Error fetching Student object %@\n%@",[error localizedDescription],[error userInfo]);
        abort();
    }
    // trả về số lượng phần tử trong mảng results.
    NSLog(@"%d results ",results.count);
    for (Student *s in results) {
        // đổi name thành chữ hoa.
        s.name=[s.name uppercaseString];
    }
    // save context khi đã chỉnh sửa bản ghi
    if ([self.ManagedObjectContext save:&error]==NO) {
        NSLog(@"Error saving context %@\n%@",[error localizedDescription],[error userInfo]);
    }
}

– Filter : lọc dữ liệu với mẫu “*3?”

- (IBAction)Filter:(id)sender {
    // tạo một đối tượng  FetchRequest để đọc thông tin Entity Student.
    NSFetchRequest *request=[NSFetchRequest fetchRequestWithEntityName:@"Student"];
    NSString *name=@"   ";// dấu ? có độ ưu tiên cao hơn *, ? thay thể bằng 1 ký tự, * có thể không or có tuỳ số lượng!.
    // set các điều kiên cho request.
    // set lấy mẫu dữ liệu
    [request setPredicate:[NSPredicate predicateWithFormat:@"name like %@",name]];
    // set sắp xếp tăng
    [request setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"studentId" ascending:YES]]];
    NSError *error=nil;
    // Truy vấn trả về mảng đối tượng lấy mẫu như như trên lưu trong results
    NSArray *results=[self.ManagedObjectContext executeFetchRequest:request error:&error];
    // không có bản ghi thì trả vể error.
    if (!results) {
        NSLog(@"Error fetching Student object %@\n%@",[error localizedDescription],[error userInfo]);
        abort();
    }
    // trả về số lượng phần tử trong mảng results
    NSLog(@"%d results ",results.count);
    // log ra giá trị studentId và name.
    for (Student *s in results) {
        NSLog(@"%@ -> %@",s.studentId,s.name);
    }
}

Như vậy cơ bản mình đã giới thiệu cho các bạn truy vấn một số câu lệnh cơ bản trong CoreData.

link full code:

http://www.mediafire.com/download/xl5ioqgssne8bux/coreData.zip

Phần tiếp theo: mình sẽ giới thiệu cho các bạn về login Facebook

Nếu các bạn muốn biết thêm các kỹ thuật khác về ios, các bạn có thể tham khảo thêm các khóa học ios tại đây.

 

`

 

 

 

Add a Comment

Your email address will not be published. Required fields are marked *