[Swift][iOS9] Sử dụng AppSearch để làm 1 ứng dụng từ điển đơn giản
This post hasn't been updated for 3 years
Mở đầu
Chắc hẳn mỗi người dùng iPhone đều không xa lạ gì với Spotlight. Chúng ta có thể sử dụng nó để tìm app, tìm contact của 1 người nào đó, hay thậm chí là tìm các thông tin trên internet một cách nhanh chóng. Thay vì phải thực hiện nhiều thao tác chúng ta chỉ cần trượt màn hình xuống, điền thông tin cần tìm kiếm vào là xong.
Hãy thử tưởng tượng, khi bạn học thêm 1 ngôn ngữ mới, để tra nghĩa của từ, thay vì vào app từ điển (đôi khi tôi còn chẳng nhớ nó nằm ở đâu nữa) và thực hiện các thao tác search, chúng ta có thể search ngay trên Spotlight. Điều đó thật là tiện lợi, nhưng nó ĐÃ TỪNG là bất khả thi vì Spotlight không cho phép chúng ta can thiệp sâu như vậy vào trong ứng dụng.
Khi giới thiệu iOS 9, Apple đã cho phép bên thứ ba có thể tạo các nội dung có thể search được trên Spotlight thông qua App search APIs. Và điều bất khả thi ở trên đã dần trở thành hiện thực. Với bài viết này, tôi sẽ hướng dẫn các bạn tìm hiểu qua về App search APIs thông qua 1 ứng dụng từ điển tiếng Nhật đơn giản. Let's begin
App search APIs
Trước khi bắt tay vào làm app, chúng ta sẽ tìm hiểu qua về App search APIs. App search trên iOS 9 bao gổm 3 phần chính. Mỗi phần thực hiện 1 nhiệm vụ riêng biệt, nhưng nó cũng có thể phối hợp cùng các phần khác. 3 phần đó bao gồm :
1. NSUserActivity
Trên iOS9, NSUserActivity (vốn đã có mặt từ iOS 8 để thực hiện chức năng Handoff) đã được bổ sung thêm một vài property mới để thực hiện chức năng search.
Theo lý thuyết, nếu 1 task có thể được represent như một NSUserActivity để được handoff sang 1 device khác, thì nó cũng có thể được tiếp tục "handoff" trên chính device này. Điều này có nghĩa là chúng ta có thể index activities, states và navigation points trong ứng dụng, sau đó "handoff" nó cho Spotlight, hay như chúng ta vẫn nói thì là search trên Spotlight
2. Core Spotlight
Được giới thiệu trên iOS9, đây có lẽ là phần quy chuẩn nhất trong App Search. Đơn giản là bạn không thể custom nó theo ý muốn, mà chỉ có thể thay đổi code để phù hợp với những tiêu chuẩn có sẵn của Apple. Tuy nhiên nó lại có 1 sức mạnh to lớn mà có thể cho phép người dùng có thể search nội dung bên trong ứng dụng ngay trên spotlight, đúng như tên gọi của nó Core Spotlight
Và Core Spotlight chính là chìa khóa giúp chúng ta thực hiện điều mong muốn trên. Đơn giản bạn chỉ cần index dữ liệu, việc còn lại cứ để Core Spotlight lo.
3. Web markup
Phần cuối cùng của AppSearch chính là Web markup. Công việc của Web markup chỉ đơn giản là giúp bạn có thể search được nội dung website của bạn ngay trên Spotlight. Thật là "đơn giản" nên trong phạm vi bài này, tôi sẽ k đề cập đến Web markup.
Start
Cuối cùng cũng đọc xong cái phần lý thuyết dài ngoẵng, thôi cứ thực hành cho nó nhớ lâu chứ nói suông 1 lúc lại quên mất. Cùng thực hiện cái ứng dụng ở phần mở đầu thôi.
1. Chuẩn bị
Chúng ta sẽ chuẩn bị 1 ứng dụng đơn giản, hiển thị các từ tiếng Nhật có trong file JSON
[
{
"furigana": "わたし",
"kanji": "私",
"romanji": "watashi",
"vietnamese": "Tôi",
"favourite": 0,
"vocabularyID" : "1"
},
{
"furigana": "わたしたち",
"kanji": "私達",
"romanji": "watashitachi",
"vietnamese": "Chúng ta",
"favourite": 0,
"vocabularyID" : "2"
},
{
"furigana": "あなた",
"kanji": "貴方",
"romanji": "anata",
"vietnamese": "Bạn (ngôi thứ 2)",
"favourite": 0,
"vocabularyID" : "3"
},
{
"furigana": "ともだち",
"kanji": "友達",
"romanji": "tomodachi",
"vietnamese": "Bạn bè",
"favourite": 0,
"vocabularyID" : "4"
},
{
"furigana": "じしょ",
"kanji": "辞書",
"romanji": "jisho",
"vietnamese": "Từ điển",
"favourite": 0,
"vocabularyID" : "5"
}
]
Vì mục đích của chúng ta là có thể search được nó ở trên Spotlight, nên bạn có thể sử dụng luôn code ở trong thư mục Startsource để thực hiện.
2. Index dữ liệu
Để dữ liệu có thể được search thông qua Spotlight, chúng ta phải thực hiện việc index dữ liệu với CSSearchableIndex. Do đó, việc quan trọng nhất và cũng là việc mà bạn phải thực hiện đầu tiên là
import CoreSpotlight
Sử dụng hàm có sẵn trong CoreSpotlight để thực hiện việc index, việc gọi hàm index ở đâu sẽ tùy thuộc vào yêu cầu của ứng dụng, ở đây, tôi sẽ gọi luôn nó ở AppDelegate
let searchableItems : [CSSearchableItem] = // TODO:
CSSearchableIndex.defaultSearchableIndex().indexSearchableItems(searchableItems) { error in
if let error = error {
print("Error = \(error)")
}
}
Câu lệnh trên chỉ thiếu duy nhất 1 biến là 1 array chứa các CSSearchableItem
. Như vậy, với mỗi 1 Vocabulary
đã có, chúng ta sẽ phải tạo ra 1 CSSearchableItem
tương ứng.
import CoreSpotlight
import MobileCoreServices
extension Vocabulary {
static let domainIdentifier = "com.quocnb.appsearchdemo.vocabulary"
var attributeSet: CSSearchableItemAttributeSet {
let attributeSet = CSSearchableItemAttributeSet(
itemContentType: kUTTypeMessage as String)
attributeSet.title = self.kanji
attributeSet.contentDescription = "\(self.furigana)\n\(self.vietnamese)"
return attributeSet
}
var searchableItem: CSSearchableItem {
let item = CSSearchableItem(uniqueIdentifier: self.vocabularyID,
domainIdentifier: Vocabulary.domainIdentifier,
attributeSet: attributeSet)
return item
}
}
Quá đơn giản, bây giờ bạn chỉ cần run app và tận hưởng kết quả thôi
Với kết quả ở trên, rõ ràng bạn có thể thấy chúng ta có thể search được kết quả không chỉ ở title (Kanji) mà còn có thể search được cả kết quả từ description của nó (Furigana + Vietnamese)
3. Xử lý action khi bấm vào kết quả trên Spotlight
OK, với các bước đơn giản trên, chúng ta đã có thể search được kết quả trong app ở ngay trên spotlight. Khi bấm vào kết quả trên spotlight, ứng dụng của chúng ta sẽ được tự động mở ra. Tuy nhiên, nếu nó nhảy thẳng vào phần detail thì sẽ ứng dụng sẽ ngon hơn nhiều
Nhớ lại 1 chút phần lý thuyết ở trên nào, Core Spotlight
không cho phép chúng ta custom nhiều, trong đó có việc handle action xem khi bấm vào kết quả search trên Spotlight. Tuy nhiên, trong App Search ngoài Core Spotlight
còn có NSUserActivity
, thứ sẽ giúp chúng ta thực hiện việc còn thiếu
Trong AppDelegate đã có sẵn function hỗ trợ việc bắt action của NSUserActivity, overwrite nó
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
guard userActivity.activityType == CSSearchableItemActionType,
let uniqueIdentifier = userActivity.userInfo? [CSSearchableItemActivityIdentifier] as? String else {
return false
}
guard let nav = self.window?.rootViewController as? UINavigationController,
listVC = nav.viewControllers.first as? VocabularyListTableViewController,
let vocabulary = VocabularyService().vocabularyWithID(uniqueIdentifier) else {
return false
}
nav.popToRootViewControllerAnimated(false)
let vocabularyDetailVC = listVC.storyboard?.instantiateViewControllerWithIdentifier("VocabularyDetailViewController") as! VocabularyDetailViewController
vocabularyDetailVC.vocabulary = vocabulary
nav.pushViewController(vocabularyDetailVC, animated: true)
return true
}
Check nếu Activity được gửi từ Spotlight và xử lý nó theo yêu cầu của ứng dụng, hiển thị từ tiếng Nhật đã được chọn trên Spotlight. Thế là xong
Kết
Qua ví dụ nhỏ trên, tôi đã hướng dẫn các bạn tìm hiểu qua về App search APIs. Tuy App search APIs chỉ hỗ trợ trên iOS 9 trở đi nhưng hi vọng nó sẽ có ích trong các ứng dụng mà bạn sắp thực hiện. Nếu bạn cần demo, nó ở ngay đây, feel free to using it
All Rights Reserved