【问题标题】:How to display JSON file in sections and rows in TableView in Swift如何在 Swift 中的 TableView 中的部分和行中显示 JSON 文件
【发布时间】:2017-10-11 04:01:24
【问题描述】:

我是 Xcode 和 Swift 的新手。我需要帮助将 JSON 文件中的数据显示到带有部分和行的 TableView 中。我需要在每个街区展示不同的餐厅。我想我需要在我的 JSON 文件中进行更改,但我无法弄清楚。我真的很感激任何帮助。干杯。

这是我的 JSON 文件:

{
"hoods": {

"neighborhoodNames": {
   "marina":[

{
  "name": "MARINA-1",
  "dob": "December 18, 1963",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/brad.jpg"
},
{
  "name": "MARINA-2",
  "description": "Tom Cruise, is an American film actor and producer. He has been nominated for three Academy Awards and has won three Golden Globe Awards. He started his career at age 19 in the 1981 film Endless Love.",
  "dob": "July 3, 1962",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/cruise.jpg"
},
{
  "name": "MARINA-3",
  "description": "John Christopher 'Johnny' Depp II is an American actor, film producer, and musician. He has won the Golden Globe Award and Screen Actors Guild award for Best Actor.",
  "dob": "June 9, 1963",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/johnny.jpg"
}
],
   "MISSION":[

{
  "name": "MISSION-1",
  "dob": "December 18, 1963",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/brad.jpg"
},
{
  "name": "MISSION-2",  
  "dob": "July 3, 1962",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/cruise.jpg"
},
{
  "name": "MISSION-3",
  "dob": "June 9, 1963",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/johnny.jpg"
},
 {
  "name": "MISSION-4",
  "dob": "June 9, 1963",
  "image": "http://microblogging.wingnity.com/JSONParsingTutorial/johnny.jpg"
}
]}
}
}

这是 JSON 文件的链接:http://barhoppersf.com/json/hoods.json

这是我的 Xcode:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

  let urlString = "http://barhoppersf.com/json/hoods.json"



@IBOutlet weak var tableView: UITableView!

var nameArray:[[String]] = []
var dobArray:[[String]] = []
var imgURLArray:[[String]] = []
var neighborhoodNames = [String]()


override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self


    self.downloadJsonWithURL()

    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}




func downloadJsonWithURL() {

    let url = NSURL(string: urlString)

    URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in


        if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {


            if let actorArray = jsonObj!.value(forKey: "hoods") as? NSArray {

                for actor in actorArray{

                    if let actorDict = actor as? NSDictionary {


                        if let name = actorDict.value(forKey: "neighborhoodNames") {
                            self.neighborhoodNames.append(name as! String)
                        }
                        if let name = actorDict.value(forKey: "name") {
                            self.nameArray.append([name as! String])
                        }
                        if let name = actorDict.value(forKey: "dob") {
                            self.dobArray.append([name as! String])
                        }
                        if let name = actorDict.value(forKey: "image") {
                            self.imgURLArray.append([name as! String])
                        }

                    }
                }
            }

//                self.nameArray = self.nameArray.sorted()


            OperationQueue.main.addOperation({
                self.tableView.reloadData()
            })
        }
    }).resume()
}




 func downloadJsonWithTask() {

    let url = NSURL(string: urlString)

    var downloadTask = URLRequest(url: (url as URL?)!, cachePolicy:     URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 15)

    downloadTask.httpMethod = "GET"

    URLSession.shared.dataTask(with: downloadTask, completionHandler: {(data,   response, error) -> Void in

         let jsonData = try? JSONSerialization.jsonObject(with: data!, options:  .allowFragments)

        print(jsonData as Any)

    }).resume()
}


   // MARK: - changing the color, background and position of the header
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int)  -> UIView? {
    let headerView = UIView()
    headerView.backgroundColor = UIColor.self.init(red: 254/255, green:  170/255, blue: 25/255, alpha: 1.0)


    let headerLabel = UILabel(frame: CGRect(x: 8, y: 5, width: tableView.bounds.size.width, height: tableView.bounds.size.height))

    headerLabel.font = UIFont(name: "Trebuchet MS", size: 15)
    headerLabel.textColor = UIColor.darkGray
    headerLabel.text = self.tableView(self.tableView, titleForHeaderInSection: section)
    headerLabel.sizeToFit()
    headerView.addSubview(headerLabel)

    return headerView
}


    // MARK: - changing the size of the header cell
    //      func tableView(_ tableView: UITableView, heightForHeaderInSection  section: Int) -> CGFloat {
    //        return 40
    //    }


       func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

      return (nameArray[section].count)

}



     func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

    return neighborhoodNames[section]
}

     func numberOfSections(in tableView: UITableView) -> Int {
    return neighborhoodNames.count
}


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

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell

      //          cell.nameLabel.text = nameArray[indexPath.row]
         cell.nameLabel?.text = nameArray[indexPath.section][indexPath.row]


    return cell
}

  // set up A_Z index
   //    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
    //        return indexName
    //    }

       // call correct section when index is tapped
       func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {

    guard let index = indexName.index(of: title) else {
        return -1
    }

    return index

}

      ///for showing next detailed screen with the downloaded info
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

     let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
    vc.imageString = imgURLArray[indexPath.section][indexPath.row]
    vc.nameString = nameArray[indexPath.section][indexPath.row]
    vc.dobString = dobArray[indexPath.section][indexPath.row]

    self.navigationController?.pushViewController(vc, animated: true)
}
}

提前非常感谢!!! 点。

【问题讨论】:

  • 您的问题是什么?你有什么问题?请只发布相关代码。
  • 我正在尝试在 TableView 部分的行中显示所有不同的餐厅(Marina-1、Marina-2...)和社区的名称(Marina)。谢谢。
  • 上面的JSON怎么和JSON文件的链接不匹配?
  • 对不起,伙计们。 JSON 的 url 现在是正确的。谢谢

标签: ios json swift uitableview


【解决方案1】:

您上面的 JSON 和来自该 URL 的 JSON 是不同的,所以我在这里的内容可以同时适用。

import UIKit

struct Actor {

    var children: String

    var country: String

    var description: String

    var dob: String

    var height: String

    var image: String

    var name: String

    var spouse: String

    init?(dict:Dictionary<String,String>) {

        guard

            let children = dict["children"],

            let country = dict["country"],

            let description = dict["description"],

            let dob = dict["dob"],

            let height = dict["height"],

            let image = dict["image"],

            let name = dict["name"],

            let spouse = dict["spouse"]

        else {

            return nil
        }

        self.children =  children

        self.country =  country

        self.description =  description

        self.dob =  dob

        self.height =  height

        self.image =  image

        self.name =  name

        self.spouse =  spouse
    }
}

struct Restaurant {

    var name: String

    var dob: String

    var image: String

    init?(dict:Dictionary<String,String>) {

        guard

            let name = dict["name"],

            let dob = dict["dob"],

            let image = dict["image"]

        else {

            return nil
        }

        self.name = name

        self.dob = dob

        self.image = image
    }
 }

struct NeighborhoodActors {

    var name: String

    var actors: Array<Actor>

    init(name:String, data:Array<Dictionary<String,String>>) {

        self.name = name

        self.actors = Array<Actor>()

        for dict in data {

            if let actor = Actor(dict: dict) {

                self.actors.append(actor)
            }
        }
    }
}

struct NeighborhoodRestaurants {

    var name: String

    var restaurants: Array<Restaurant>

    init(name:String, data:Array<Dictionary<String,String>>) {

        self.name = name

        self.restaurants = Array<Restaurant>()

        for dict in data {

            if let restaurant = Restaurant(dict: dict) {

                self.restaurants.append(restaurant)
            }
        }
    }
 }

class ViewController: UITableViewController {

    let urlString = "http://barhoppersf.com/json/hoods.json"

    var tableData = Array<NeighborhoodRestaurants>()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.downloadJsonWithURL() // This loads tableview with data from url

        load(file: "document") // This loads tableview with the json in your question, which I put in a json file to test
    }

    func load(file:String) {

        guard let path = Bundle.main.path(forResource: file, ofType: "json") else { return }

        guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { return }

        guard let json = try? JSONSerialization.jsonObject(with: data) else { return }

        guard let dict = json as? Dictionary<String,Dictionary<String,Dictionary<String,Array<Dictionary<String,String>>>>> else { return }

        guard let hoods = dict["hoods"] else { return }

        guard let names = hoods["neighborhoodNames"] else { return }

        for (key, value) in names {

            let neighborhood = NeighborhoodRestaurants(name: key, data: value)

            self.tableData.append(neighborhood)
        }

        self.tableData.sort { $0.name > $1.name } // This will arrange the restaurants alphabetically

        self.tableView.reloadData()
    }

    func downloadJsonWithURL() {

        let url = NSURL(string: urlString)

        URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in

            if let error = error {

                print(error.localizedDescription)

                return
            }

            if let data = data {

                guard let json = try? JSONSerialization.jsonObject(with: data) else { return }

                guard let dict = json as? Dictionary<String,Dictionary<String,Dictionary<String,Array<Dictionary<String,String>>>>> else { return }

                guard let hoods = dict["hoods"] else { return }

                guard let names = hoods["neighborhoodNames"] else { return }

                for (key, value) in names {

                    let neighborhood = NeighborhoodActors(name: key, data: value)

                    // self.tableData.append(neighborhood)
                }

                DispatchQueue.main.async {

                    self.tableView.reloadData()
                }
            }

        }).resume()
    }

    // MARK: - changing the color, background and position of the header
    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int)  -> UIView? {

        let headerView = UIView()

        headerView.backgroundColor = UIColor.self.init(red: 254/255, green:  170/255, blue: 25/255, alpha: 1.0)

        let headerLabel = UILabel(frame: CGRect(x: 8, y: 5, width: tableView.bounds.size.width, height: tableView.bounds.size.height))

        headerLabel.font = UIFont(name: "Trebuchet MS", size: 15)

        headerLabel.textColor = UIColor.darkGray

        headerLabel.text = self.tableView(self.tableView, titleForHeaderInSection: section)

        headerLabel.sizeToFit()

        headerView.addSubview(headerLabel)

        return headerView
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return self.tableData[section].restaurants.count
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

        return self.tableData[section].name
    }

    override func numberOfSections(in tableView: UITableView) -> Int {

        return self.tableData.count
    }

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

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        cell.textLabel?.text = self.tableData[indexPath.section].restaurants[indexPath.row].name

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController

        vc.restaurant = self.tableData[indexPath.section].restaurants[indexPath.row]

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

class DetailViewController: UIViewController {

    @IBOutlet var imageView: UIImageView!

    @IBOutlet weak var nameLabel: UILabel!

    @IBOutlet weak var dobLabel: UILabel!

    var restaurant: Restaurant!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.nameLabel.text = self.restaurant.name

        self.dobLabel.text = self.restaurant.dob

        if let url = URL(string: self.restaurant.image) {

            let task = URLSession.shared.dataTask(with: url) { data, resonse, error in

                if let error = error {

                    print(error.localizedDescription)

                    return
                }

                if let data = data {

                    let image = UIImage(data: data)

                    DispatchQueue.main.async {

                        self.imageView.image = image
                    }
                }
            }

            task.resume()
        }
    }
}

这是打开 URL、打开苹果地图和拨打电话号码的方法。

func telephone(phoneNumber:String) {

    let application = UIApplication.shared

    if application.openURL(URL(string: "tel://\(phoneNumber)")!) {

        print("Ringing")

    } else {

        print("Something has gone wrong.")
    }
}

func directions(address:String) {

    let geocoder = CLGeocoder()

    geocoder.geocodeAddressString(address) { (placemarks, error) in

        if let description = error?.localizedDescription {

            print(description)

            return
        }

        if let placemark = placemarks?.first {

            let pin = MKPlacemark(placemark: placemark)

            let item = MKMapItem(placemark: pin)

            let region = MKCoordinateRegionMakeWithDistance(pin.coordinate, 1000, 1000)

            let options: Dictionary<String,Any> = {

                var dict = Dictionary<String,Any>()

                dict[MKLaunchOptionsMapCenterKey] = NSValue(mkCoordinate: region.center)

                dict[MKLaunchOptionsMapSpanKey] = NSValue(mkCoordinateSpan: region.span)

                return dict
            }()

            item.openInMaps(launchOptions: options)

            return
        }

        print("An unknown error has occured.")
    }
}

func website(url:String) {

    if let url = URL(string: url) {

        let application = UIApplication.shared

        application.openURL(url)

        return
    }

    print("The URL is invalid.")
}

【讨论】:

  • 特里斯坦感谢您的帮助和回答,但它在这里不起作用。也许我做错了什么。我收到一个错误:'由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'-[UITableViewController loadView] 加载了“BYZ-38-t0r-view-8bC-Xf-vdC”笔尖,但没有获得 UITableView。 '有什么想法吗?
  • 在你的故事板中,它是 UIViewController 还是 UITableViewController?
  • 是ViewController
  • 如果你添加一个 UITableViewController 到你的故事板并设置我在上面创建的类应该可以工作。如果需要使用 UIViewController,则需要添加 UITableView 插座并设置 UITableViewDelegate 和 UITableViewDatasource。另外,将超类从 UITableViewController 更改为 UIViewController,并从所有 tableview 方法中删除覆盖。
  • 我搞定了。太感谢了。现在,当我单击单元格(Marina-1、Marina-2 ...)时,我必须获得信息显示。我用 TableViewCell 和 TableViewController 设置了它。
猜你喜欢
  • 2017-02-19
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多