无法将自定义对象数组保存到 Swift 4 中的 UserDefault

Not able to save a custom object array save to UserDefault in Swift 4

我在 GoogleWhosebug 上搜索了大约 2 天,但没有成功。

我的自定义对象几乎是 CNContact 对象的复制品。

struct Contact: Codable {

let fullName, phones, emails: String
let imageDataAvailable, expanded: Bool
let thumbnailImageData, imageData: Data
let contactType: Int
let identifier: String
let namePrifix, givenName, middleName, familyName, previousFamilyName, nameSuffix, nickName, organizationName, departmentName, jobTitle, phoneticGivenName, phoneticMiddleName, phoneticFamilyName, phoneticOrganizationName, note: String
let birthday, nonGregorianBirthday: DateComponents
let dates: [ContactDate]
let postalAddresses: [PostalAddress]
let urlAddresses: [UrlAddress]
let contactRelations: [ContactRelation]
let socialProfiles: [SocialProfile]
let instantMessageAddresses: [InstantMessageAddress]
let phoneNumbers: [PhoneNumber]
let emailAddresses: [Email]
}

struct PostalAddress: Codable {
    let label, street, subLocality, city, subAdministativeArea, state, postalCode, country, isoCountryCode: String
}

struct UrlAddress: Codable {
    let label, value: String
}

struct ContactRelation: Codable {
    let label, name: String
}

struct SocialProfile: Codable {
    let label, urlString, userName, userIdentifier, service: String
}

struct PhoneNumber: Codable {
    let label, stringValue: String
}

struct Email: Codable {
    let label, value: String
}

struct InstantMessageAddress: Codable {
    let label, userName, service: String
}

struct ContactDate: Codable {
    let label: String
    let value: DateComponents
}

我尝试将 Contact 对象的数组保存到 UserDefault,但它总是给我同样的错误。

请帮我解决这个问题。

编辑 1

我尝试使用以下代码将数组转换为数据,但没有成功,我又遇到了另一个错误

代码

do {
        let contactJson = try JSONSerialization.data(withJSONObject: arrContact, options: .prettyPrinted)
        CommonFunctions.setUserDefaultValue(key: WSKey.contacts.rawValue, value: contactJson)
    } catch let parsingError {
        print("Error", parsingError)
    }


错误

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (_SwiftValue)'

我在日志中使用 debugDescription 命令的数组如下

"[Storedge.Contact(fullName: \"Kate Bell\", phones: \"(555) 564-8583\n(415) 555-3695\", emails: \"kate-bell@mac.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"177C371E-701D-42F8-A03B-C61CA31627F6\", namePrifix: \"\", givenName: \"Kate\", middleName: \"\", familyName: \"Bell\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"Creative Consulting\", departmentName: \"\", jobTitle: \"Producer\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: calendar: gregorian (fixed) year: 1978 month: 1 day: 20 isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [Storedge.PostalAddress(label: \"$!!$\", street: \"165 Davis Street\", subLocality: \"\", city: \"Hillsborough\", subAdministativeArea: \"\", state: \"CA\", postalCode: \"94010\", country: \"\", isoCountryCode: \"us\")], urlAddresses: [Storedge.UrlAddress(label: \"$!!$\", value: \"www.icloud.com\")], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"(555) 564-8583\"), Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"(415) 555-3695\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"kate-bell@mac.com\")]), Storedge.Contact(fullName: \"Daniel Higgins\", phones: \"555-478-7672\n(408) 555-5270\n(408) 555-3514\", emails: \"d-higgins@mac.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"AB211C5F-9EC9-429F-9466-B9382FF61035\", namePrifix: \"\", givenName: \"Daniel\", middleName: \"\", familyName: \"Higgins\", previousFamilyName: \"\", nameSuffix: \"Jr.\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"Sister: Emily\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [Storedge.PostalAddress(label: \"$!!$\", street: \"332 Laguna Street\", subLocality: \"\", city: \"Corte Madera\", subAdministativeArea: \"\", state: \"CA\", postalCode: \"94925\", country: \"USA\", isoCountryCode: \"us\")], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"555-478-7672\"), Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"(408) 555-5270\"), Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"(408) 555-3514\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"d-higgins@mac.com\")]), Storedge.Contact(fullName: \"John Appleseed\", phones: \"888-555-5512\n888-555-1212\", emails: \"John-Appleseed@mac.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"410FE041-5C4E-48DA-B4DE-04C15EA3DBAC\", namePrifix: \"\", givenName: \"John\", middleName: \"\", familyName: \"Appleseed\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"College roommate\", birthday: calendar: gregorian (fixed) year: 1980 month: 6 day: 22 isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [Storedge.PostalAddress(label: \"$!!$\", street: \"3494 Kuhl Avenue\", subLocality: \"\", city: \"Atlanta\", subAdministativeArea: \"\", state: \"GA\", postalCode: \"30303\", country: \"USA\", isoCountryCode: \"us\"), Storedge.PostalAddress(label: \"$!!$\", street: \"1234 Laurel Street\", subLocality: \"\", city: \"Atlanta\", subAdministativeArea: \"\", state: \"GA\", postalCode: \"30303\", country: \"USA\", isoCountryCode: \"us\")], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"888-555-5512\"), Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"888-555-1212\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"John-Appleseed@mac.com\")]), Storedge.Contact(fullName: \"Anna Haro\", phones: \"555-522-8243\", emails: \"anna-haro@mac.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"F57C8277-585D-4327-88A6-B5689FF69DFE\", namePrifix: \"\", givenName: \"Anna\", middleName: \"\", familyName: \"Haro\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"Annie\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: calendar: gregorian (fixed) year: 1985 month: 8 day: 29 isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [Storedge.ContactDate(label: \"$!!$\", value: calendar: gregorian (fixed) year: 2002 month: 2 day: 15 isLeapMonth: false ), Storedge.ContactDate(label: \"$!!$\", value: calendar: gregorian (fixed) year: 2002 month: 2 day: 15 isLeapMonth: false )], postalAddresses: [Storedge.PostalAddress(label: \"$!!$\", street: \"1001 Leavenworth Street\", subLocality: \"\", city: \"Sausalito\", subAdministativeArea: \"\", state: \"CA\", postalCode: \"94965\", country: \"USA\", isoCountryCode: \"us\")], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"555-522-8243\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"anna-haro@mac.com\")]), Storedge.Contact(fullName: \"Hank M. Zakroff\", phones: \"(555) 766-4823\n(707) 555-1854\", emails: \"hank-zakroff@mac.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"2E73EE73-C03F-4D5F-B1E8-44E85A70F170\", namePrifix: \"\", givenName: \"Hank\", middleName: \"M.\", familyName: \"Zakroff\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"Financial Services Inc.\", departmentName: \"\", jobTitle: \"Portfolio Manager\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [Storedge.PostalAddress(label: \"$!!$\", street: \"1741 Kearny Street\", subLocality: \"\", city: \"San Rafael\", subAdministativeArea: \"\", state: \"CA\", postalCode: \"94901\", country: \"\", isoCountryCode: \"us\")], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"(555) 766-4823\"), Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"(707) 555-1854\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"hank-zakroff@mac.com\")]), Storedge.Contact(fullName: \"David Taylor\", phones: \"555-610-6679\", emails: \"\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"E94CD15C-7964-4A9B-8AC4-10D7CFB791FD\", namePrifix: \"\", givenName: \"David\", middleName: \"\", familyName: \"Taylor\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"Plays on Cole\'s Little League Baseball Team\n\", birthday: calendar: gregorian (fixed) year: 1998 month: 6 day: 15 isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [Storedge.PostalAddress(label: \"$!!$\", street: \"1747 Steuart Street\", subLocality: \"\", city: \"Tiburon\", subAdministativeArea: \"\", state: \"CA\", postalCode: \"94920\", country: \"USA\", isoCountryCode: \"us\")], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"555-610-6679\")], emailAddresses: []), Storedge.Contact(fullName: \"mavya.soni@jayatma.com \", phones: \"\", emails: \"mavya.soni@jayatma.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"F01A8F75-B1E0-4B72-A017-6FDE693BE4E4\", namePrifix: \"\", givenName: \"mavya.soni@jayatma.com\", middleName: \"\", familyName: \"\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"mavya.soni@jayatma.com\")]), Storedge.Contact(fullName: \"Dimple Shah\", phones: \"\", emails: \"\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"4B0CE4C4-6569-4936-8C45-34A15725DF9D\", namePrifix: \"\", givenName: \"Dimple\", middleName: \"\", familyName: \"Shah\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [], emailAddresses: []), Storedge.Contact(fullName: \"yash.soni@jayatma.com \", phones: \"\", emails: \"yash.soni@jayatma.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"36C2E9A2-3955-49C7-BCED-02CDD1622E69\", namePrifix: \"\", givenName: \"yash.soni@jayatma.com\", middleName: \"\", familyName: \"\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"yash.soni@jayatma.com\")]), Storedge.Contact(fullName: \"Bhavesh Panchal\", phones: \"\", emails: \"Bhavesh.panchal@jayatma.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"564EB186-036C-437D-952D-A09A85A21027\", namePrifix: \"\", givenName: \"Bhavesh\", middleName: \"\", familyName: \"Panchal\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"Bhavesh.panchal@jayatma.com\")]), Storedge.Contact(fullName: \"Kayamuddin Ansari\", phones: \"7575801826\", emails: \"kayamuddin.ansari@jayatma.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"9D479A76-E092-4C9A-9BCC-418AB1DFC134\", namePrifix: \"\", givenName: \"Kayamuddin\", middleName: \"\", familyName: \"Ansari\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"7575801826\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"kayamuddin.ansari@jayatma.com\")]), Storedge.Contact(fullName: \"Manan Bhatt\", phones: \"7575801826\", emails: \"manan.bhatt@jayatma.com\", imageDataAvailable: false, expanded: false, thumbnailImageData: 0 bytes, imageData: 0 bytes, contactType: 0, identifier: \"0C1E052F-6636-4D47-979E-CFF2A66CF505\", namePrifix: \"\", givenName: \"Manan\", middleName: \"\", familyName: \"Bhatt\", previousFamilyName: \"\", nameSuffix: \"\", nickName: \"\", organizationName: \"\", departmentName: \"\", jobTitle: \"\", phoneticGivenName: \"\", phoneticMiddleName: \"\", phoneticFamilyName: \"\", phoneticOrganizationName: \"\", note: \"\", birthday: isLeapMonth: false , nonGregorianBirthday: isLeapMonth: false , dates: [], postalAddresses: [], urlAddresses: [], contactRelations: [], socialProfiles: [], instantMessageAddresses: [], phoneNumbers: [Storedge.PhoneNumber(label: \"$!!$\", stringValue: \"7575801826\")], emailAddresses: [Storedge.Email(label: \"$!!$\", value: \"manan.bhatt@jayatma.com\")])]"

由于您的联系人是可编码的,您可以利用 JSONEncoder/JSONDecoder 并执行以下操作:

if let json = try? JSONEncoder().encode(contact) {
    userDefs?.setValue(json, forKey: "contact");
    ...

并再次检索联系人:

 if let loaded = userDefs?.value(forKey: "contact") as? Data {
     let contact2 = try? JSONDecoder().decode(Contact.self, from: loaded)
      ...