在表格视图中填充JSON数据Swift 4

时间:2019-05-02 19:00:25

标签: arrays json swift

我有json数据,我可以解析导航和名称的第一部分,但是我需要将数组子元素解析为表视图。

{
"nav": [
    {
        "name": "Home",
        "navigationName": "Home",
        "icon": null,
        "navigation": {
            "URI": null,
            "type": "CUSTOM",
            "target": "home",
            "depth": null,
            "data": null,
            "filters": {},
            "urlStructure": {
                "title": null,
                "isFeatured": false,
                "isCampaign": false
            }
        },
        "styles": []
    },
    {
        "name": "New In",
        "navigationName": "New In",
        "icon": null,
        "navigation": {
            "URI": null,
            "type": "NO_LINK",
            "target": "",
            "depth": null,
            "data": null,
            "filters": {},
            "urlStructure": {
                "title": null,
                "isFeatured": false,
                "isCampaign": false
            }
        },
        "styles": [
            "linkNewin"
        ],
        "children": [
            {
                "name": "New In Mens",
                "navigationName": "New In Mens",
                "icon": null,
                "navigation": {
                    "URI": "/men?facet:new=latest&sort=latest",
                    "type": "CATEGORY",
                    "target": "men",
                    "depth": null,
                    "data": null,
                    "filters": {
                        "facet:new": "latest",
                        "sort": "latest"
                    },
                    "urlStructure": {
                        "title": null,
                        "isFeatured": false,
                        "isCampaign": false
                    }
                },
                "styles": [
                    "linkNewin"
                ]
            },

那是json数据。我已经解析并填充了nav数组中的名字,但是不能为Children数组做名字。 到目前为止,我已经创建了此数据模型:

    struct Menu: Codable {
    var nav: [Menus]

}

struct Menus: Codable {
    var name: String
    var children: [Child]?


}

struct Child: Codable {
    var name: String
}

有人有什么想法吗?

我已经有了这些结构,因此当我在其中添加断点时可以看到孩子的名字,但是我不知道如何访问它们并将它们添加到第二部分。下面是我设置的表格视图< / p>

extension MenuViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 32
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCell(withIdentifier: "cell")

        if cell == nil {
            cell = UITableViewCell.init(style: .value1, reuseIdentifier: "cell")
        }
        let navItem = self.menu?.nav[indexPath.row]
//        cell?.det?.text = self.menu?.nav[indexPath.row].children?[indexPath.row].name


        return cell!
    }


}

1 个答案:

答案 0 :(得分:0)

I'm not sure how to approach your question since you gave not enough background and information, so I'm going to assume certain things and give you an answer. Let's start!

Looks like the children node is a Nav array so I created the following structs:

struct Menu: Codable {
    let nav: [Nav]

    func getMenu(_ parent: String? = nil) -> [Nav] {
        if parent == nil {
            return nav
        } else {
            let option =
                nav.compactMap { $0 }
                   .first { $0.name == parent }
            if let children = option?.children {
                return children
            } else {
                return []
            }
        }
    }
}

struct Nav: Codable {
    let name, navigationName: String
    let icon: String?
    let navigation: Navigation
    let styles: [String]
    let children: [Nav]?
}

struct Navigation: Codable {
    let URI: String?
    let type: String
    let target: String
    let depth: Int?
    let data: String?
    let filter: [String:String]?
    let urlStructure: UrlStructure
}

struct UrlStructure: Codable {
    let title: String?
    let isFeatured: Bool
    let isCampaign: Bool
}

Inside Menu I created a getMenu method. If no parameter is supplied it returns the top level menu else it tries to find a Nav whose name property equals the parameter sent. To decode your json use the following method that receives a JSON string and returns a Menu:

func decodeJson(_ jsonString: String) -> Menu {
    let decoder = JSONDecoder()
    // Try to get JSON from String to Data
    guard let jsonData = jsonString.data(using: .utf8) else { return Menu() }
    do {
        return try decoder.decode(Menu.self, from: jsonData)
    } catch { // Decode, if bad JSON return empty Menu
        return Menu()
    }
}

Thats all to decode your JSON to a Menu struct, now let's deal with the UI stuff. In your viewDidload or any other entry point in your ViewController you need to transform your JSON to a Menu struct. Define a variable for the Menu and a optional String variable that has the current menu's name.

var menu: Menu!
var currentMenuOption: String? = nil

Then initialize your navigationMenu with your JSON string:

let navigationMenu = decodeJson(jsonString)

After all of this your extension should look like this:

extension MenuViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return navigationMenu.getMenu(currentMenuOption).count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCell(withIdentifier: "cell")

        if cell == nil {
            cell = UITableViewCell.init(style: .value1, reuseIdentifier: "cell")
        }
        let navItem = self.menu.getMenu(currentMenuOption)[indexPath.row]
            cell?.det?.text = navItem.name
        return cell!
    }

If the user selects a row you must set currentMenuOption with the row text and reload the table. This implementation is trying to avoid changing your code as little as possible. Hopes this works for you, or at least give you an idea how to solve it :)