从字典键中提取值 - 然后组合成一个对象
Posted
技术标签:
【中文标题】从字典键中提取值 - 然后组合成一个对象【英文标题】:Extracting values from dictionary keys - then combining into an object 【发布时间】:2017-10-26 14:22:31 【问题描述】:我有一个 JSON 响应,我已在 Swift 中将其解析为单个字典集 [String:Any]。我正在尝试检查每个键的值,然后将该值作为变量添加到 SteamFriend 对象的创建中。
for (key, value) in level3
var avatar:URL!
var personaname:String = ""
var personastate:Int = 0
var steamid:String = ""
if key == "avatar"
if let avatarAsString = value as? String
let avatarAsURL = URL(string: avatarAsString)
avatar = avatarAsURL
else if key == "personaname"
if let personanameAsString = value as? String
personaname = personanameAsString
else if key == "personastate"
if let personastateAsInt = value as? Int
personastate = personastateAsInt
else if key == "steamid"
if let steamidAsString = value as? String
steamid = steamidAsString
let createSteamFriend = SteamFriend(avatar: avatar, personaname:
personaname, personastate: personastate, steamid: steamid)
SteamFriend 的类是
class SteamFriend
var avatar: URL
var personaname: String
var personastate: Int
var steamid: String
init (avatar:URL, personaname:String, personastate: Int, steamid:String)
self.avatar = avatar
self.personaname = personaname
self.personastate = personastate
self.steamid = steamid
当我运行上面的代码时,我立即在 createSteamFriend 行上收到一条错误消息,指出“在展开对象时意外发现 nil”。我已经针对上面的每个可选转换运行了一个打印语句,并且我知道它们都是返回值。
我确定我的代码逻辑存在缺陷。我一辈子都想不出创建 SteamFriend 对象的正确方法。
【问题讨论】:
在let createSteamFriend = SteamFriend(...)
行放一个断点并检查值。另外,我认为您想在 for 循环之外(之后)执行该行,并将 var 声明也放在外面(在 for 循环之前)。还有SteamFriend(avatar:personaname:personastate: steamid:)
的代码是什么?
@larme 我现在将更新答案以包含 SteamFriend 类。
【参考方案1】:
问题是您在每个循环中重新声明变量,因此 URL 为 nil
,除非在最后一次迭代中找到键 avatar
。
反正这是一种很麻烦的枚举字典的方式,直接获取key的值,不用循环:
var avatar: URL!
if let avatarAsString = level3["avatar"] as? String
let avatarAsURL = URL(string: avatarAsString)
avatar = avatarAsURL
let personaname = level3["personaname"] as? String ?? ""
let personastate = level3["personastate"] as? Int ?? 0
let steamid = level3["steamid"] as? String ? ""
let createSteamFriend = SteamFriend(avatar: avatar, personaname:
personaname, personastate: personastate, steamid: steamid)
如果初始化程序中的avatar
参数是必需的(非可选类型),我什至会写
guard let avatarAsString = level3["avatar"] as? String else
// show an error message
return
let avatar = URL(string: avatarAsString)!
【讨论】:
谢谢老兄,就是这样。我做了太多的 for 循环。在你提到这个之后我立即在level3上做了一个打印,发现最后一个for循环是不必要的。【参考方案2】:您正在为每个元素重置循环中的变量。 因此,一旦您找到“头像”,您就可以设置您的 URL。下一个元素,您将头像重置为 URL!。 把你的变量放在你的循环之外。
var avatar:URL!
var personaname:String = ""
var personastate:Int = 0
var steamid:String = ""
for (key, value) in level3
if key == "avatar"
if let avatarAsString = value as? String
let avatarAsURL = URL(string: avatarAsString)
avatar = avatarAsURL
else if key == "personaname"
if let personanameAsString = value as? String
personaname = personanameAsString
else if key == "personastate"
if let personastateAsInt = value as? Int
personastate = personastateAsInt
else if key == "steamid"
if let steamidAsString = value as? String
steamid = steamidAsString
let createSteamFriend = SteamFriend(avatar: avatar, personaname:
personaname, personastate: personastate, steamid: steamid)
【讨论】:
【参考方案3】:基本上,您的 avatar
为 nil,因为您正在创建 createSteamFriend
实例四次,并且值一次单独出现。
如果你得到一个字典,为什么要运行循环?尝试直接从字典中获取值不要使用循环和不必要的 if else 条件。
var avatar = URL()
if let avatarAsString = level3["avatar"] as? String
let avatarAsURL = URL(string: avatarAsString)
avatar = avatarAsURL
let personaname = level3["personaname"] as? String
let personastate = level3["personastate"] as? Int
let steamid = level3["steamid"] as? String
let createSteamFriend = SteamFriend(avatar: avatar, personaname:
personaname, personastate: personastate, steamid: steamid)
【讨论】:
以上是关于从字典键中提取值 - 然后组合成一个对象的主要内容,如果未能解决你的问题,请参考以下文章
具有 Unity 和 Firebase 数据库的字典数组 - 从键中获取值