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:无法将“NSDate”类型的值转换为预期的参数类型“NSDateComponents”
Swift:无法将“UnsafeMutablePointer”类型的值转换为预期的参数类型“UnsafeMutablePointer”
Swift 2 到 Swift 3:无法将类型 '(Data?, NSError?) -> Void' 的值转换为预期的参数类型 'GTMSessionFetcherCompletionHand
“无法将类型 'String' 的值分配给类型 'AnyObject?'”,Swift 3,Xcode 8 beta 6