如何在Swift

时间:2017-05-12 00:11:41

标签: ios json swift uitableview

我是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)
}
}

非常感谢! 典

1 个答案:

答案 0 :(得分:0)

上面的JSON和该网址中的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()
        }
    }
}

这是打开网址,打开苹果地图和拨打电话号码的方法。

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.")
}