簡體   English   中英

使用Swift 3,如何解析JSON文件,以便可以全局訪問數據?

[英]Using Swift 3, how can I parse a JSON file so that I can access the data globally?

我是iOS開發的新手,因此如果使用不正確的術語,請提前道歉。 我正在為學校項目開發一個基本應用程序,希望對您有所幫助!

我有一個JSON文件,其中包含20個不同的對象(請參見下面的第一個對象的示例),我想在三個不同的View Controller中解析和訪問這些對象以實現不同的目的-相同的數據,只是以不同的方式排序或表示。

JSON文件存儲在本地的xCode項目中。 如何解析它,以便可以在不同的View Controller中全局訪問數據?

我的理解是,最好在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
        }
    }

}

創建一個新的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格式,否則此函數將引發錯誤

我通常不會在AppDelegate上看到這種類型的東西。 你應該盡量少做些

您可能想看看類似MVVM的方法。 您可以創建一個視圖模型,其工作是出售數據的各種排列。 您可以將其創建為單例,但是如果您的應用不太復雜,則可以在每個視圖控制器中實例化視圖模型。

我通常編寫一個數據管理器,負責解析數據並提供一種以模型數組的形式檢索數據的方法。 視圖模型可以在實例化時或根據需要調用datamanager方法。 同樣,對於簡單的項目,您可以直接在viewmodel中進行數據解析。 視圖模型將具有各種方法,視圖控制器將使用這些方法來檢索必要格式的數據。

上面已大大簡化,但應該可以滿足您的需求。

基本流程:

  1. 視圖控制器實例化視圖模型(或獲取共享實例)並在視圖模型上調用方法
  2. 如果沒有數據,Viewmodel會在datamanager上調用method。
  3. Datamanager解析JSON並返回模型數組
  4. Viewmodel方法操作來自模型的數據(例如,排序),並將其返回給視圖控制器。
  5. View Controller顯示返回的數據。

從文件中讀取內容並創建字典

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對象中,您可以構建模型類。 請參考鏈接的,如何解析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

注意:如果您的應用程序不訪問數據,則不要將值始終保存在內存中。 盡可能嘗試清理內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM