保存在 userdefaults 中会使应用程序崩溃

Posted

技术标签:

【中文标题】保存在 userdefaults 中会使应用程序崩溃【英文标题】:save in userdefaults is crashing app 【发布时间】:2018-03-01 14:16:45 【问题描述】:

我是 swift 新手,尝试将数组保存到 userdefaults 中,但我的应用程序崩溃了。

我正在使用下面的代码

let currentObject = productsArray[clickedPosition] as Product
print("currentObject===\(currentObject)")
var currentCartArray = [Product]()
currentCartArray.append(currentObject)

UserDefaults.standard.set(currentCartArray, forKey: "Wafaa_MyCart")
UserDefaults.standard.synchronize()

下面是我得到的输出

currentObject===Product(Id: Optional(10007), TitleEN: Optional("PDF 1"), 
                TitleAR: Optional("PDF 1 AR"), DescriptionEN: nil, 
                DescriptionAR: nil, AboutEN: Optional("Merchant 1"), 
                AboutAR: Optional("Merchant 1"), CategoryId: Optional(1), 
                UnitSold: Optional(0), CategoryEN: Optional("Category 1"), 
                CategoryAR: Optional("الفئة الأولى"), CountryId: Optional(23), 
                CountryEN: Optional("Egypt"), CountryAR: Optional("مصر"), 
                CountryFlag: Optional("http://xxxx.xxxxx.info//Files/CountryPhotos/EG-128.png"),
                 MerchantId: Optional(1), MerchantNameEN: Optional("Merchant 1"), 
                MerchantNameAR: Optional("Merchant 1"), Logo: Optional(""), 
                CurrencyId: Optional(1), CurrencyCode: Optional(414), 
                CurrencyEN: Optional("Kuwaiti Dinar"), CurrencyAR: Optional("دينار كويتى"), 
                SymbolEN: Optional("KWD"), SymbolAR: Optional("KWD"), 
                Discount: Optional("0%"), 
                FinalPrice: Optional("1.000"), Price: Optional("1.000"), 
                OverViewAR: Optional("ddddddd"), OverViewEN: Optional("dddd"), 
                NoUsersRate: Optional(0), IsFavorite: Optional(false), 
                IsPurchased: Optional(false), 
                FavoriteIds: nil, Rate: Optional(3), 
                DemoVideo: Optional("http://player.vimeo.com/video/1111"), 
                VideoDuration: Optional("06:12:00"), ViewersCount: Optional(7), 
                Photo: Optional("http://xxxx.xxxx.info//Images/noimageicon.png"), 
                AddedOnDate: Optional("28/02/2018 01:43 PM"))

这个崩溃说下面的错误

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object (
"Wafaa.Product(Id: Optional(10007), TitleEN: Optional(\"PDF 1\"), 
    TitleAR: Optional(\"PDF 1 AR\"), DescriptionEN: nil, DescriptionAR: nil, 
    AboutEN: Optional(\"Merchant 1\"), AboutAR: Optional(\"Merchant 1\"), 
    CategoryId: Optional(1), UnitSold: Optional(0), CategoryEN: Optional(\"Category 1\"), 
    CategoryAR: Optional(\"\U0627\U0644\U0641\U0626\U0629 \U0627\U0644\U0623\U0648\U0644\U0649\"), 
    CountryId: Optional(23), CountryEN: Optional(\"Egypt\"), 
    CountryAR: Optional(\"\U0645\U0635\U0631\"), 
    CountryFlag: Optional(\"http://xxx.xxxx.info//Files/CountryPhotos/EG-128.png\"), 
    MerchantId: Optional(1), MerchantNameEN: Optional(\"Merchant 1\"), 
    MerchantNameAR: Optional(\"Merchant 1\"), Logo: Optional(\"\"), 
    CurrencyId: Optional(1), CurrencyCode: Optional(414), 
    CurrencyEN: Optional(\"Kuwaiti Dinar\"), 
    CurrencyAR: Optional(\"\U062f\U064a\U0646\U0627\U0631 \U0643\U0648\U064a\U062a\U0649\"), 
    SymbolEN: Optional(\"KWD\"), SymbolAR: Optional(\"KWD\"), 
    Discount: Optional(\"0%\"), FinalPrice: Optional(\"1.000\"), 
    Price: Optional(\"1.000\"), OverViewAR: Optional(\"ddddddd\"), 
    OverViewEN: Optional(\"dddd\"), NoUsersRate: Optional(0), 
    IsFavorite: Optional(false), IsPurchased: Optional(false), 
    FavoriteIds: nil, Rate: Optional(3), 
    DemoVideo: Optional(\"http://player.vimeo.com/video/xxxxx\"), VideoDuration: Optional(\"06:12:00\"), 
    ViewersCount: Optional(7), Photo: Optional(\"http://xxxx.xxxx.info//Images/noimageicon.png\"), 
    AddedOnDate: Optional(\"28/02/2018 01:43 PM\"))"

我记得,在 Objective-C 中,只有当我有 NULL 时它才会崩溃,但这里我没有任何 null,为什么还会发生崩溃?

知道我哪里出错了吗?

【问题讨论】:

"'尝试插入非属性列表对象"。我猜Product 无效。您还应该使 Product NSCoding 也兼容。 请不要使用.synchronize(),它不仅没用(软件已弃用)而且有时会导致问题。 为了澄清@Larme 所说的,用户默认值只能存储属性列表,这是一组有限的基础对象(基本上是数字、字符串、日期、数据和相同的集合)。如果您想在默认值中存储任何其他内容,则必须将它们转换为其中一种类型。见Property List Programming Guide 【参考方案1】:

在实际存储到UserDefaults 之前,您首先必须将对象序列化为Data 实例。幸运的是,Swift 4 提供了内置工具来轻松进行序列化和反序列化(Codable 协议)。

查看this tutorial,其中详细描述了所需的步骤。

【讨论】:

这对我有很大帮助并清楚地理解它为什么会失败......我也明白了为什么这在 Objective-C 中对我来说很好【参考方案2】:

Userdefaults 并不意味着像您尝试那样存储对象。它们用于存储数字、字符串、日期等。试试 Core Data 的对象类型。

【讨论】:

以上是关于保存在 userdefaults 中会使应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Swift - UserDefaults 设置未保存在框架内

userdefaults 不保存按钮状态

首次打开 App 时在 UserDefaults 中保存日期

将字典保存到 UserDefaults

UserDefaults 可以在每个 .synchronize() 之后继续保存新数据吗?

保存在userdefaults中是崩溃的应用程序