将 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

将NSString转换为键值对

将此数据从 JSON 解析为 NSDictionary [重复]

NSDictionary 与 NSArray 正在转换为元素数组,同时使用 AfNetworking 2 将数据发布到 PHP

如何使用内部函数 C++ 将 3 个加法和 1 个乘法转换为矢量化 SIMD

web应用中浏览器与服务端的编码和解码