Xây dựng ứng dụng iPhone thứ hai – Phần 2


Thiết kế Model Layer

Hầu hết các ứng dụng đều phải xử lý dữ liệu. Trong bài học thứ hai này, ứng dụng cũng quản lý một danh sách các sự kiện hiển thị thông tin của các loài chim. Để tìm hiểu sâu hơn về Model-View-Controller (MVC) design pattern, bạn cần phải tạo ra các lớp để biểu diễn và quản lý dữ liệu này.

Trong phần này, bạn sẽ thiết kế hai lớp. Lớp thứ nhất biểu diễn khối dữ liệu chính mà ứng dụng quản lý. Lớp thứ hai tạo và quản lý sự thể hiện của các khối dữ liệu. Những lớp này cùng với danh sách chính chứa dữ liệu tạo nên model layer trong ứng dụng BirdWatching.

Xác định dữ liệu và tạo ra lớp dữ liệu

Để thiết kế lớp dữ liệu, việc đầu tiên ta phải làm là phân tích kỹ các chức năng của ứng dụng để xác định các thành phần dữ liệu cần quản lý. Ví dụ, ở đây bạn phải định nghĩa lớp Bird và lớp BirdSighting. Tuy nhiên để xử lý cho đơn giản thì các bạn chỉ cần định nghĩa ra một lớp dữ liệu đơn giản (BirdSighting) chứa các thuộc tính như “bird name”, “sighting location”, “date”…

Để tổ chức ra những đối tượng BirdSighting mà ứng dụng BirdWatching có thể sử dụng, bạn cần thêm một lớp mới trong project của bạn và là lớp con của NSObject.

Tạo lớp BirdSighting
  • Trong Xcode, chọn File > New > File (hoặc nhấn Command-N)
  • Trong hộp hội thoại xuất hiện, chọn Cocoa Touch trong phần iOS ở phần bên trái của hộp hội thoại
  • Trong vùng chính của hộp hội thoại, chọn Objective-C class và nhấn button Next.
  • Gõ tên của lớp là BirdSighting trong trường Class, chọn NSObject trong “Subclass of” pop-up menu và nhấn button Next
  • Trong hộp thoại hiển thị tiếp theo, chọn thư mục BirdWatching trong Group pop-up menu:
    SecondIPhoneApp6
  • Cuối cùng nhấn button Create

Xcode sẽ tạo ra hai file tên là BirdSighting.hBirdSighting.m trong thư mục BirdWatching của project.

Lớp BirdSighting cần một cách thức để lữu trữ thông tin của loài chim. Trong bài hướng dẫn này, các bạn sẽ khai báo các thuộc tính để biểu diễn những phần tử đó.

Khai báo thuộc tính (properties) và phương thức (initial methods) trong interface BirdWatching.h
  1. Chọn interface BirdSighting.h trong project navigator để mở vùng soạn thảo
  2. Thêm đoạn mã lệnh sau giữa hai câu lệnh @interface@end:
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, copy) NSString *location;
    @property (nonatomic, strong) NSDate *date;
  3. Thêm đoạn mã lệnh sau sau dòng khai báo thuộc tính thứ ba:
    -(id)initWithName:(NSString *)name location:(NSString *)location date:(NSDate *)date;
Xây dựng nội dung cho các phương thức khởi tạo trong lớp thực thi BirdWatching.m
    1. Trong project navigator, chọn file BirdSighting.m. Khi BirdSighting.m mở trong vùng soạn thảo, Xcode hiển thị một biểu tượng thông báo ở giữa của thanh công cụ và ở trên vùng soạn thảo. Nhấn vào button khuyến cáo ở trên navigator selector bar để hiển thị khuyến cáo.
      SecondIPhoneApp8
    2. Trong trường hợp này, Xcode nhắc các bạn rằng trong lớp BirdSighting chưa khởi tạo phương thức initWithName. Bạn hãy xử lý ngay vấn đề ngay.
    3. Trong vùng soạn thảo mã lệnh, giữa câu lệnh @implementation@end trong file BirdSighting.m, hoàn thiện phương thức initWithName.
      SecondIPhoneApp7
    4. Gõ đoạn mã lệnh sau đây trong phương thức initWithName:
-(id)initWithName:(NSString *)name location:(NSString *)location date:(NSDate *)date
    {
    self = [super init];
    if (self) {
       _name = name;
       _location = location;
       _date = date;
       return self;
    }
    return nil;
}

Lớp BirdSighting là một phần trong model layer của ứng dụng BirdWatching. Để bảo vệ lớp BirdSighting như là đại diện thuần tuý của một đối tượng model, bạn phải thiết kế một lớp controller để tạo thể hiện của lớp BirdSighting và điều khiển một danh sách chứa các thực thể đó. Một lớp data controller cho phép các đối tượng khác trong ứng dụng có thể truy xuất vào từng cá thể BirdSighting và danh sách chính mà không cần thiết phải biết đến bất cứ vấn đề gì liên quan đến data model được khởi triển khai như thế nào. Bước tiếp theo bạn sẽ tạo ra lớp data controller.

Tạo lớp Data Controller

Một lớp data controller cụ thể quản lý viêc nạp, lưu trữ và truy xuất dữ liệu của một ứng dụng. Mặc dù ứng dụng BirdWatching không cho phép truy xuất vào một file để nạp hoặc lưu trữ dữ liệu, nó vẫn cần thiết một data controller để tạo nên một đối tượng BirdSighting và quản lý danh sách của chúng. Cụ thể, lớp đó sẽ như sau:

      • Tạo ra một danh sách chính nhằm lưu trữ tất cả các đối tượng BirdSighting
      • Trả về số lượng các đối tượng BirdSighting trong danh sách
      • Trả về một đối tượng BirdSighting tại một vị trí cụ thể trong danh sách
      • Tạo ra một đối tượng BirdSighting với thông tin nhập từ bàn phím và đưa nó danh sách

Với những thao tác trên với lớp BirdSighting, bạn sẽ tạo interface và lớp thực thi mới thừa kế tới đối tượng NSObject trong project của bạn.

Tạo lớp Data Controller
      • Trong Xcode, chọn File > New > File (hoặc nhấn Command-N)
      • Trong hộp hội thoại xuất hiện, chọn Cocoa Touch trong phần iOS ở phần bên trái của hộp hội thoại
      • Trong vùng chính của hộp hội thoại, chọn Objective-C class và nhấn button Next.
      • Gõ tên của lớp là BirdSightingDataController trong trường Class, chọn NSObject trong “Subclass of” pop-up menu và nhấn button Next
      • Trong hộp thoại hiển thị tiếp theo, chọn thư mục BirdWatching trong Group pop-up menu.
      • Cuối cùng nhấn button Create

Trong bài hướng dẫn này, danh sách chứa các đối tượng BirdSighting được biểu diễn bởi một mảng (array). Nếu bạn sử dụng NSMutableArray, thì mỗi lần thêm phần tử thì kích cỡ của mảng sẽ tự động tăng theo.

Khai báo thuộc tính của data controller
      • Mở BirdSightingDataController.h ở chế độ soạn thảo
      • Thêm đoạn code sau đây giữa dòng lệnh @interface@end:
         @property (nonatomic, copy) NSMutableArray *masterBirdSightingList;

        Chú ý về copy attribute trong định nghĩa thuộc tính masterBirdSightingList: Nó chỉ ra rằng một bản copy nên được sử dụng cho việc gán giá trị. Sau đó, trong file thực thi, bạn sẽ tạo ra phương thức setter cho để đảm bảo rằng bản copy của mảng sẽ cũng có thể mở rộng.

Khai báo ba phương thức truy xuất dữ liệu của data controller
      • Trong file BirdSightingDataController.h,hêm đoạn mã lệnh sau đâu phía sau phần khai báo property:
        - (NSUInteger)countOfList;
        - (BirdSighting *)objectInListAtIndex:(NSUInteger)theIndex;
        - (void)addBirdSightingWithSighting:(BirdSighting *)sighting;

        Chú ý rằng Xcode sẽ hiển thị một biểu tượng màu đỏ bên trái của phương thức objectInListAtIndexaddBirdSightingWithSighting. Khi bạn nhấn vào đó, Xcode sẽ hiển thị thông báo “Expected a type.” Điều này có nghĩa là Xcode chưa nhận ra BirdSighting như là một kiểu trả về. Để sửa lỗi này, bạn cần phải thêm một khai báo chuyển tiếp (fordward).

      • Thêm một khai báo chuyển tiếp trong lớp BirdSighting thông qua việc gõ đoạn mã lệnh sau giữa hai câu lệnh #import@interface ở phần mở đầu của file header:
        @class BirdSighting;
Triển khai phương thức tạo danh sách
      • Thêm đoạn mã lệnh sau vào đầu của file:
         #import "BirdSighting.h
        #import "BirdSightingDataController.h"
      • Khai báo phương thức tạo danh sách bằng cách thêm câu lệnh @interface trước câu lệnh @implementationCâu lệnh @interface sẽ như sau:
 @interface BirdSightingDataController ()
- (void)initializeDefaultDataList;
@end
      • Đoạn mã lệnh @interface BirdSightingDataController () được gọi trong phần mở rộng lớp.
      • Xây dựng phương thức tạo danh sách bằng cách thêm đoạn mã lệnh sau giữa câu lệnh @implementation và câu lệnh @end:
        - (void)initializeDefaultDataList {
            NSMutableArray *sightingList = [[NSMutableArray alloc] init];
            self.masterBirdSightingList = sightingList;
            BirdSighting *sighting;
            NSDate *today = [NSDate date];
            sighting = [[BirdSighting alloc] initWithName:@"Pigeon" location:@"Everywhere" date:today];
            [self addBirdSightingWithSighting:sighting];
        }

        Phương thức initializeDefaultDataList thực hiện những công việc sau: Đầu tiên, nó gán một mutable array cho biến sightingList. Sau đó, nó sử dụng một vài dữ liệu mặc định để tạo ra một đối tượng BirdSighting mới và truyền nó tới phương thức addBirdSightingWithSighting mà bạn đã khai báo ở phần trước nhằm thêm phần tử birdslighting mới vào danh sách chính.

Tạo setter cho thuộc tính danh sách chính (master list)

Thêm đoạn mã lệnh dưới đây, trong đoạn mã @implementation của file BirdSightingDataController.m:

- (void)setMasterBirdSightingList:(NSMutableArray *)newList {
    if (_masterBirdSightingList != newList) {
        _masterBirdSightingList = [newList mutableCopy];
    }
}

Mặc định, Xcode không bao gồm khởi tạo phương thức init khi bạn tạo lớp method when you create new Objective-C class files. This is because most objects don’t need to do anything other than call [super init]. In this tutorial, the data controller class needs to create the master list.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: