Roei Nadam
Roei Nadam

Reputation: 1780

Crash when unarchived data to CNContact

Hello I have a crash when unarchived data to CNContact :

in line : var decodedContacts = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [CNContact.self], from: archived) as? [CNContact?]

the error log :

NSKeyedUnarchiver.unarchivedObject(ofClasses: [CNContact.self], from: contactsData) as? [CNContact?] Error Domain=NSCocoaErrorDomain Code=4864 "value for key 'root' was of unexpected class 'NSArray' (0x1d97a9ed8) [/System/Library/Frameworks/CoreFoundation.framework]. Allowed classes are: {( "'CNContact' (0x1d9881018) [/System/Library/Frameworks/Contacts.framework]" )}" UserInfo={NSDebugDescription=value for key 'root' was of unexpected class Allowed classes are: {( "'CNContact' (0x1d9881018) [/System/Library/Frameworks/Contacts.framework]" )}}

import Contacts

class ContactsManager {

static let numberOfSavedContacts = 12

static let shared = ContactsManager()
private init() {
    loadContacts()
}

private(set) var contacts: [CNContact?] = Array(repeating: nil, count: numberOfSavedContacts)

func add(contact: CNContact, at index: Int, phone: CNLabeledValue<CNPhoneNumber>? = nil) {
    if index < ContactsManager.numberOfSavedContacts {
        let editContact = contact.mutableCopy() as! CNMutableContact
        if phone != nil {
            editContact.phoneNumbers = [phone!]
        }
        contacts[index] = editContact
        saveContacts()
    }
}

func deleteContact(_ index: Int) {
    if index < ContactsManager.numberOfSavedContacts {
        contacts[index] = nil
        saveContacts()
    }
}

func saveContacts() {
    do {
        let contactsData = try NSKeyedArchiver.archivedData(withRootObject:contacts,requiringSecureCoding:false)
        UserDefaults.standard.set(contactsData, forKey: "contacts")
    }
    catch {
        print(error)
    }
}


func loadContacts() {
    if let contactsData = UserDefaults.standard.object(forKey: "contacts") as? Data {
        do {
            if var decodedContacts = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, CNContact.self, NSNull.self], from: contactsData) as? [CNContact?] {
                print(decodedContacts)
                contacts = decodedContacts
            } else {
                print("decodedContacts is nil")
            }
        } catch {
            print(error)
        }
    }
}

}

Upvotes: 0

Views: 93

Answers (1)

Larme
Larme

Reputation: 26096

NSKeyedUnarchiver is the "old way" of archiving objects. It's Objective-C oriented.

Seeing the error: was of unexpected class 'NSArray'

Then, you need to specify you'll encounter NSArray objects when decoding:

ofClasses: [NSArray.self, CNContact.self]

Now, you get another error: was of unexpected class 'NSNull'". NSNull ~ nil.

You are saving nil contacts with Array(repeating: nil, count: numberOfSavedContacts).

So you need to tell the unarchiver that you might encounter nil values:

ofClasses: [NSArray.self, NSNull.self, CNContact.self]

I don't know why you save nil value, that's strange though, you might want to change that behavior.

Upvotes: 0

Related Questions