【问题标题】:How to add section to UITableView programmatically in swift 3如何在 swift 3 中以编程方式将部分添加到 UITableView
【发布时间】:2017-06-04 13:47:53
【问题描述】:

我需要列出 json 的内容并按日期(部分)排序。到目前为止,我成功获取了 json 并列出了主要内容(名称和时间),但我需要按日期排序。

编辑: 如果我有超过 100 个“项目”(json 对象)并且在某些情况下重复了日期(如下面 json 的前两个对象),那么我希望这些项目位于以日期为标题的部分中每个部分。

Json:

[
{"date_raw":"1/18/2017 12:00:00 AM","name":"Hello 2","hour":"12:00 - 14:00","audio_url":"http://example.com/file2.mp4"},
{"date_raw":"1/18/2017 12:00:00 AM","name":"Hello 1","hour":"10:00 - 12:00","audio_url":"http://example.com/file1.mp4"},
{"date_raw":"1/17/2017 12:00:00 AM","name":"Hello","hour":"10:00 - 12:00","audio_url":"http://example.com/file.mp4"},
{"date_raw":"1/16/2017 12:00:00 AM","name":"Hello","hour":"10:00 - 12:00","audio_url":"http://example.com/file.mp4"}
]

主类

class MyVC: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    // date_raw
    var section: [String] = []

    // date_raw, name, hour, audio_url
    var items: [(String, String, String, String)] = []

    var dateV:String = ""

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count

    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "cell")

        cell.textLabel!.text = items[indexPath.row].1 // get name
        cell.detailTextLabel!.text = items[indexPath.row].2 // get hour

        return cell;
    }


    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(items[indexPath.row])

    }


    func getJson(_ url:String) {

        // Asynchronous Http call to your api url, using NSURLSession:
        URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { (data, response, error) -> Void in

            if error != nil || data == nil {

                print("error")

            } else {


                do {

                    let json:NSArray = try (JSONSerialization.jsonObject(with: data!, options:JSONSerialization.ReadingOptions.mutableContainers) as? NSArray)!

                    for i in 0...json.count-1 {

                        if let date_raw = (json[i] as AnyObject).value(forKey: "date_raw") as? String,
                            let name = (json[i] as AnyObject).value(forKey: "name") as? String,
                            let hour = (json[i] as AnyObject).value(forKey: "hour") as? String,
                            let audio_url = (json[i] as AnyObject).value(forKey: "audio_url") as? String {

                            if date_raw != self.dateV {
                                self.section.append(date_raw)
                                self.dateV = date_raw;
                            }

                            self.items.append(date_raw, name, hour, audio_url)

                        }
                    }//End for

                    //print(self.section)
                    self.do_table_refresh();

                } catch {
                    print("error")
                }

            }

        }).resume()
        // TODO: butonu disable et
    }


    func do_table_refresh() {
        DispatchQueue.main.async(execute: {
            self.tableView.reloadData()
            self.tableView.isHidden = false
            return
        })
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate      =   self
        tableView.dataSource    =   self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        tableView.isHidden = true

        getJson("http://example.com/my-json-file.json")

    }


}

【问题讨论】:

    标签: ios json uitableview swift3


    【解决方案1】:
    func numberOfSections(in tableView: UITableView) -> Int
    {
        return 5 // number of sections
    }
    

    使用此函数以编程方式添加部分

    【讨论】:

    • 谢谢,但是如果我不知道我会有多少“部分”怎么办? (取决于动态 json)
    • 使用实例变量而不是 5。每次解析 json 结构时填充该变量。
    • 好吧,假设我使用:return section.count,这还不够,对吧?
    • 是的,你得根据json响应来计算段数。
    • 抱歉,我在添加项目时仍然不明白如何在表格中添加部分:cell.textLabel!.text = items[indexPath.row].1 /:
    【解决方案2】:

    这里有代码示例(粘贴在 Playground 中并玩得开心)

    //: Playground - noun: a place where people can play
    
    import UIKit
    import PlaygroundSupport
    
    PlaygroundPage.current.needsIndefiniteExecution = true
    
    struct Model {
        let date: String
        let name: String
        let hour: String
        let audioUrl: String
    }
    
    class HelpViewController: UITableViewController {
    
        let jsonData = "[{\"date_raw\":\"1/18/2017 12:00:00 AM\",\"name\":\"Hello 2\",\"hour\":\"12:00 - 14:00\",\"audio_url\":\"http://example.com/file2.mp4\"},{\"date_raw\":\"1/18/2017 12:00:00 AM\",\"name\":\"Hello 1\",\"hour\":\"10:00 - 12:00\",\"audio_url\":\"http://example.com/file1.mp4\"},{\"date_raw\":\"1/17/2017 12:00:00 AM\",\"name\":\"Hello\",\"hour\":\"10:00 - 12:00\",\"audio_url\":\"http://example.com/file.mp4\"},{\"date_raw\":\"1/16/2017 12:00:00 AM\",\"name\":\"Hello\",\"hour\":\"10:00 - 12:00\",\"audio_url\":\"http://example.com/file.mp4\"}]"
    
        var data = [String: [Model]]()
        var keys = [String]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TestCell")
            loadData()
        }
    
        func loadData() {
            guard let jsonData = jsonData.data(using: .utf8),
                let json = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments),
                let jsonArray = json as? [[String: Any]]
            else { return }
    
            // Map json to array of Models
            let mappedData = jsonArray.flatMap { (elem) -> Model? in
                guard let dateRaw = elem["date_raw"] as? String,
                    let name = elem["name"] as? String,
                    let hour = elem["hour"] as? String,
                    let audioUrl = elem["audio_url"] as? String else { return nil }
    
                return Model(date: dateRaw, name: name, hour: hour, audioUrl: audioUrl)
            }
    
            // Create a dictionary from array of Models
            // Each key == section (model.date), will contain array of associated with this key models
            data = mappedData.reduce([String: [Model]]()) { (result, element) -> [String: [Model]] in
    
                var res = result
                if res[element.date] == nil {
                    res[element.date] = [element]
                    self.keys += [element.date]
                } else {
                    res[element.date]! += [element]
                }
                return res
            }
    
            tableView.reloadData()
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            if keys.count < 1 { return 0 }
    
            let key = keys[section]
            return data[key]?.count ?? 0
        }
    
        override func numberOfSections(in tableView: UITableView) -> Int {
            return keys.count
        }
    
        override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            return keys[section]
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath)
    
            let key = keys[indexPath.section]
            let model = data[key]?[indexPath.row]
            if let model = model {
                cell.textLabel?.text = model.name
            }
    
            return cell
        }
    
    }
    
    let helpViewController = HelpViewController()
    helpViewController.view.frame = CGRect(x: 0, y: 0, width: 320, height: 400)
    
    PlaygroundPage.current.liveView = helpViewController.view
    

    【讨论】:

    • 谢谢。我已经尝试过了,它有效。日期显示为部分标题,但不幸的是没有按顺序(因为它在 json 中)。我不知道会发生什么。 /:
    • 这是因为 Dictionary 不保证键的顺序。您可以查看github.com/lukaskubanek/OrderedDictionary。还要检查我更新的答案,现在它已将键存储在数组中,以保持与 json 文件中键的顺序相同。
    • 哇!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多