Search code examples
swiftgeneric-programmingcncontact

Unable to remove item from CNMutableContact in Generic Function


I want to allow a user to remove elements( eg CNPhoneNumber, CNEmailAddresses) from a contact after displaying the original contact and depending on what they choose I remove from my edited contact.

Even though I have a mutable contact and use mutable array from the key in my code the returned edited contact won't delete the element.

What am I doing wrong here?

Here is my generic function(Builds and runs fine except for issue listed above)

private func removeFromEditedContact<T:NSString>(labeledValueType:T, with key:String,from contact:CNContact,to toContact:CNContact, at indexPath:IndexPath) -> CNContact {

    let mutableContact = toContact.mutableCopy() as! CNMutableContact


    //what detail are we seraching for in the contact
    if let searchingArray = contact.mutableArrayValue(forKey: key) as? [CNLabeledValue<T>] {
        let searchValue = searchingArray[indexPath.row].value
        //if detail is present in our mutable contact remove it
        var labeledValueToChange = mutableContact.mutableArrayValue(forKey: key) as? [CNLabeledValue<T>]

        if let index = labeledValueToChange?.index(where: {$0.value == searchValue})  {
            labeledValueToChange?.remove(at: index)

        }
    }
    return mutableContact
}

Solution

  • The contact is not being modified because you are only removing the value from the mutable array you have created. You have to assign this value back to the contact after removing it from labeledValueToChange like so:

    contact.setValue(labeledValueToChange, forKey: key)
    

    Also if the original contact is the one you want to modify you can just pass it to the function directly as an inout parameter. I tried your function and it works like this:

    private func removeFromEditedContact<T:NSString>(labeledValueType:T, with key:String,from contact:inout CNMutableContact, at indexPath:IndexPath) -> CNMutableContact {
    
            //what detail are we seraching for in the contact
            if let searchingArray = contact.mutableArrayValue(forKey: key) as? [CNLabeledValue<T>] {
    
                let searchValue = searchingArray[indexPath.row].value
                //if detail is present in our mutable contact remove it
                var labeledValueToChange = contact.mutableArrayValue(forKey: key) as? [CNLabeledValue<T>]
    
                if let index = labeledValueToChange?.index(where: {$0.value == searchValue})  {
                    labeledValueToChange?.remove(at: index)
                }
    
    
                contact.setValue(labeledValueToChange, forKey: key)
            }
    
            return contact
        }