将 NSDictionary 与内部函数解码为 swift 对象的值
Posted
技术标签:
【中文标题】将 NSDictionary 与内部函数解码为 swift 对象的值【英文标题】:Decode NSDictionary with functions inside as values to swift object 【发布时间】:2020-11-23 07:08:40 【问题描述】:任何意见或建议将不胜感激!谢谢!
我有一个问题要解决,但似乎在任何地方都找不到答案。一些背景:我们正在更新我们的 ios 应用程序,生产版本是用 obj-c 编写的,但是我们用 Swift 开发了新的 UI 功能。因此,我们有一个字典,其中包含一些用于 Swift 开发方面的值,其中包含许多重要的 UI 数据。至于现在,我们只是循环 dict 来获取值。我想将其转换为 swift 对象,因此更容易访问所需的值。问题是字典包含函数调用和 UIImage 类型的值。将这个字典解析为 swift 对象的最聪明的方法是什么?字典:
let dict : [String: Any] = [
"keySelectedMenuButton" : 0,
"keySettButtCallback" : settTapCallback,
"keyInfoButtCallback" : logoTapCallback,
"keyObjectMenuCallback": menuButtonTapCallback,
"buttonListChanged" : doneEditTapCallback,
"keyObjectArray" : [
["keyObjectTitle" : "Home",
// "keyObjectLineImage": UIImage(named: "objektu atskyrimas_4x")!,
"keyObjCtrlButtCollectionArray" : [
["keyCtrlItemTitle" : "Smart Menu",
"keyCtrlItemSubtitle" : "",
//"keyCtrlItemImage" : UIImage(named: "ico_rocket")!,
"keyCtrlObjectAfterTap" : buttonTap1Callback
],
["keyCtrlItemTitle" : "Lock",
"keyCtrlItemSubtitle" : "doors",
//"keyCtrlItemImage" : UIImage(named: "ico_lock_1@x3")!,
"keyCtrlObjectAfterTap" : buttonTapCallback
],
["keyCtrlItemTitle" : "Unlock",
"keyCtrlItemSubtitle" : "Gates",
// "keyCtrlItemImage" : UIImage(named: "ico_lock_0@x3")!,
"keyCtrlObjectAfterTap" : buttonTapCallback
],
["keyCtrlItemTitle" : "Ignore",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_shield@x3")!,
"keyCtrlObjectAfterTap" : buttonTap1Callback
],
["keyCtrlItemTitle" : "Stop",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_stop")!
"keyCtrlObjectAfterTap" : buttonTap2Callback
],
["keyCtrlItemTitle" : "State",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_query@x3")!,
"keyCtrlObjectAfterTap" : buttonTap3Callback
],
["keyCtrlItemTitle" : "Controller",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_settings_lines")!,
"keyCtrlObjectAfterTap" : buttonTap1Callback
],
["keyCtrlItemTitle" : "Logs",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_log@x3")!,
"keyCtrlObjectAfterTap" : buttonTap2Callback
],
["keyCtrlItemTitle" : "Notifications",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_notifications")!,
"keyCtrlObjectAfterTap" : buttonTap3Callback
]]
],
["keyObjectTitle":"Auto",
//"keyObjectLineImage": UIImage(named: "objektu atskyrimas_4x")!,
"keyObjCtrlButtCollectionArray" : [
["keyCtrlItemTitle" : "Smart Menu",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_rocket")!,
"keyCtrlObjectAfterTap" : buttonTap2Callback
],
["keyCtrlItemTitle" : "Lock",
"keyCtrlItemSubtitle" : "Backdoor",
// "keyCtrlItemImage" : UIImage(named: "ico_lock_1@x3")!,
"keyCtrlObjectAfterTap" : buttonTapCallback
],
["keyCtrlItemTitle" : "Unlock",
"keyCtrlItemSubtitle" : "Fence",
// "keyCtrlItemImage" : UIImage(named: "ico_lock_0@x3")!,
"keyCtrlObjectAfterTap" : buttonTapCallback
],
["keyCtrlItemTitle" : "Ignore",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_shield@x3")!,
"keyCtrlObjectAfterTap" : buttonTap1Callback
],
["keyCtrlItemTitle" : "Stop",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_stop")!,
"keyCtrlObjectAfterTap" : buttonTap3Callback
]]
],
["keyObjectTitle":"Basement",
// "keyObjectLineImage": UIImage(),
"keyObjCtrlButtCollectionArray" : [
["keyCtrlItemTitle" : "Smart Menu",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_rocket")!,
"keyCtrlObjectAfterTap" : buttonTap1Callback
],
["keyCtrlItemTitle" : "Lock",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_lock_1@x3")!,
"keyCtrlObjectAfterTap" : buttonTapCallback
],
["keyCtrlItemTitle" : "Unlock",
"keyCtrlItemSubtitle" : "",
// "keyCtrlItemImage" : UIImage(named: "ico_lock_0@x3")!,
"keyCtrlObjectAfterTap" : buttonTapCallback
]]
]
]
]
func logoTapCallback()
print("logo tapped")
func menuButtonTapCallback()
print("menu button tapped ")
func buttonTapCallback()
print("button tapped")
func buttonTap1Callback()
print("button tapped 1")
func buttonTap2Callback()
print("button tapped 2")
func buttonTap3Callback()
print("button tapped 3")
func settTapCallback()
print("settTap")
func doneEditTapCallback()
print("doneEditTap")
// Dictionary structure I would like to use:
struct InitialDictionaryStructure
var keySelectedMenuButton : Int
var keySettButtCallback : ()->Void
var keyInfoButtCallback : ()->Void
var keyObjectMenuCallback : ()->Void
var buttonListChanged : ()->Void
var keyObjectArray : [[Object]]
struct Object
var keyObjectTitle : String
//var keyObjectLineImage : UIImage
var keyObjCtrlButtCollectionArray : [Button]
struct Button
var keyCtrlItemTitle : String
var keyCtrlItemSubtitle : String
//var keyCtrlItemImage : UIImage
var keyCtrlObjectAfterTap : ()-> Void
【问题讨论】:
由于函数不符合 JSON 或 PropertyList,您必须在每个结构中编写自定义init(dictionary : [String:Any])
方法并手动分配值。
@vadian 感谢您的回答。也许您可能会提供一个实现的示例?将不胜感激!
【参考方案1】:
没有智能方式,你必须添加初始化器。
如果不打算修改值,请将结构成员声明为常量,并且我会稍微缩短成员名称以省略冗余信息。
struct InitialDictionaryStructure
let menuButton : Int
let settButtCallback : ()->Void
let infoButtCallback : ()->Void
let objectMenuCallback : ()->Void
let buttonListChanged : ()->Void
let objects : [Object]
init(dictionary : [String:Any])
menuButton = dictionary["keySelectedMenuButton"] as! Int
settButtCallback = dictionary["keySettButtCallback"] as! ()-> Void
infoButtCallback = dictionary["keyInfoButtCallback"] as! ()-> Void
objectMenuCallback = dictionary["keyObjectMenuCallback"] as! ()-> Void
buttonListChanged = dictionary["buttonListChanged"] as! ()-> Void
let objectData = dictionary["keyObjectArray"] as! [[String:Any]]
objects = objectData.map(Object.init)
struct Object
let title : String
// let lineImage : UIImage
let buttons : [Button]
init(dictionary : [String:Any])
title = dictionary["keyObjectTitle"] as! String
// lineImage = dictionary["keyObjectLineImage"] as! UIImage
let buttonData = dictionary["keyObjCtrlButtCollectionArray"] as! [[String:Any]]
buttons = buttonData.map(Button.init)
struct Button
let title : String
let subtitle : String
// let image : UIImage
let objectAfterTap : ()-> Void
init(dictionary : [String:Any])
title = dictionary["keyCtrlItemTitle"] as! String
subtitle = dictionary["keyCtrlItemSubtitle"] as! String
// image = dictionary["keyCtrlItemImage"] as! UIImage
objectAfterTap = dictionary["keyCtrlObjectAfterTap"] as! ()-> Void
请考虑这是一个没有任何类型和nil
检查的简单示例。如果字典中没有包含正确类型的所有键,代码将会崩溃。
创建一个项目写
let initialDictionaryStructure = InitialDictionaryStructure(dictionary: dict)
print(initialDictionaryStructure)
【讨论】:
非常感谢您的解决方案和解释!我很感激!我想从现在开始我会自己管理一切,再次感谢。以上是关于将 NSDictionary 与内部函数解码为 swift 对象的值的主要内容,如果未能解决你的问题,请参考以下文章
PHP json_encode() 与空 NSDictionary
将此数据从 JSON 解析为 NSDictionary [重复]
NSDictionary 与 NSArray 正在转换为元素数组,同时使用 AfNetworking 2 将数据发布到 PHP