Hướng dẫn lập trình macOS phần 3

Ở phần trước chúng ta đã hoàn thành việc tạo giao diện cho ứng dụng luộc trứng. Trong phần này chúng ta sẽ đưa các chức năng kết hợp với giao diện trong phần trước để hoàn thành ứng dụng.

Sandboxing

Trước khi đi vào chức năng, chúng ta cần tìm hiểu trước về Sandboxing. Nếu bạn là một lập trình viên iOS, chắc bạn đã quen với khái niệm này, nếu không thì hãy tiếp tục đọc. Ứng dụng dùng cơ chế sandbox sẽ có vùng nhớ độc lập hoàn toàn với hệ thống, không thể can thiệp vào các file của ứng dụng của chúng ta từ những ứng dụng khác, bị hạn chế quyền truy cập và quyền ghi. Đối với ứng dụng iOS, đây là cơ chế bắt buộc. Còn đối với macOS, nó là tuỳ chọn, tuy nhiên, nếu bạn muốn phân phối ứng dụng của bạn qua App Store của Mac,nó phải dùng sandbox. Thông thường, bạn nên dùng sandbox cho ứng dụng của bạn, bởi vì nó sẽ làm cho ứng dụng của bạn ít khả năng bị lỗi hơn.

Để bật Sandboxing ứng dụng của chúng ta, chọn phần project trong "Project Navigator". Chọn EggTimer trong danh sách "Targets", sau đó chọn "Capabilities" trong tab ở trên cùng. Bấn vào switch để bật "App Sandbox". Màn hình sẽ hiện ra cho chúng ta rất nhiều tuỳ chọn và quyền truy cập cho ứng dụng. Ứng dụng của chúng ta không cần phải thay đổi những tuỳ chọn ở bên dưới nên sẽ bỏ qua phần này.

Sắp xếp file

Nhìn vào phần "Project Navigator". Tất cả các file được liệt kê không có thứ tự nào. Tuy ứng dụng của chúng ta không có nhiều file nhưng vẫn phải sắp xếp chúng lại vào các folder để việc làm quen, từ đó khi đối mặt với các project lớn hơn sẽ rất hữu dụng cho việc tìm kiếm sau này.

Chọn 2 file view controller bằng cách click vào một file sau đó Shift-Click vào file còn lại. Chuột phải và chọn "New Group from Selection" từ popup menu. Đặt tên group là "View Controllers". Chúng ta sẽ cần một vài file model cho project, vì vậy ấn vào group EggTimer. Chuột phải và chọn "New Group", đặt tên nó là "Model".

Cuối cùng, chọn "Info.plist" và "EggTimer.entitlements" và đặt chúng vào group "Suppporting Files".

Kéo thả các group vào trong "Project Navigator" cho giống như ảnh.

Model

Chọn group "Model" trong "Project Navigator" và chọn File/New/File... Chọn macOS/Swift File và chọn Next. Đặt tên cho file là "EggTimer.swift" và chọn "Create" để tạo.

Ảnh trên là những properties của EggTimer. "TimerInterval" sẽ biểu hiện số giây.

Điều tiếp theo cần thêm vào là hai properties để kiểm tra điều kiện.

Có một vài shortcut có thể dùng để quản lý trạng thái của EggTimer.

Tạo một protocol trong EggTimer.swift nhưng bên ngoài class EggTimer.

Bắt đầu timer của EggTimer sẽ kích hoạt chức năng mỗi giây, thêm đoạn code sau để kích hoạt chức năng được gọi từ timer. Từ khoá "dynamic" cần có để Timer có thể tìm được function.

  1. "startTime" là một "Optional Date". Nếu như nó nil, timer sẽ không được chạy và không có gì xảy ra.
  2. Tính lại "elapsedTime". "startTime" sớm hơn thời gian hiện tại, vì vậy "timeIntervalSinceNow" sẽ tạo ra giá trị âm. Dấu âm sẽ đổi giá trị "elapsedTime" thành dương.
  3. Tính thời gian còn lại của timer, làm tròn về giây.
  4. Nếu timer đã hoàn thành, khởi động lại nó và gọi "delegate" nó đã hoàn thành. Nếu không phải, gọi "delegate" báo số giây còn lại.

  1. "startTime" đặt thời gian từ thời điểm hiện tại dùng "Date()" và đặt liên tiếp "Timer".
  2. "resumeTimer" là cái được gọi khi timer bị dừng và chạy lại. Thời gian bắt đầu sẽ được tính lại dựa trên elapsedTime.
  3. "stopTimer" dừng việc chạy timer.
  4. "resetTimer" dừng việc chạy timer và đặt properties về giá trị ban đầu.

Tất cả các function đều gọi "timerAction" để hiện việc cập nhật liên tục.

ViewController

Bây giờ đối tượng "EggTimer" đã hoạt động, đến lúc trở về ViewController.swift để hiện giá trị của đối tượng này, ViewController đã có các thuộc tính "@IBOutlet", nhưng bây giờ phải có một thuộc tính cho đối tượng "EggTimer":

và thêm dòng này vào "ViewDidLoad"

Điều này sẽ gây ra lỗi vì ViewController chưa thêm "EggTimerProtocol".

Lỗi sẽ biến mất vì ViewController đã có 2 function của "EggTimerProtocol", tuy nhiên "updateDisplay" hiện tại vẫn chưa tồn tại.

"updateDisplay" dùng function private để lấy text và ảnh cho thời gian còn lại, và hiện nó trong text field và image view.

"textToDisplay" chuyển hoá số giây còn lại sang "M:SS". "imageToDisplay" tính xem trứng đã hoàn thành được bao nhiêu tương đương với số phần trăm và chọn ảnh hiển thị cho phù hợp.

Vậy "ViewController" đã có đối tượng "EggTimer" và nó có chức năng lấy dữ liệu từ "EggTimer" và hiện thị kết quả, nhưng các button vẫn chưa hoạt động. Trong phần 2 chúng ta đã có các "@IBActions" cho các nút.

3 hành động gọi đến chức năng của "EggTimer" mà bạn đã thêm vào lúc trước.

Chạy ứng dụng và bạn sẽ nhận được kết quả giống như hình.

Ở phần sau chúng ta sẽ làm thêm chức năng cho các button trên menu và thêm vào âm thanh cho ứng dụng sống động hơn, cảm ơn các bạn đã theo dõi. Pref: https://www.raywenderlich.com/151748/macos-development-beginners-part-3