Swift:无法将'[String:DayData]'类型的值转换为预期的参数类型'AnyObject?'

时间:2016-08-19 06:15:16

标签: swift

在尝试保存我创建的新结构时,我无法保存到CoreData。

var allInformationByDate = [
"2016-08-13": DayData(sales: 0, doorsKnocked: 0, milesWalked: 0.00, hoursWorked: 0.00)

]

struct DayData { 
let sales: Int
let doorsKnocked: Int
let milesWalked: Double
let hoursWorked: Double
}

我收到了错误:

  

无法将'[String:DayData]'类型的值转换为预期的参数类型'AnyObject?'

在这段代码上,特别是“allInformationByDate”......

var allInfoByDateDefault = NSUserDefaults.standardUserDefaults()
    allInfoByDateDefault.setValue(allInformationByDate, forKey:"allInfoByDateRecord")
    allInfoByDateDefault.synchronize()

有人知道如何修复这种语法吗?我已经尝试过改为

allInformationByDate as! AnyObject

但这只是让应用程序崩溃。

2 个答案:

答案 0 :(得分:1)

问题是您无法在NSUserDefaults

中保存自定义对象

但由于DayData的所有属性都符合属性列表,因此您可以编写NSUserDefaults的扩展名以将DayData转换为字典,反之亦然。

此扩展程序可以编写单个DayData对象以及字典[String:DayData]

extension NSUserDefaults {

 // read a write a single 'DayData' object

  func dayDataForKey(key: String) -> DayData? {
    guard let data = self.objectForKey(key) as? [String:AnyObject] else { return nil }
    return DayData(sales: data["sales"] as! Int, doorsKnocked: data["doorsKnocked"] as! Int, milesWalked: data["milesWalked"] as! Double, hoursWorked: data["hoursWorked"] as! Double)
  }

  func setDayData(dayData : DayData, forKey key: String) {
    let propertyListRepresentation  = ["sales": dayData.sales, "doorsKnocked" : dayData.doorsKnocked, "milesWalked": dayData.milesWalked, "hoursWorked": dayData.hoursWorked]
    self.setObject(propertyListRepresentation, forKey: key)
  }

  // read a write a dictionary ('[String:DayData]') object

  func dayDataDictionaryForKey(key: String) -> [String: DayData]? {
    guard let dayData = self.objectForKey(key) as? [String : [String: AnyObject]] else { return nil }
    var result = [String: DayData]()
    for (key, value) in dayData {
      result[key] = DayData(sales: value["sales"] as! Int, doorsKnocked: value["doorsKnocked"] as! Int, milesWalked: value["milesWalked"] as! Double, hoursWorked: value["hoursWorked"] as! Double)
    }
    return result
  }

  func setDayDataDictionary(dayData : [String: DayData], forKey key: String) {
    var result = [String : [String: AnyObject]]()
    for (key, value) in dayData {
      result[key] = ["sales": value.sales, "doorsKnocked" : value.doorsKnocked, "milesWalked": value.milesWalked, "hoursWorked": value.hoursWorked]
    }
    self.setObject(result, forKey: key)
  }
}

现在您可以轻松地将字典写入用户默认值:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setDayDataDictionary(allInformationByDate, forKey: "allInfoByDateRecord")

或阅读

let defaults = NSUserDefaults.standardUserDefaults()
if let infoByDateDefault = defaults.dayDataDictionaryForKey("allInfoByDateRecord") {
   allInformationByDate = infoByDateDefault
}

答案 1 :(得分:0)

您不应使用setValue方法。要设置字典,请调用setObject方法。

文档:

  

在标准应用程序域中设置指定默认密钥的值。

     

value参数只能是属性列表对象:NSData,NSString,NSNumber,NSDate,NSArray或NSDictionary。对于NSArray和NSDictionary对象......

此外,使用带有Objective-C API的Swift结构非常非常不方便。您需要使结构符合NSCoding并将其转换为NSData,然后再将其存储到NSUserDefaults。这基本上是一团糟。

您可以搜索向您展示如何符合NSCoding的教程,但我不建议您使用它。

NSUserDefaults通常用于保存简单的数据结构,如整数,浮点数,bool。这是因为,毕竟它是专为您设计的,以保存用户偏好和相关内容。

看到你有这样的结构,我建议你使用Core Data而不是NSUserDefaults。您可以创建数据模型并基于struct:

生成NSManagedObject子类
class DayData: NSManagedObject {
    @NSManaged var sales: NSNumber?
    @NSManaged var doorsKnocked: NSNumber?
    @NSManaged var milesWalked: NSNumber?
    @NSManaged var hoursWorked: NSNumber?
}

相信我,在这种情况下,核心数据更方便。

有关详细信息,请查看this tutorial