Predicates are for filtering the fetched CNContact
objects, to restrict the outcomes to people who match some standards. For instance, you would possibly use a predicate to fetch solely contacts with telephone numbers:
request.predicate = NSPredicate(format: "phoneNumbers.@rely > 0")
But it surely received’t “break up” a single CNContact
into a number of entries, one for every telephone quantity. It’s a must to do this your self. You need to use the sample that Joakim outlined (+1). Or, personally, I would use a flatMap
technique that takes an array of return values and builds an array from that:
extension CNContactStore {
/// Flat map
///
/// - Parameters:
/// - request: The `CNContactFetchRequest`.
/// - rework: A closure that returns an array of values to be appended to the ultimate outcomes.
/// - Returns: A flat array of all the outcomes.
func flatMap(request: CNContactFetchRequest, _ rework: (CNContact, UnsafeMutablePointer) -> [T]) throws -> [T] {
var outcomes: [T] = []
strive enumerateContacts(with: request) { contact, cease in
outcomes += rework(contact, cease)
}
return outcomes
}
/// Map
///
/// - Parameters:
/// - request: The `CNContactFetchRequest`.
/// - rework: A closure that returns a price to be appended to the ultimate outcomes.
/// - Returns: A flat array of all the outcomes.
func map(request: CNContactFetchRequest, _ rework: (CNContact, UnsafeMutablePointer) -> T) throws -> [T] {
var outcomes: [T] = []
strive enumerateContacts(with: request) { contact, cease in
outcomes.append(rework(contact, cease))
}
return outcomes
}
}
That’s each a flatMap
(to your use-case the place you might wish to return a number of objects for a given CNContact
), in addition to a extra conventional map
rendition (not used right here, however is my typical use-case).
Anyway, you possibly can then use it like so:
let keys = [
CNContactPhoneNumbersKey as CNKeyDescriptor,
CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
]
let request = CNContactFetchRequest(keysToFetch: keys)
request.predicate = NSPredicate(format: "phoneNumbers.@rely > 0")
request.sortOrder = .userDefault
let formatter = CNContactFormatter()
formatter.fashion = .fullName
do {
let outcomes = strive retailer.flatMap(request: request) { contact, _ in
contact.phoneNumbers.compactMap { telephone -> Contact? in
guard let identify = formatter.string(from: contact) else { return nil }
return Contact(fullName: identify, phoneNumber: telephone.worth.stringValue)
}
}
…
} catch {
print("Did not fetch contacts with telephone numbers:", error)
}
That returned:
Contact(fullName: "John Appleseed", phoneNumber: "888-555-5512")
Contact(fullName: "John Appleseed", phoneNumber: "888-555-1212")
Contact(fullName: "Kate Bell", phoneNumber: "(555) 564-8583")
Contact(fullName: "Kate Bell", phoneNumber: "(415) 555-3695")