Arez Wong Arez Wong - 1 month ago 10
Swift Question

Removing a CNContact array based on one of its key value

I am a swift newbie and trying to play around with the Contacts framework and have encountered a problem:-

I have an array of

CNContact
called contacts with keys of
givenName
,
familyName
and
phoneNumbers
.
I want to filter out certain names that is defined as type
String
from the array of contacts

I tried:

for name in namesToRemove { // 'name' is always in fullname format
contacts = contacts.filter () { $0.givenName + " " + $0.familyName != name }
}


but got an error of

Binary operator '!=' cannot be applied to operands of type 'CNContact' and 'String'


but the removal only works if both
givenName
and
familyName
are specified.

Also, keep in mind that on an iPhone device, some contacts' full name were only specified in either its 'First name' or 'Last name' column.

Any ideas how do I go about this? Much appreciated!

Answer

You could make use contains for the namesToRemove array as a conditional for a filter operation on contacts:

let filteredContacts = contacts.filter { !namesToRemove.contains($0.givenName) }

We first setup a CNContact example structure (since you have not supplied us with a minimal working example ...)

/* example setup */
struct CNContact {
    let givenName: String
    let familyName: String
    let phoneNumbers: [String]
    init(_ givenName: String, _ familyName: String, 
         _ phoneNumbers: [String]) { 
        self.givenName = givenName
        self.familyName = familyName
        self.phoneNumbers = phoneNumbers
    }
} 

let contacts = [CNContact("David", "Scott",   ["123-567", "010-111"]),
                CNContact("Lisa",  "Rowling", ["134-521", "121-731"]),
                CNContact("Brad",  "Knight",  ["621-141", "551-723"]),
                CNContact("David", "Phelps",  ["652-723", "718-888"]),
                CNContact("Sarah", "Bright",  ["166-720", "378-743"])]

Example usage:

/* example #1: 
   filter by removing any contacts that whose 'givenName' property
   are contained in a list of given surnames to remove 'namesToRemove' */
let namesToRemove1 = ["David", "Sarah"]
let filteredContacts1 = contacts.filter { !namesToRemove1.contains($0.givenName) }

filteredContacts1.forEach { 
    print($0.givenName, $0.familyName, $0.phoneNumbers.first ?? "none") 
} /* Lisa Rowling 134-521
     Brad Knight 621-141 */

/* example #2: 
   filter by removing any contacts that whose 'givenName' and 'familyName'
   properties are contained in a list of given full names to remove ('namesToRemove'), 
   where we know these full names are separated by exactly a single whitespace */
let namesToRemove2 = ["David Phelps", "Sarah Bright"]
let filteredContacts2 = contacts.filter { 
    !namesToRemove2.contains($0.givenName + " " + $0.familyName) }

filteredContacts2.forEach { 
    print($0.givenName, $0.familyName, $0.phoneNumbers.first ?? "none") 
} /* David Scott 123-567
     Lisa Rowling 134-521
     Brad Knight 621-141  */

Finally, an additional example based on the subsequent updates of your question:

/* example #3: 
   filter by removing any contacts where at least one of the following
   holds: 
   1. 'givenName' + " " + 'familyName' equals a name in 'namesToRemove',
   2. 'givenName' by itself equals a name in 'namesToRemove',
   3. 'familyName' by itself equals a name in 'namesToRemove', */

let contacts2 = [CNContact("David", "Scott",   ["123-567", "010-111"]),
                CNContact("Lisa",  "Rowling", ["134-521", "121-731"]),
                CNContact("",  "Brad Knight",  ["621-141", "551-723"]),
                CNContact("David Phelps", "",  ["652-723", "718-888"]),
                CNContact("Sarah", "Bright",  ["166-720", "378-743"])]
   print(" ")
let namesToRemove3 = ["David Phelps", "Sarah Bright", "Brad Knight"]
let filteredContacts3 = contacts2.filter { 
    !(namesToRemove3.contains($0.givenName + " " + $0.familyName) ||
      namesToRemove3.contains($0.givenName) ||
      namesToRemove3.contains($0.familyName)) }

filteredContacts3.forEach { 
    print($0.givenName, $0.familyName, $0.phoneNumbers.first ?? "none") 
} /* David Scott 123-567
     Lisa Rowling 134-521 */