我是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
}
}
}
答案 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中进行数据解析。视图模型将具有视图控制器用于以必要格式检索数据的各种方法。
以上内容大大简化,但应该可以满足您的需求。
基本流程:
答案 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]
。您必须将其存储在AppUtils
类parsedResponse
变量中。
var locationDetailsList = [LocationDetails]()
//Your model construction code here.
//Store the array of objects into AppUtils class
AppUtils.parsedResponse = locationDetailsList
像这样访问不同UIViewController
的模型。
AppUtils.parsedResponse
注意:如果您的应用未访问数据,请不要将值始终保留在内存中。尽可能尝试清理内存。