1

I'm not sure if this belongs in Stack Overflow, if it doesn't please let me know.

I have this piece of code that adds contacts to an array, if a contact with that phone/name combination already exists in the array it does not add it again (meaning no duplicates).

It works as intended but it increases build times dramatically and I am looking for a better way to use contains or some other approach.

var contacts = [CNContact]()

let name: String = contact.givenName + " " + contact.middleName + " " + contact.familyName

if (name.stringByReplacingOccurrencesOfString(" ", withString: "")).length > 1
{
    if contact.phoneNumbers.count > 0 
    {
        // Check if contacts already contains name/phone combination
        if let phoneNumber: String = (contact.phoneNumbers[0].value as? CNPhoneNumber)?.stringValue
        {
            if contacts.contains({$0.phoneNumbers.count > 0 && ($0.phoneNumbers[0].value as? CNPhoneNumber)?.stringValue == phoneNumber}) &&
                 contacts.contains({($0.givenName + " " + $0.middleName + " " + $0.familyName) == name})
            { /* Contact with same name/phone combination already exists in array */ }
            else { contacts.append(contact) }
        }
    }
}
ohr
  • 1,717
  • 14
  • 15

1 Answers1

2

Chained + is the most common cause of slow build times in my experience. When people complain about build times, I always ask "you've got chained +, don't you." Have been right about 90%. For example:

let name: String = contact.givenName + " " + contact.middleName + " " + contact.familyName

and also

contacts.contains({($0.givenName + " " + $0.middleName + " " + $0.familyName) == name})

Use interpolation rather than chained +:

"\(contact.givenName) \(contact.middleName) \(contact.familyName)"

Or join an array:

[contact.givenName, contact.middleName, contact.familyName].joined(separator: " ")

In this particular case, I'd almost certainly make a helper though:

extension Contact {
    var fullName: String {
        return "\(contact.givenName) \(contact.middleName) \(contact.familyName)"
    }
}

Then much of the rest of your code would get simpler.

The problem with chained + is that it has many overloads, and so the compiler has to do a combinatorially explosive search of all the different versions of + it might use here.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks that did drop build times to about 1/3. Knowing this, would you ever use '+' to chain strings? – ohr Nov 11 '16 at 22:01
  • I never use `+` to combine strings. Not only is there a compile time cost, but it's inefficient, since it has to create intermediate objects. – Rob Napier Nov 11 '16 at 23:24