ios – Fetch contacts by telephone quantity smart in Swift

0
27
ios – Fetch contacts by telephone quantity smart in Swift


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")

LEAVE A REPLY

Please enter your comment!
Please enter your name here