Swift嵌套过滤器优化? [英] Swift nested filter optimization?

查看:152
本文介绍了Swift嵌套过滤器优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Swift中做一些使用KVC在Objective-C中容易实现的事情. iOS9中新增的 Contacts框架适用于比旧的地址簿API .但是,通过手机号码查找联系人似乎很困难.为查找联系人而提供的谓词仅限于名称和唯一标识符.在Objective-C中,您可以获得所有联系人,然后使用NSPredicate对KVC查询进行过滤.结构是:

I was trying to do something in Swift that would be easy in Objective-C using KVC. The new Contacts framework added in iOS9 is for the most part easier to use than the old AddressBook API. But finding a contact by its mobile phone number seems to be difficult. The predicates provided for finding contacts are limited to the name and the unique identifier. In Objective-C you could get all the contacts and then use an NSPredicate to filter on a KVC query. The structure is:

CNContact-> phoneNumbers->(字符串,CNPhoneNumber-> stringValue)

CNContact->phoneNumbers->(String, CNPhoneNumber->stringValue)

假设在下面的代码中我通过以下方式获取了联系人:

Presume in the code below that I fetched the contacts via:

let keys = [CNContactEmailAddressesKey,CNContactPhoneNumbersKey, CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)]
let fetchRequest = CNContactFetchRequest(keysToFetch: keys)
var contacts:[CNContact] = []
try! CNContactStore().enumerateContactsWithFetchRequest(fetchRequest) { ...

我想将stringValue与一个已知值进行比较.这是我到操场为止的东西:

I want to compare the stringValue to a known value. Here's what I have so far from a playground:

import UIKit
import Contacts

let JennysPhone    = "111-867-5309"
let SomeOtherPhone = "111-111-2222"
let AndAThirdPhone = "111-222-5309"

let contact1 = CNMutableContact()
contact1.givenName = "Jenny"
let phone1 = CNPhoneNumber(stringValue: JennysPhone)
let phoneLabeled1 = CNLabeledValue(label: CNLabelPhoneNumberMobile, value: phone1)
contact1.phoneNumbers.append(phoneLabeled1)

let contact2 = CNMutableContact()
contact2.givenName = "Billy"
let phone2 = CNPhoneNumber(stringValue: SomeOtherPhone)
let phoneLabeled2 = CNLabeledValue(label: CNLabelPhoneNumberMobile, value: phone2)
contact2.phoneNumbers.append(phoneLabeled2)

let contact3 = CNMutableContact()
contact3.givenName = "Jimmy"
let phone3 = CNPhoneNumber(stringValue: SomeOtherPhone)
let phoneLabeled3 = CNLabeledValue(label: CNLabelPhoneNumberMobile, value: phone3)
contact3.phoneNumbers.append(phoneLabeled3)

let contacts = [contact1, contact2, contact3]

let matches = contacts.filter { (contact) -> Bool in
    let phoneMatches = contact.phoneNumbers.filter({ (labeledValue) -> Bool in
        if let v = labeledValue.value as? CNPhoneNumber
        {
            return v.stringValue == JennysPhone
        }
        return false
    })
    return phoneMatches.count > 0
}

if let jennysNum = matches.first?.givenName
{
    print("I think I found Jenny:  \(jennysNum)")
}
else
{
    print("I could not find Jenny")
}

这确实有效,但是效率不高.在设备上,我需要在后台线程中运行它,如果该人有很多联系人,则可能需要一段时间.是否有更好的方法使用新的iOS联系人框架通过电话号码(或电子邮件地址,相同的想法)查找联系人?

This does work, but it's not efficient. On a device I would need to run this in a background thread, and it could take a while if the person has a lot of contacts. Is there a better way to find a contact by phone number (or email address, same idea) using the new iOS Contacts framework?

推荐答案

如果您正在寻找一种更快捷的方法:

If you are looking for a more Swift-y way to do it:

let matches = contacts.filter {
    return $0.phoneNumbers
                .flatMap { $0.value as? CNPhoneNumber }
                .contains { $0.stringValue == JennysPhone }
}

.flatMapphoneNumbers的每个成员从类型CNLabeledValue强制转换为CNPhoneNumber,而忽略那些不能强制转换的成员.

.flatMap casts each member of phoneNumbers from type CNLabeledValue to type CNPhoneNumber, ignoring those that cannot be casted.

.contains检查这些电话号码是否与Jenny的电话号码匹配.

.contains checks if any of these phone numbers matches Jenny's number.

这篇关于Swift嵌套过滤器优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆