() translation by (you can also view the original English article)
Ngày 2012, Apple cho ra mắt iCloud bên cạnh iOS 5. Cùng thời điểm, công ty này tuyên bố rằng nhà phát triển có quyền truy xuất iCloud thông qua một số API. Trước tiên, các nhà phát triển có 3 chọn lựa:
Tuy nhiên, các API này không hoàn hảo. Nhược điểm lớn nhất của chúng là thiếu minh bạch. Cụ thể là Core Data Integration đã gây ra sự thất vọng và thất bại cho trải nghiệm từ các nhà phát triển giàu kinh nghiệm. Khi mọi thứ không ổn, nhà phát triển không biết ai hoặc cái gì là thủ phạm. Đó là có thể một vấn đề ở trong mã nguồn của họ hoặc của Apple.
CloudKit
Tại WWDC 2014, Apple đã giới thiệu CloudKit, một framework mới hoàn toàn tương tác trực tiếp với các máy chủ iCloud của Apple. Framework được so sánh với một số giải pháp PaaS (Platform as a Service - dịch vụ cung cấp nền tảng phát triển), như Firebase. Tương tự Firebase, Apple cung cấp API linh hoạt và trang quản trị cho phép nhà phát triển nhìn thấy dự liệu lưu trữ trên các máy chủ iCloud của Apple.
Điều tôi thích nhất ở CloudKit là sự tận tâm của chính Apple cho framework này. Theo chính công ty chia sẻ, iCloud Drive và iCloud Photo Library được xây dựng trên CloudKit. Điều này cho thấy framework CloudKit và cơ sở hạ tầng của nó rất mạnh mẽ và đáng tin.
Là một người phát triển, dấu hiệu lòng tin và sự tận tuỵ rất quan trọng. Trong quá khứ, Apple thi thoảng phát hành các API bị vướng các lỗi hoặc thiếu sót những tính năng quan trọng đơn giản vì công ty không dự định sử dụng chính sản phẩm của mình. Điều này không đúng cho CloudKit. Và nó đầy hứa hẹn.
Bạn có nên dùng CloudKit?
Key-value storage (lưu trữ theo khoá-giá trị) và document storage (lưu trữ kiểu tài liệu) có công dụng riêng, và Apple nhấn mạnh rằng CloudKit không thay thế hoặc chống lại các API hiện có của iCloud. Điều này cũng tương tự với Core Data. Ví dụ CloudKit không đề xuất local storage (lưu trữ cục bộ). Có nghĩa là một ứng dụng chạy trên một thiết bị mà không có kết nối mạng sẽ vô ích nếu chỉ dựa vào CloudKit.
Apple cũng nhấn mạnh rằng việc xử lý lỗi rất quan trọng khi làm việc cùng CloudKit. Nếu thao tác save không thành công, và người dùng không nhận được thông báo, thì họ có lẽ thậm chí không biết dữ liệu của họ chưa được lưu lại - và đã mất.
CloudKit là một giải pháp tuyệt vời để lưu trữ dữ liệu có cấu trúc và không cấu trúc trên cloud. Nếu bạn cần một giải pháp để truy xuất dữ liệu trên nhiều thiết bị, vậy CloudKit là một chọn lựa khả dĩ để cân nhắc.
Tại WWDC 2015, Apple đã làm điều mà vài nhà phát triển mong đợi hoặc từng hi vọng. Họ đã tuyên bộ một dịch vị web cho CloudKit. Nghĩa là CloudKit có thể dùng trên bất kỳ nền tảng nào, bao gồm Android và Windows Phone.
Giá cả của Apple cũng khá cạnh tranh. Bắt đầu với CloudKit được miễn phí, và điều này duy trì cho đa số các ứng dụng. Lại lần nữa, CloudKit rất đáng xem xét nếu bạn dự định lưu trữ dữ liệu trên cloud.
Những khái niệm của CloudKit
Nhà phát triển đang đấu tranh với Core Data thường không thông thuộc với những block của framework. Nếu bạn không dành thời gian học và hiểu Core Data, thì bạn khó tránh phải gặp phải khó khăn. Tương tự cho CloudKit.
Trước khi bắt đầu làm việc với ứng dụng mẫu sử dụng CloudKit, tôi muốn dành ít phút giới thiệu với bạn một số khái niệm then chốt của framework CloudKit và cơ sở hạ tầng của nó. Hãy bắt đầu với container, database và sandboxing.
Sự riêng tư và chính sách ngăn chặn
Apple rất minh bạch rằng riêng tự là một khía cạnh quan trong của CloudKit. Điều trước tiên cần biết là mỗi ứng dụng có container riêng của nó trên iCloud. Khái niệm này tương tự với cách ứng dụng iOS có sandbox riêng của chúng. Tuy nhiên, container có thể được chia sẽ giữa các ứng dụng miễn là những ứng dụng đó tương tác với cùng một tài khoản người phát triển. Như bạn có thể hình dung, điều này mở ra những khả năng thú vị cho những nhà phát triển.
Container của CloudKit gồm vài database. Mỗi container có một public database (công khai) có thể dùng để lưu dữ liệu có thể được truy xuất với mỗi người của ứng dụng của bạn. Ngoài database chung đó, một container cũng có một private database (dùng riêng) cho mỗi người dùng ứng dụng của bạn. Database riêng của mỗi người dùng được sử dụng để lưu dữ liệu đặc thù của người dùng đó. Sự phân biệt và đóng gói dữ liệu là thành phần chính của CloudKit và hạ tầng iCloud.
Thậm chí container của một ứng dụng có thể chứa nhiều database, từ phía nhà phát triển một container chỉ có hai database: public database và private database của người dùng đang đăng nhập vào tài khoản iCloud của họ. 2017, Apple giới thiệu database thứ 3, shared database (được chia sẻ chung), cung cấp cho ứng dụng khả năng chia sẻ một phần các bản ghi với một private database từ người dùng khác, mời họ đóng góp vào những bản ghi được chia sẻ.
Tôi sẽ nói nhiều hơn về các tài khoản iCloud sau.
Records (bản ghi) và Record Zones
Database của container từ một ứng dụng lưu các bản ghi. Điều này không quá khác biệt với một database truyền thống. Đầu tiên, bản ghi được lưu trong một database của CloudKit không có gì hơn một từ điển các cặp key-value (khoá & giá trị). Chúng giống như các từ điển phô trương nhưng đó chỉ là một phần của câu chuyện.
Mỗi bản ghi có một record type (kiểu bản ghi) và một số trường metadata. Một metadata của bản ghi theo dõi khi nào bản ghi được tạo ra, người dùng nào tạo ra bản ghi, lần gần nhất bản ghi được cập nhật là lúc nào, và ai đã cập nhật.
Class CKRecord đại diện cho kiểu bản ghi này, và nó là một class khá mạnh mẽ. Các giá trị bạn lưu trong một bản ghi không giới hạn với kiểu danh sách thuộc tính. Bạn có thể lưu string (chuỗi), number (số), date (ngày tháng) và blob trong một bản ghi, nhưng class CKRecord cũng xử lý dữ liệu location (địa điểm), CCLocation, như một kiểu dữ liệu first-class.
Thậm chí bạn có thể lưu nhiều mảng (array) của những kiểu dữ liệu được hỗ trợ trong một bản ghi. Nói cách khác, nhiều mảng của nhiều chuỗi hoặc con số không gặp vấn đề gì với một đối tượng CKRecord.
Các bản ghi được sắp xếp trong record zone (các khu vực của bản ghi). Một record zone nhóm những bản ghi có liên quan. Mặc định thì public database và private database có record zone riêng biệt, nhưng có thể tạo một record zone mới nếu cần thiết. Record zone là chủ đề nâng cao nên ta không thảo luận nhiều trong loạt bài viết này.
Relationships
Relationships (sự liên hệ) giữa các bản ghi được quản lý qua các đối tượng của class CKReference. Hãy nhìn vào ví dụ để hiểu chính xác hơn cách relationship hoạt động. Ứng dụng chúng ta tạo ra trong loạt bài này sẽ quản lý một số danh sách mua hàng. Mỗi danh sách có thể có nhiều sản phẩm hoặc không có sản phẩm nào. Có nghĩa là mỗi sản phẩm cần một tham chiếu đến danh sách chứa nó.



Việc hiểu rõ sản phẩm có một tham chiếu đến danh sách chứa nó rất quan trọng. Trong khi có thể tạo một mảng của các giá trị của CKReference cho các sản phẩm trong một danh sách, thì tiện lợi hơn và được khuyến khích là thêm foreign key (khoá tham chiếu) với sản phẩm, không phải cho danh sách. Đó là điều Apple khuyến nghị.
CloudKit quản lý relationship theo cách khá cơ bản, nhưng cung cấp một chọn lựa để tự động xoá đi bản ghi thứ cấp khi bản ghi cấp cao của nó được xoá. Chúng ta sẽ xem xét rõ hơn vào relationship sau trong loạt bài này.
Các tài nguyên
Tôi cũng muốn đề cập class CKAsset. Trong khi có thể lưu dữ liệu blob trong bản ghi, thì dữ liệu không được cấu trúc (như hình ảnh, âm thanh, và đoạn phim) nên được lưu thành giá trị của CKAsset. Giá trị CKAsset luôn liên kết với một bản ghi, và nó tương ứng với một file trên disk. Chúng ta sẽ không làm việc với CKAsset trong loạt bài này.
Xác thực
Tôi bảo đảm bạn đồng ý rằng CloudKit thật sự hấp dẫn. Tuy nhiên có một chi tiết quan trọng mà ta chưa thảo luận: xác thực. Người dùng tự xác thực thông qua tài khoản iCloud của họ. Những người dùng không đăng nhập vào tài khoản iCloud không thể ghi dữ liệu vào iCloud.
Mặc dù điều này đúng với bất kỳ API iCloud nào, nhưng hãy nhớ rằng các ứng dụng chỉ dựa vào CloudKit sẽ không hoạt động trong tình huống đó. Tất cả người dùng có thể làm là truy xuất dữ liệu trong public database, nếu được nhà phát triển cấp phép.
Đọc dữ liệu
Người dùng không đăng nhập vào tài khoản iCloud của họ vẫn có thể đọc dữ liệu từ public database. Điều không cần nói là private database không cho phép truy xuất khi không biết ai là người đang sử dụng ứng dụng.
Đọc và ghi
Khi đã đăng nhập, người dùng có thể đọc và ghi vào public và private database của họ. Tôi đã nhắc qua Apple cực kỳ coi trọng quyền riêng tư. Do đó, các bản ghi được lưu trữ trong private database và chỉ cho phép người dùng đó truy xuất. Ngay cả bạn, nhà phát triển, không thể nhìn thấy dữ liệu mà người dùng đã lưu trữ trong private database của họ. Đây là mặt bất lợi của việc Apple dành quyền quản lý back-end ứng dụng của bạn, nhưng lại là lợi điểm cho người dùng.
Danh sách mua sắm
Ứng dụng chúng ta sắp xây dựng sẽ quản lý danh sách mua sắm của bạn. Mỗi danh sách mua sắm sẽ có tên và có nhiều sản phẩm (hoặc không có cái nào). Sau khi xây dựng ứng dụng danh sách mua sắm, bạn sẽ cảm thấy khá thoải mái khi sử dụng framework CloudKit trong dự án của riêng bạn.
Điều kiện tiên quyết
Trong bài hướng dẫn này, tôi sẽ sử dụng Xcode 9 và Swift 4. Nếu bạn đang sử dụng phiên bản Xcode cũ hơn, thì nhớ rằng bạn đang sử dụng một phiên bản khác của ngôn ngữ lập trình Swift. Điều này có nghĩa là bạn sẽ cần cập nhật mã nguồn của dự án cho phù hợp với trình biên dịch. Đa số những thay đổi khá nhỏ, nhưng quan trọng là bạn phải nhận thức được điều này.
Vì CloudKit là một chủ đề nâng cao, tôi sẽ giả sử bạn đã quen thuộc với Xcode lẫn ngôn ngữ lập trình Swift. Nếu bạn mới phát triển iOS, sau đó tôi khuyên bạn nên đọc hướng dẫn giới thiệu đầu tiên hoặc tham gia một trong số khóa học của chúng tôi về phát triển Swift:
- SwiftCreate iOS Apps With SwiftMarkus Mühlberger
- Design PatternsSwift Design PatternsDerek Jensen
Hãy bảo đảm bạn xem chúng nếu chỉ mới phát triển iOS hoặc ngôn ngữ Swift.
Thiết lập dự án
Đã đến lúc bắt đầu viết code. Khởi động Xcode và tạo một dự án mới theo mẫu Single View Application.



Đặt tên cho dự án của bạn và organization identifier (định danh tổ chức) cho nó. Kết quả sẽ tạo ra một bundle identifier, dùng để tạo identifier (mã định danh) của container mặc định cho ứng dụng của bạn. Identifier cần phải là duy nhất với các tài khoản nhà phát triển khi họ chia sẻ cùng một namespace. Do đó rất quan trọng khi tuân theo lời khuyên từ Apple và sử dụng reverse domain name notation (quy tắc đặt tên đảo nghịch).



Kích hoạt iCloud
Bước tiếp theo là kích hoạt iCloud và CloudKit. Chọn dự án trong Project Navigator ở bên trái và chọn mục tiêu cho ứng dụng của bạn từ danh sách các mục tiêu. Mở tab General và xét Team sang team chính xác. Để tránh gặp vấn đề trong bước tiếp theo, hãy xác minh rằng tài khoản nhà phát triển của bạn có các quyền cần có để tạo App ID.



Tiếp theo, mở tab Capabilities ở trên cùng và bật kích hoạt chế độ iCloud thành on. Xcode sẽ cần chút thời gian để tạo App ID đại diện cho bạn. Các quyền lợi cần thiết cũng sẽ được thêm vào ứng dụng. Nếu cách này không hiệu quả, hãy đảm bảo team được thiết lập chính xác và bạn có các quyền cần thiết để tạo App ID.



Việc kích hoạt CloudKit chỉ đơn giản bằng cách chọn checkbox có tên gọi CloudKit. Theo mặc định, ứng dụng của bạn sẽ sử dụng container mặc định cho ứng dụng của bạn. Khi bạn kích hoạt CloudKit thì container này tự động được sinh ra.
Nếu ứng dụng của bạn cần truy xuất vào container khác hoặc vào nhiều container, hãy chọn checkbox có tên gọi Specify custom containers và chọn những container mà ứng dụng của bạn yêu cầu truy xuất.



Bạn có thể đã nhận thấy rằng Xcode đã tự động liên kết mục tiêu của bạn với framework CloudKit. Có nghĩa là bạn đã sẵn sàng để bắt đầu sử dụng CloudKit trong ứng dụng của mình.
Bắt đầu thực hiện nào
Trong hướng dẫn tiếp theo của loạt bài, chúng tôi sẽ thêm các chức năng tạo mới, chỉnh sửa và xóa danh sách mua sắm. Tuy nhiên, để hoàn thành hướng dẫn này, tôi muốn cho bạn khởi động bằng cách chỉ cho bạn làm thế nào để tương tác với API CloudKit. Tất cả điều chúng ta sẽ làm là lấy bản ghi của người dùng đang đăng nhập hiện giờ.
Mở ViewController.swift và thêm một dòng import vào trên cùng để import CloudKit.
1 |
import UIKit |
2 |
import CloudKit |
Để lấy bản ghi từ người dùng, trước tiên chúng tôi cần tìm identifier của bản ghi. Hãy xem cách làm điều này. Tôi đã tạo một phương thức trợ giúp, fetchUserRecordID
, chứa logic để lấy identifier của bản ghi từ người dùng. Chúng ta gọi phương thức này qua phương thức viewDidLoad
của view controller.
1 |
override func viewDidLoad() { |
2 |
super.viewDidLoad() |
3 |
|
4 |
// Fetch User Record ID
|
5 |
fetchUserRecordID() |
6 |
}
|
Việc triển khai fetchUserRecordID
thú vị hơn viewDidLoad
một chút. Trước tiên ta lấy một tham chiếu đến container mặc định của ứng dụng thông qua kích hoạt defaultContainer
trên class CKContainer
. Sau đó chúng tôi gọi fetchUserRecordIDWithCompletionHandler(_:)
trong defaultContainer
. Phương thức này nhận một closure làm tham số duy nhất.
1 |
private func fetchUserRecordID() { |
2 |
// Fetch Default Container
|
3 |
let defaultContainer = CKContainer.default() |
4 |
|
5 |
// Fetch User Record
|
6 |
defaultContainer.fetchUserRecordID { (recordID, error) -> Void in |
7 |
if let responseError = error { |
8 |
print(responseError) |
9 |
|
10 |
} else if let userRecordID = recordID { |
11 |
DispatchQueue.main.sync { |
12 |
self.fetchUserRecord(recordID: userRecordID) |
13 |
}
|
14 |
}
|
15 |
}
|
16 |
}
|
Closure nhận 2 tham số: giá trị (không bắt buộc) CKRecordID
và giá trị (không bắt buộc) NSError
. Nếu error
là nil
, thì chúng ta an tâm mở recordID
.
Quan trọng cần nhấn mạnh rằng closure sẽ được gọi trong một luồng xử lý chạy nền. Có nghĩa là bạn cần cẩn thận khi cập nhật giao diện người dùng của ứng dụng từ bên trong một closure do CloudKit gọi. Ví dụ trong fetchUserRecordID
, tôi gọi fetchUserRecord(_:)
trong luồng xử lý chính.
Trong fetchUserRecord(_:)
, chúng ta gọi bản ghi của người dùng thông qua việc báo cho CloudKit biết bản ghi nào chúng ta đang quan tâm. Lưu ý rằng chúng ta gọi fetchRecordWithID(_:completionHandler:)
trong đối tượng privateDatabase
, một thuộc tính của đối tượng defaultContainer
.
Phương thức này nhận giá trị CKRecordID
và một handler. Tham số thứ hai nhận một giá trị CKRecord
(không bắt buộc) và một giá trị NSError
. Nếu chúng ta lấy bản ghi người dùng thành công, thì chúng ta xuất ra Console của Xcode.
1 |
private func fetchUserRecord(recordID: CKRecordID) { |
2 |
// Fetch Default Container
|
3 |
let defaultContainer = CKContainer.default() |
4 |
|
5 |
// Fetch Private Database
|
6 |
let privateDatabase = defaultContainer.privateCloudDatabase |
7 |
|
8 |
// Fetch User Record
|
9 |
privateDatabase.fetch(withRecordID: recordID) { (record, error) -> Void in |
10 |
if let responseError = error { |
11 |
print(responseError) |
12 |
|
13 |
} else if let userRecord = record { |
14 |
print(userRecord) |
15 |
}
|
16 |
}
|
17 |
}
|
Khi chúng ta chạy ứng dụng trong Xcode, bạn sẽ thấy trong console kết quả tương tự như vậy:



Bài viết này cho bạn hiểu sơ về CloudKit. API hiện thời của nó trực quan và dễ sử dụng. Trong hướng dẫn tiếp theo, chúng ta sẽ đào sâu hơn các khả năng của CloudKit API.
Bạn có thể lấy toàn bộ dự án mẫu tại Github (có thẻ #introduction
).
Tổng kết
Giờ bạn có hiểu biết đúng đắn những điều cơ bản của framework CloudKit. Phần còn lại của loạt bài sẽ tập trung vào phần xây dựng ứng dụng danh sách mua hàng. Trong hướng dẫn tiếp theo, chúng ta sẽ bắt đầu thêm khả năng tạo mới, điều chỉnh, và xoá các danh sách mua hàng.