Thursday, October 15, 2015

Lập trình iOS: Bài 3 - Ứng dụng đầu tiên, tìm hiểu về UIWindow, UIView và UIViewController

Đã lâu không có thời gian post bài, hôm nay mình tranh thủ cùng các bạn tìm hiểu tiếp lập trình iOS với ứng dụng đầu tiên.
Hiện tại mình đang sử dụng Xcode 7.0.1, iOS 9.0
Ở bài 3 này, chúng ta sẽ tìm hiểu để nắm rõ hơn về UIWindow, UIView và UIWiewController, những khái niệm mà theo mình thì cách đây vài năm, với các phiên bản trước của Xcode sẽ giúp chúng ta hiểu sâu hơn, ở các bản mới sau này, mọi thứ gần như Apple đã giúp chúng ta làm hết cả.



1. Đầu tiên là bước tạo thông tin dự án từ Xcode




Chúng ta chọn Application và lấy mẫu Single View Application, tức là ứng dụng chỉ có 1 view (chúng ta sẽ tìm hiểu khái niệm này ở dưới)



Đặt tên dự án, chọn Objective-C (chúng ta sẽ tìm hiểu Swift ở các bài viết riêng về nó sau  này), theo mình nghĩ hiện tại vẫn nên theo bước Objective-C, khi các bạn đã ổn với nó thì học Swift cũng chưa muộn.
Sau khi tạo xong dự án, vào chọn Project Navigator ở panel bên trái, chúng ta sẽ thấy các file của dự án mà ta vừa tạo.


Chúng ta sẽ lướt qua sơ bộ các file này:
  • File main.m chứa phương thức main() được xem như là entry point của ứng dụng
  • File Infor.plist: file cấu hình thông tin của ứng dụng
  • Main.storyboard: đây được xem là file khởi đầu, chứa các giao diện NIB của ứng dụng, với dự án của chúng ta vừa tạo, file này chứa bên trong nó một UIViewController đã được thiết lập là Root cho ứng dụng.
  • Các file AppDelegate.*: được tạo mặc định, khai báo cho lớp Application Delegate cho ứng dụng của bạn
  • ViewController.*: là lớp ViewController mà chúng ta sẽ tìm hiểu tiếp ở phần sau
Tiếp theo, chúng ta click vào Main.storyboard

Click để phóng to

Ở vùng giữa, đó chính là giao diện NIB của ViewController đầu tiên, được thiết lập là Root của ứng dụng.

2. Tìm hiểu kiến trúc của một ứng dụng iPhone


Hình ở trên mô tả vòng đời chính của một ứng dụng iOS.
Khi user tap vào icon của ứng dụng, hệ thống sẽ launch ứng dụng dụng bằng việc gọi phương thức main() của nó (được khai báo trong file main.m), đây chính là entry point của ứng dụng.
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
Mỗi ứng dụng iPhone đều có một thể hiện duy nhất của lớp UIApplication, lớp này là cung cấp một điểm tập trung để kiểm soát và điều phối các ứng dụng chạy trên iPhone. Trong phương thức main() sẽ tạo ra một autorelease pool (được sử dụng để quản lý bộ nhớ) và thực hiện lời gọi phương thức UIApplicationMain của lớp UIApplication. Phương thức UIApplicationMain này sẽ tạo ra một thể hiện Singleton của lớp UIApplication, trong ứng dụng, ta có thể truy xuất thể hiện này qua phương thức shareApplication.

Trách nhiệm quản lý các hành vi mức cao của ứng dụng được lớp UIApplication giao lại cho đối tượng UIApplicationDelegate, đây thực chất là một protocol cung cấp các phương thức xử lý các sự kiện cơ bản của ứng dụng: khi ứng dụng được launch, ứng dụng chuyển xuống background, ứng dụng thoát, bộ nhớ không đủ… đối tượng UIApplicationDelegate này ta sẽ tạo ra và cung cấp cho đối tượng Singleton UIApplication (ta sẽ tìm hiểu việc cung cấp đối tượng delegate ở đoạn sau)

Và khi ứng dụng được launch, phương thức -(BOOL)application: didFinishLaunchingWithOptions: sẽ được gọi.

Chúng ta sẽ thấy được hàm này trong file AppDelegate.m, tạm chấp nhận về hàm này, chúng ta qua đến file AppDelegate.h, chúng ta sẽ thấy một thuộc tính đó là UIWindow


Đây chính là thuộc tính cốt lõi nhất của ứng dụng, window, như tên của nó, là cửa sổ ứng dụng, là màn hình hiển thị chính, nó sẽ có nhiệm vụ "mang vác" trên mình nó các đối tượng "visual" (mang tính "trực quan") sau này.
Với ứng dụng của ta vừa tạo, thuộc tính UIView của lớp ViewController sẽ được UIWindown này "mang vác", và khi đó view sẽ được hiển thị lên màn hình ứng dụng.

3. Vai trò của UIWindow, UIView và UIViewController

Như đã đề cập ở đầu bài viết, mục đích của chúng ta trước hết là hiểu sâu một chút về 3 đối tượng này, về vai trò, sự liên hệ giữa chúng.

Vai trò của UIWindow
  • Một ứng dụng iPhone thường chỉ có duy nhất một window, được đại diện bởi một thể hiện của lớp UIWindow. Ứng dụng của bạn tạo window này tại thời điểm launch ứng dụng, add một hoặc nhiều view vào nó và hiển thị. Sau đó, bạn hiếm khi cần lại đối tượng window này, như trong trường hợp ứng dụng của chúng ta, window chỉ add một view của Root ViewController, và sau đó nó giao lại toàn bộ quyền điều khiển cho Root ViewController này.
  • Trong iOS, một đối tượng window không có các đối tượng “trang sức” mang tính trực quan như nút đóng, thanh tiêu đề và nó không thể đóng trực tiếp bởi người dùng.
Vai trò của UIView
  • Một view, thể hiện của lớp UIView, định nghĩa một vùng trên màn hình (được gọi là frame, có tọa độ [x,y] của góc trên trái, width và height) trong ứng dụng iPhone, view đóng vai trò hiển thị giao diện và đáp ứng các tương tác với giao diện đó. Mỗi đối tượng view có trách nhiệm render nội dung và đáp ứng các sự kiện touch trong vùng của nó.
  • Ngoài trách nhiệm trên, view còn quản lý một hoặc nhiều view con của nó. Tức là, một view có thể add thêm nhiều view con bên trong nó
  • Chúng ta sẽ gặp các UIView này trong iOS qua cấu trúc cây sau

Vai trò của ViewController
  • ViewController là những đối tượng đóng vai trò trung tâm trong các ứng dụng iPhone. Giống như ý nghĩa tên của nó, ViewController có nhiệm vụ quản lý một view và trong iOS chúng còn giúp điều hướng và quản lý bộ nhớ.
  • Nếu chúng ta biết đến mô hình MVC, thì ViewController chính là controller, nó là "tầng giữa" để điều khiển các hoạt động liên quan đến View mà nó có trách nhiệm quản lý.

4. Ứng dụng Hello Wolrd

 Quay trở lại ứng dụng của chúng ta, ở mục 2 chúng ta đã biết đến UIWindow nên chúng ta sẽ không cần quan tâm đến nó nữa, tiếp theo chọn file ViewController.h


Qua đó, ta có thể thấy ViewController là một lớp mới được định nghĩa, và nó kế thừa từ lớp UIViewController (đây là lớp chuẩn của iOS, nó là đại diện của ViewController mà chúng ta đã nói ở trên). ViewController sẽ là nơi chúng ta "điều khiển" view hiển thị trong ứng dụng Single View của mình, việc "điều khiển" đó sẽ thực hiện ở trong file ViewController.m, thông qua các hàm của nó, nhưng trước hết, chúng ta cần biết view mà chúng ta sẽ điều khiển sẽ như thế nào đây?

Chọn Main.storyboard, chúng ta sẽ thấy View Controller Scene, tiếp đó là View Controller, đây chính là đối tượng của chúng ta đang tìm hiểu.


Click chọn View Controller, chúng ta sẽ thấy trong tab Indentity


Class của View Controller mà ta chọn (màu xanh) là ViewController (lớp mà ta định nghĩa ở file ViewController.h), ở đây do việc đặt tên mặc định của Xcode có vẻ làm chúng ta dễ nhầm lẫn, nếu ở ViewController.h ta đặt tên là MyViewController, thì ở mục Class (bên phải) chúng ta sẽ chọn lại là MyViewController.

Chọn sang tab Attributes, ta thấy


Trường "Is Initial View Controller" được check, điều này cho phép ứng dụng chúng ta biết ViewController này được chọn là Root ViewController của ứng dụng, và nó cùng với View của nó sẽ được add lên đối tượng Window đầu tiên.

Sau đó, chúng ta quay lại để tìm hiểu đối tượng View của ViewController như thế nào


Khi chúng ta click chọn View, vùng làm việc sẽ focus (màu lam) mà chúng ta thấy, đó chính là View, là vùng '"trực quan" mà ViewController của chúng ta sẽ điều khiển, bạn có thể thử đổi màu nền của nó để biết rõ hơn


Click phải chuột lên View Controller, chúng ta sẽ hiểu được mối liên hệ giữa View này và ViewController của chúng ta


Đối tượng View (màu xanh) đã được thiết lập mặc định kết nối với thuộc tính Outlet "view" của ViewController, và thuộc tính "view" này là duy nhất, điều này đánh dấu rằng View (màu xanh) của chúng ta sẽ được View Controller này "điều khiển".

Giờ thì thử run ứng dụng để kiểm tra


Tiếp theo, chúng ta sẽ thêm một vài đối tượng UIView khác vào view "xanh" của chúng ta để xây dựng ứng dụng đầu tiên Hello World.
Kéo 2 đối tượng Lable và Button vào view


Kết nối Outlets với lớp ViewController của chúng ta, việc này sẽ giúp ViewController "điều khiển" :)


Kết nối Label với thuộc tính _myLabel





Kết nối sự kiện Touch Up Inside của Button "Touch Me" với hàm buttonClick




Run ứng dụng


Tuy nhiên, khi chúng ta touch vào button Touch Me! thì không có gì xảy ra!
Điều này là hiển nhiên, vì chúng ta chưa "điều khiển" gì cả :D
Quay lại ViewController.m, chúng ta sẽ thêm và đoạn code vào hàm buttonClick:
- (IBAction)buttonClick:(id)sender {
    _myLabel.text = @"You have just touched on button!";
    _myLabel.textColor = [UIColor redColor];
}
Run lại ứng dụng và thấy chúng ta đã "điều khiển" như thế nào.


 Hy vọng qua bài viết này sẽ phần nào giúp các bạn hiểu rõ hơn cơ bản một ứng dụng iOS sẽ như thế nào, các thành phần chủ yếu của nó.
Và chúng ta sẽ tiếp tục  đi sâu vào các vấn đề khác nhau ở các bài viết tiếp theo.

Lập trình iOS: Bài 4 - UINavigationViewController và ứng dụng Multiple ViewController

No comments:

Post a Comment