Tôi đã viết app cho Apple Watch như thế nào(P1)?

Sau dự án XXXiOS tôi may mắn được đội Dọn Rác thuê theo hợp đồng cho mượn ngắn hạn để sang nghiên cứu và làm 1 cái khá là mới mẻ: Apple Watch. Được cấp trên đầu tư thời gian, điều kiện để nghiên cứu nên cũng muốn chia sẻ những gì mình biết được qua tìm hiểu cũng như làm dự án thực tế: Crisis Management.


Có thể trên mạng đã có tương đối các bài viết hướng dẫn, giới thiệu đầy đủ về Apple Watch và WatchKit nhưng tôi vẫn muốn viết lại. Để chia sẻ với mọi người trong 3S đặc biệt là team iOS cùng 1 số bạn ham mê tự học Objective-C. Có thể bài viết của tôi không được chi tiết, không nói hết được các đặc điểm của WatchKit nhưng ít nhất nó được rút ra từ việc làm sản phẩm thực tế chứ không phải là làm các ứng dụng đơn giản mục đích demo. Đặc biệt hơn nữa là nó viết bằng Tiếng Việt :D.

1. Lời nói đầu

Do mới chỉ làm 1 ứng dụng Crisis nên tôi chỉ nói đến các vấn đề xoay quanh nó. Những thông tin, vấn đề cơ bản xin các bạn đọc tài liệu hướng dẫn của Apple. Các tính năng, kĩ thuật khác sẽ được bổ sung trong tương lai hoặc nếu bạn cần hướng dẫn 1 cách đầy đủ nhất vui lòng đọc quyển WatchKitTutorials v1.1 – RayWenderlich trên fileserver 3S (cám ơn anh Tuấn.PQ) – 1 cuốn sách khá đầy đủ, dễ hiểu, thực tế và khá vui nhộn.

Ngoài ra bạn có thể tham khảo blog các nhân của 1 nữ iOS Developer: Natasha Murashev – http://natashatherobot.com

2. Giới thiệu về Apple Watch SDK – WatchKit

Bỏ qua các thông tin về phần cứng, cách thức hoạt động cơ bản mà bạn có thể dễ dàng tìm đọc trên mạng, tôi xin phép đi luôn vào phần quan trọng nhất. Câu hỏi đặt ra với người mới tìm hiểu về Apple Watch là: Apple Watch hoạt động như thế nào, chúng giao tiếp với iPhone/iPad ra sao?…

 

Apple Watch hoạt động dựa vào App Extension API mà Apple công bố cùng với iOS8. Ở thời điểm hiện tại, bạn chỉ có thể chạy ứng dụng trên Apple Watch như là phần mở rộng của 1 ứng dụng trên iPhone. Apple Watch không thể chạy độc lập.

Apple Watch có thể kết nối wifi vậy nó có thể vào mạng, request data từ Server…? Câu trả lời là KHÔNG!

Tất cả các việc xử lý, request dữ liệu đều do iPhone xử lý, sau đó sẽ chuyển dữ liệu sang cho Apple Watch hiển thị. Apple chỉ có nhiệm vụ là hiển thị giao diện và nhận tương tác của người dùng sau đó gửi cho thiết bị chủ – iPhone. Cơ chế hoạt động này khá giống với cơ chế Client-Server.


Vậy Apple Watch truyền dữ liệu qua lại với iPhone như thế nào?

Apple Watch hoạt động dựa vào App Extension vì thế việc truyền dữ liệu với iPhone được Apple khuyên khích thông qua Shared App Group. Khi có bất kì thay đổi nào về dữ liệu, iPhone sẽ update data ở môi trường chạy ngầm, khi nào Apple Watch cần truy xuất dữ liệu thì nó đã sẵn sàng. Phần này tôi sẽ nói cụ thể hơn ở các bài sau.

1 số Controller cơ bản trong WatchKit:

  • WKInterfaceController  ~ UIViewController
  • WKInterfaceButton ~ UIButton
  • WKInterfaceGroup
  • WKInterfaceTable ~ UITableView

3. Ứng dụng Crisis Management

Crisis Management là 1 hệ thống quản lý, cảnh báo khủng hoảng(thiên tai). Các khủng hoảng( crisis) được định nghĩa sẵn trong cơ sở dữ liệu và người dùng chỉ cần lấy danh sách của chúng về thực hiện việc kích hoạt (activate). Done. Nghe khá là đơn giản đúng không.

Do hệ thống mới ở bước đầu của giai đoạn phát triển nên tính năng còn khá sơ khai, nhất là với người dùng trên mobile. Tuy nhiên gì thì gì, Apple Watch còn mới nên khá là ham hố làm ứng dụng cho nó, mà đã làm là phải đủ cả: Main App, Notification và cả Glance nữa.

  • Main App thì chính là Main Screen của app.
  • Notification: cơ bản là không khác gì trên iPhone.
  • Glance: nó giống như là màn hình tổng quan của app, sẽ được nói tới ở các bài viết sau khi đã có Device để test.

3.1. Main App

Tôi xin phép đi từ màn hình Home trước vì nó là linh hồn của app cũng như phần cho phép tùy biến, thực nhiện nhiều thao tác nhất. Phần này chiếm phần lớn thời gian tôi làm app.

Sẽ có 3 màn hình: Home ->Crisis List -> Activate Screen:

– Màn hình Home thì đơn giản có mỗi 1 label Crisis Management là tên app và 1 button Activate để di chuyển đến màn hình CrisisList nên tôi xin bỏ qua.

– Màn hình tiếp theo là CrisisList sẽ có 1 Table để hiện thị danh sách các crisis được lấy về từ server thông qua API.

Mỗi 1 row sẽ chứa 1 crisis với các thông tin: ảnh đại diệntên Crisis ở trên và Branche – chi nhánh(địa điểm) xảy ra. Đây là các crisis chưa được kích hoạt nghĩa là nó hiện không xảy ra.

Dưới đây là các thành phần giao diện cơ bản của Crisis List sử dụng WKInterfaceTable:

Table trong WatchKit được gọi là WKInterfaceTable ~ UITableView, được  sử dụng giống như Tabe trên iOS(UIKit) nhưng đơn giản hơn

Sự khác nhau cơ bản giữa chúng là ở Section:

Theo như hình thì Table trên WatchKit sẽ có ít khả năng tùy biến hơn nhưng tại sao Apple lại làm được 1 app như hình dưới, giống như là có section:

Thực ra dòng có hình chiếc cốc + chữ Drinks cũng chính là 1 row được tùy biến. Các row trong WKInterfaceTable có các WKRowController để thực hiện việc điều khiển, hiển thị. 1 Table có thể hiển thị được nhiều Row khác nhau. Để tạo thêm Row bạn hãy chọn Table và khai báo số RowController mà bạn muốn:

1. Chọn Table cần tùy biến

 

2. Khai báo số CustomRow cho Table

3. Chọn  RowController muốn tùy biến

4. Khai báo Controller Class cho Row

– Như vậy là xong phần tạo giao diện. Tiếp theo là phần viết code cho Controller.

Nếu như trong WKInterfaceController có duy nhất 1 Table thì bạn có thể truy xuất trực tiếp nó thông qua getter table giống như với UIKit. Ở đây tôi vẫn tạo property IBOutlet riêng cho nó để… đỡ nhầm

 Để thuận tiện cũng như các bạn không khỏi bỡ ngỡ tôi dùng thêm 1 thư viện là IGInterDataTable của Instagram. Bình thường thì WKInterfaceTable chỉ làm việc tốt với mảng 1 chiều, với mảng đa chiều thì bạn phải thực hiện tính toán, chuyển đổi mất khá nhiều thời gian và dễ nhầm lẫn.

Việc sử dụng IGInterDataTable cho phép chúng ta làm việc với Table DataSource giống như của UIKitcó Section, NSIndexPath, reloadData(mặc định không có cơ chế reload lại table trên WatchKit)…

Tìm hiểu Lifecyle của WKInterfaceController bạn sẽ thấy chỉ có 3 trạng thái: awakeWithContextwillActivate và didDeactive. Đọc tên chắc bạn cũng hiểu được ý nghĩa của chúng rồi nhưng lưu ý là: willActive sẽ được gọi bất cứ khi nào view được hiển thị đặc biệt là khi bạn khóa màn hình và unlock trở lại. didDeactive cũng tương tự.

Chúng ta sẽ viết code gọi API để lấy về danh sách Crisis trong phương thức: awakeWithContext. Mục đích là chỉ request lên server 1 lần.

Data trả về sẽ là 1 list các Branches, trong mỗi Branche sẽ có nhiều các Events – chính là Crisis mà tôi cần.

 

Sauk hi có được dữ liệu bạn sẽ dễ dàng set DataSource, config Row cho Table 1 cách dễ dàng:


Xin lưu ý trong phương thức: – (NSString *)table:(WKInterfaceTable *)table rowIdentifierAtIndexPath:(NSIndexPath *)indexPath

Ở đây tôi tôi trả về 1 String  = “CRWRow” ở đây chính là Segue Identifier của RowController. Việc sử dụng Segue Identifier nhằm giúp xác định View tương ứng với RowController mà bạn muốn. Nôm na là bạn muốn Row ở IndexPath A sẽ dùng Custom Row View trong Storyboard có Identifiert là CRWRow. Chính ra không giải thích có khi lại dễ hiểu hơn

OK, bây giờ chạy thử và nếu không có gì sai sót ta sẽ có 1 danh sách các Crisis tương tự như hình dưới. (Lưu ý code trên chỉ là demo, bạn nào muốn code chạy được thực sự vui lòng liên hệ tác giả).

Phần 1 xin tạm dừng tại đây.

Sang phần sau tôi sẽ cố gắng nói tiếp về việc tùy biến giao diện trên Apple Watch sử dụng WKInterfaceGroup cùng các thuộc tính của WKInterfaceObject.

Ngoài ra có thể sẽ nói thêm về cơ chế trao đổi dữ liệu với iPhone + tối ưu tốc độ sử dụng Image Cached.



Khám phá những thành phần mới cho Android Material Design trong v28 Android Design Support Library