CKQuery,如何从记录中获取所有字段?
CKQuery, how to fetch all Fields from Record?
我已经弄清楚如何搜索我的 CKrecord 并仅使用下面的代码显示一个字段中的字符串。
我有几个问题..(我是新手)
我可以搜索并且不区分大小写吗?
如何搜索记录中的所有字段,然后显示匹配的所有字段?
我正在制作一个参考应用程序,因此您可以搜索 BBC1 等所有与 BBC1 相关的内容(即在该 recordID 中)显示。
Dashboard.jpg showing Record and Fields
import UIKit
import CloudKit
import MobileCoreServices
class ViewController: UIViewController {
@IBOutlet var addressField: UITextField!
@IBOutlet var commentsField: UITextView!
let container = CKContainer.defaultContainer()
var publicDatabase: CKDatabase?
var currentRecord: CKRecord?
override func viewDidLoad() {
publicDatabase = container.publicCloudDatabase
super.viewDidLoad()
}
@IBAction func performQuery(sender: AnyObject) {
let predicate = NSPredicate(format: "serviceName = %@", addressField.text!)
let query = CKQuery(recordType: "SystemFields", predicate: predicate)
publicDatabase?.performQuery(query, inZoneWithID: nil, completionHandler: ({results, error in
if(error != nil) {
dispatch_async(dispatch_get_main_queue()) {
self.notifyUser("Cloud Access Error",
message: error!.localizedDescription)
}
} else {
if results!.count > 0 {
let record = results![0]
self.currentRecord = record
dispatch_async(dispatch_get_main_queue()) {
self.commentsField.text = record.objectForKey("Location") as! String
}
} else { dispatch_async(dispatch_get_main_queue()) {
self.notifyUser("No Match Found",
message: "No record matching the address was found")
}
}
}
}))
}
func notifyUser(title: String, message: String) -> Void
{
let alert = UIAlertController(title: title,
message: message,
preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "OK",
style: .Cancel, handler: nil)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true,
completion: nil)
}
}
根据 Apple 的 CKQuery Class Reference,您应该能够通过使用记录字段的标记化搜索来完成这两项工作:
To perform a tokenized search of a record’s fields, use the special operator self
. A tokenized search searches any fields that have full-text search enabled, which is all string-based fields by default. Each distinct word in the tokenized string is treated as a separate token for the purpose of searching. Comparisons are case- and diacritic-insensitive. These token strings may be found in a single field or in multiple fields.
下面是清单 5 示例(在 Swift 中):
Listing 5 - Matching a field containing one or more tokens
var predicate = NSPredicate(format: "self contains 'bob smith'")
以及清单 6 示例(在 Swift 中):
Listing 6 - Matching a field containing multiple tokens
var predicate = NSPredicate(format: "self contains 'bob' AND self contains 'smith'")
最后,查看有关 Indexes and Full-Text Search 的信息,因为您在 CloudKit 中的记录配置会影响搜索的字段(和性能)。
编辑:进一步说明您的用例:
由于您正在使用 addressField.text 的内容进行搜索...
您必须决定是否要匹配:
选项 1 -
addressField.text 中的任何 单个 词匹配记录中任何字段中的任何词。
在 Swift 2.2:
let predicate = NSPredicate(format: "self contains %@", addressField.text!)
选项 2 -
当 所有 个词在 addressField.text 中都在记录的一个字段中(尽管不一定按相同的顺序)。
在 Swift 2.2:
// creates a compound predicate to match all words in a string
// returns: nil if input was empty, otherwise an NSPredicate
func createPredicateForMatchingAllWordsIn(string: String) -> NSPredicate?
{
guard !string.isEmpty else { return nil }
var predicateList : [NSPredicate] = []
let words = string.componentsSeparatedByString(" ")
for word in words {
if !word.isEmpty {
predicateList.append(NSPredicate(format: "self contains %@", word))
}
}
return NSCompoundPredicate(andPredicateWithSubpredicates: predicateList)
}
let predicate = createPredicateForMatchingAllWordsIn(addressField.text!)
如果您想进行额外的过滤,例如仅显示单词匹配 顺序 的记录,您可以在客户端进行。 (CKQuery class 仅支持完整 NSPredicate class 提供的谓词行为的一个子集。)
我已经弄清楚如何搜索我的 CKrecord 并仅使用下面的代码显示一个字段中的字符串。
我有几个问题..(我是新手)
我可以搜索并且不区分大小写吗?
如何搜索记录中的所有字段,然后显示匹配的所有字段?
我正在制作一个参考应用程序,因此您可以搜索 BBC1 等所有与 BBC1 相关的内容(即在该 recordID 中)显示。
Dashboard.jpg showing Record and Fields
import UIKit
import CloudKit
import MobileCoreServices
class ViewController: UIViewController {
@IBOutlet var addressField: UITextField!
@IBOutlet var commentsField: UITextView!
let container = CKContainer.defaultContainer()
var publicDatabase: CKDatabase?
var currentRecord: CKRecord?
override func viewDidLoad() {
publicDatabase = container.publicCloudDatabase
super.viewDidLoad()
}
@IBAction func performQuery(sender: AnyObject) {
let predicate = NSPredicate(format: "serviceName = %@", addressField.text!)
let query = CKQuery(recordType: "SystemFields", predicate: predicate)
publicDatabase?.performQuery(query, inZoneWithID: nil, completionHandler: ({results, error in
if(error != nil) {
dispatch_async(dispatch_get_main_queue()) {
self.notifyUser("Cloud Access Error",
message: error!.localizedDescription)
}
} else {
if results!.count > 0 {
let record = results![0]
self.currentRecord = record
dispatch_async(dispatch_get_main_queue()) {
self.commentsField.text = record.objectForKey("Location") as! String
}
} else { dispatch_async(dispatch_get_main_queue()) {
self.notifyUser("No Match Found",
message: "No record matching the address was found")
}
}
}
}))
}
func notifyUser(title: String, message: String) -> Void
{
let alert = UIAlertController(title: title,
message: message,
preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "OK",
style: .Cancel, handler: nil)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true,
completion: nil)
}
}
根据 Apple 的 CKQuery Class Reference,您应该能够通过使用记录字段的标记化搜索来完成这两项工作:
To perform a tokenized search of a record’s fields, use the special operator
self
. A tokenized search searches any fields that have full-text search enabled, which is all string-based fields by default. Each distinct word in the tokenized string is treated as a separate token for the purpose of searching. Comparisons are case- and diacritic-insensitive. These token strings may be found in a single field or in multiple fields.
下面是清单 5 示例(在 Swift 中):
Listing 5 - Matching a field containing one or more tokens
var predicate = NSPredicate(format: "self contains 'bob smith'")
以及清单 6 示例(在 Swift 中):
Listing 6 - Matching a field containing multiple tokens
var predicate = NSPredicate(format: "self contains 'bob' AND self contains 'smith'")
最后,查看有关 Indexes and Full-Text Search 的信息,因为您在 CloudKit 中的记录配置会影响搜索的字段(和性能)。
编辑:进一步说明您的用例:
由于您正在使用 addressField.text 的内容进行搜索...
您必须决定是否要匹配:
选项 1 - addressField.text 中的任何 单个 词匹配记录中任何字段中的任何词。
在 Swift 2.2:
let predicate = NSPredicate(format: "self contains %@", addressField.text!)
选项 2 - 当 所有 个词在 addressField.text 中都在记录的一个字段中(尽管不一定按相同的顺序)。
在 Swift 2.2:
// creates a compound predicate to match all words in a string
// returns: nil if input was empty, otherwise an NSPredicate
func createPredicateForMatchingAllWordsIn(string: String) -> NSPredicate?
{
guard !string.isEmpty else { return nil }
var predicateList : [NSPredicate] = []
let words = string.componentsSeparatedByString(" ")
for word in words {
if !word.isEmpty {
predicateList.append(NSPredicate(format: "self contains %@", word))
}
}
return NSCompoundPredicate(andPredicateWithSubpredicates: predicateList)
}
let predicate = createPredicateForMatchingAllWordsIn(addressField.text!)
如果您想进行额外的过滤,例如仅显示单词匹配 顺序 的记录,您可以在客户端进行。 (CKQuery class 仅支持完整 NSPredicate class 提供的谓词行为的一个子集。)