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

Posted

技术标签:

【中文标题】Swift:无法将类型“[String:DayData]”的值转换为预期的参数类型“AnyObject?”【英文标题】:Swift: Cannot convert value of type '[String : DayData]' to expected argument type 'AnyObject?' 【发布时间】:2016-08-19 06:15:16 【问题描述】:

我在尝试保存我创建的新结构时无法保存到 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

但这只会让应用崩溃。

【问题讨论】:

您需要使用符合 NSCoding 的类而不是结构,并使用 NSKeyedArchiver 将对象转换为 NSData 以将其保存到 NSUserDefaults 或 plist 文件中 除上述之外,您应该调用setObject:forKey: 而不是setValue:forKey:。 (AnyObject 是“所有类隐式遵循的协议”——结构体等值类型不是类。) @LeoDabus 我一个字都听不懂。但这似乎是合法的...... ***.com/a/32420488/2303865 【参考方案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

【讨论】:

说到 Swift,我还是个菜鸟。我应该把这些元素放在哪里?谢谢! 将扩展名放在文件顶层的某处(不是在类或结构中)。然后你可以从任何地方访问它。 当我用“NSUserDefaults.stand ...”替换我的原始行时,它仍然给我一个错误“无法将类型'[String:DayData]'的值转换为预期的参数类型'DayData ’。”有什么建议吗? 您正在将字典 [String : DayData] 保存为用户默认值。我更新了答案以考虑这种类型。 我在启动应用程序时仍然收到 BAD_EXC 错误。它在 viewDidLoad 中的这段代码上: var allInfoByDateDefault = NSUserDefaults.standardUserDefaults() if (allInfoByDateDefault.valueForKey("allInfoByDateRecord") != nil) allInformationByDate = (allInfoByDateDefault.valueForKey("allInfoByDateRecord") as? [String: DayData ])!问题在于最后一部分。但我不确定如何更改语法。【参考方案2】:

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

文档:

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

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

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

你可以搜索教你如何遵守NSCoding的教程,但我真的不推荐使用它。

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

看到你有这样的结构,我建议你使用 Core Data 而不是NSUserDefaults。您可以创建一个数据模型,并根据该结构生成一个NSManagedObject 子类:

class DayData: NSManagedObject 
    @NSManaged var sales: NSNumber?
    @NSManaged var doorsKnocked: NSNumber?
    @NSManaged var milesWalked: NSNumber?
    @NSManaged var hoursWorked: NSNumber?

相信我,Core Data 在这种情况下要方便得多。

详情请看this tutorial。

【讨论】:

以上是关于Swift:无法将类型“[String:DayData]”的值转换为预期的参数类型“AnyObject?”的主要内容,如果未能解决你的问题,请参考以下文章

Swift 无法将类型“()”的值分配给类型“字符串?”

Swift:无法将“NSDate”类型的值转换为预期的参数类型“NSDateComponents”

Swift:无法将“UnsafeMutablePointer”类型的值转换为预期的参数类型“UnsafeMutablePointer”

Swift 2 到 Swift 3:无法将类型 '(Data?, NSError?) -> Void' 的值转换为预期的参数类型 'GTMSessionFetcherCompletionHand

“无法将类型 'String' 的值分配给类型 'AnyObject?'”,Swift 3,Xcode 8 beta 6

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