使用Swift 3,如何解析JSON文件以便我可以全局访问数据?

时间:2017-06-28 03:46:30

标签: ios json swift

我是iOS开发的新手,如果我使用不正确的术语,请提前道歉。我正在为一个学校项目开发一个基本的应用程序,并希望得到任何帮助!

我有一个包含20个不同对象的JSON文件(请参阅下面第一个对象的示例),我想在三个不同的View Controller中解析和访问它们用于不同的目的 - 相同的数据,只是订购或呈现在不同的方式。

JSON文件存储在xCode项目的本地。我如何解析它以便我可以在不同的View Controllers中全局访问数据?

我的理解是,最好在AppDelegate控制器中解析JSON文件,然后在每个ViewController中调用数据,但我不确定如何以编程方式执行此操作。

JSON文件的名称是“locations.json”

{
    locations: [

        {
            "id": 0001,
            "name": "Helensburgh Tunnels",
            "type": ["Tunnels", "Beach", "Views"],
            "location": "Helensburgh, South Coast",
            "image": "Helensburgh-Tunnels.jpg",
            "activity": "Walking, photography, tunnelling",
            "isVisited": false,
            "latitude": -34.178985,
            "longitude": 150.992867
        }
}

如果您可以扩展我在TableView中读取此数据的方式,那么我将不胜感激。我的TableView单元格当前配置如下(读出一个硬编码到同一ViewController中的数组) - 如何更新它以读取已解析的JSON数据?

ViewController的名称; LocationTableViewController.swift

var locations:[Location] = [
        Location(name: "Helensburgh Tunnels", type: "Old, abandoned train tunnels.", location: "Helensburgh, South Coast", image: "Helensburgh-Tunnels.jpg", activity: "Walking, photography, tunnelling", isVisited: false, latitude: "-34.178985", longitude: "150.992867")
]

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

    let cellIdentifier = "cell"
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! LocationTableViewCell

    // Configure the cell
    cell.nameLabel.text = locations[indexPath.row].name
    cell.thumbnailImageView.image = UIImage(named: locations[indexPath.row].image)
    cell.locationLabel.text = locations[indexPath.row].location
    cell.typeLabel.text = locations[indexPath.row].type
    cell.accessoryType = locations[indexPath.row].isVisited ? .checkmark : .none
    return cell
}

位置模型如下。 ViewController的名称; Location.swift

class Location: NSObject, MKAnnotation {
    var name: String = ""
    var type: String = ""
    var location: String = ""
    var image: String = ""
    var activity: String = ""
    var isVisited: Bool = false
    var rating: String = ""
    var latitude: Double = 0.0
    var longitude: Double = 0.0

    init(name: String, type: String, location: String, image: String, activity: String, isVisited: Bool, latitude: String, longitude: String) {
        self.name = name
        self.type = type
        self.location = location
        self.image = image
        self.activity = activity
        self.isVisited = isVisited
        self.latitude = Double(latitude)!
        self.longitude = Double(longitude)!
    }

    public var coordinate: CLLocationCoordinate2D { get {
        let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        return coordinate
        }
    }

}

3 个答案:

答案 0 :(得分:1)

创建一个新的Swift文件,如GlobalClass.Swift

在GlobalClass中导入Foundation和UIKit 使函数读取这样的位置: -

func readLocation() ->[String:Any]?{
    do {
        if let file = Bundle.main.url(forResource: "locations", withExtension: "json") {
            let data = try Data(contentsOf: file)
            let json = try JSONSerialization.jsonObject(with: data, options: [.mutableContainers])
            if let object = json as? [String: Any] {
                return object
            }
            return nil
        }
    } catch {
        print(error.localizedDescription)
    }
    return nil
}

并从TableView中调用此函数,如下所示: -

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

        let cellIdentifier = "cell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! LocationTableViewCell

        // Configure the cell
        if let locationJson = readLocation(){
            if let locations = locationJson["location"] as? [[String:Any]]{
                cell.nameLabel.text = locations[indexPath.row]["name"] as! String
                cell.thumbnailImageView.image = UIImage(named: (locations[indexPath.row]["image"] as! String))
                cell.locationLabel.text = locations[indexPath.row]["location"] as! String
                cell.typeLabel.text = locations[indexPath.row]["type"] as! String
                cell.accessoryType = (locations[indexPath.row]["isVisited"] as! Bool) ? .checkmark : .none
            }
        }
        return cell
    }

和部分中的行数应为

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let locationJson = readLocation(){
            if let locations = locationJson["location"] as? [[String:Any]]{
              return   locations.count
        }
    }
  return 0
}

确保您的位置文件应采用正确的json格式,否则此函数会抛出错误

答案 1 :(得分:0)

我通常不会在AppDelegate上查看此类事情。你应该做的尽可能少,

您可能希望查看类似MVVM的方法。您可以创建一个viewmodel,其作用是销售数据的各种排列。您可以将其创建为单例,但如果您的应用程序不是太复杂,您可以简单地在每个视图控制器中实例化视图模型。

我通常编写一个数据管理器,负责解析数据并提供一种方法来检索数据作为模型数组。 viewmodel可以在实例化时或根据需要调用datamanager方法。同样,对于简单的项目,您可以直接在viewmodel中进行数据解析。视图模型将具有视图控制器用于以必要格式检索数据的各种方法。

以上内容大大简化,但应该可以满足您的需求。

基本流程:

  1. View controller(s)实例化viewmodel(或获取共享实例)并在viewmodel上调用方法
  2. Viewmodel调用datamanager上的方法,如果它还没有数据。
  3. Datamanager解析JSON并返回模型数组
  4. Viewmodel方法操纵模型中的数据(例如排序)并将它们返回给视图控制器。
  5. 视图控制器显示返回的数据。

答案 2 :(得分:0)

从文件&中读取内容创建字典

let urlString = Bundle.main.path(forResource: "filename", ofType: "txt")

let url = URL(string: urlString!)

if let url = url {
    do {
        let data = try Data(contentsOf: url)

        let jsonDictionary = try JSONSerialization.jsonObject(with: data, options:[])

        // Model creation code here.
    } catch {
        print("Error : ")
    }
}

jsonDictionary对象构建模型类。 请参阅link,如何解析json对象并将其存储在模型类中。

型号:

struct LocationDetails {
    var id: Int = 0
    var name: String = ""
    // Other variables are here
}

经理班级:

// Here you can store common properties.
class AppUtils {
    class var parsedResponse: [LocationDetails]
}

构建模型列表后。例如[LocationDetails]。您必须将其存储在AppUtilsparsedResponse变量中。

var locationDetailsList =  [LocationDetails]()
//Your model construction code here.

//Store the array of objects into AppUtils class
AppUtils.parsedResponse = locationDetailsList

像这样访问不同UIViewController的模型。

AppUtils.parsedResponse

注意:如果您的应用未访问数据,请不要将值始终保留在内存中。尽可能尝试清理内存。