涉及 JSON 解析以及静态和动态 UITableView 单元格的 Swift3 项目 - 使其更加面向对象
Posted
技术标签:
【中文标题】涉及 JSON 解析以及静态和动态 UITableView 单元格的 Swift3 项目 - 使其更加面向对象【英文标题】:Swift3 project involving JSON parsing and both static and dynamic UITableView cells - making it more object-oriented 【发布时间】:2017-05-22 02:05:30 【问题描述】:我有一个 CTA(芝加哥交通管理局)火车跟踪应用程序,它可以完全按照我的意愿执行和工作。然而,代码本身远非面向对象。
您可以选择您想要的线路,这会将您带到一个显示所有车站的车站屏幕,您可以单击它进入一个表格视图,其中显示每个车站的火车到达时间和带有数据提取的目的地火车站来自 CTA 维护的 JSON 文件。
但是,我不得不为每个火车站创建一个新的 tableView swift 文件,导致 tableView 数量巨大。如果我需要更改某些内容,我需要将该更改复制并粘贴到所有站 tableViews 中。
我认为其中一个原因是我为 Trains tableView 和 Stations tableViews 使用了静态单元格,但每个目的地车站的 tableViews 都是动态的(我这样做是因为车站永远不会改变,但目的地车站的信息会更新经常为到达的火车。此外,我不知道如何更改从车站 tableView 发送到目标车站 tableView 的 JSON 提要,以便在我尝试制作项目时每个目标车站解析不同的 JSON 文件动态 tableView 单元格)。
有没有办法让我只能为 Stations tableView 提供一个动态单元格 tableView(例如 Red Line Stations tableView 只有一个动态原型单元格)?
以下是我的项目故事板及其代码:
import UIKit
class RedHowardTableViewController: UITableViewController
class Destinations
var destination: String = ""
var time: String = ""
var feed = "http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=mykey&mapid=40900&outputType=JSON"
var dataAvailable = false
var records = [Destinations]()
override func viewDidLoad()
super.viewDidLoad()
parseData()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
for r in records
r.time = ""
r.destination = ""
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return dataAvailable ? records.count : 15
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
if (dataAvailable)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let destinationRow = records[indexPath.row]
cell.textLabel?.text = "Heading towards " + destinationRow.destination
cell.detailTextLabel?.text = "Arriving at: " + destinationRow.time
return cell
else
let cell = tableView.dequeueReusableCell(withIdentifier: "PlaceholderCell", for: indexPath)
return cell
func parseData()
guard let feedURL = URL(string: feed) else
return
let request = URLRequest(url: feedURL)
let task = URLSession.shared.dataTask(with: request) (data, response, error) in
if error != nil
print("Error")
else
if let content = data
do
let json = try JSONSerialization.jsonObject(with: content, options: []) as? [String:Any] ?? [:]
print(json)
if let ctattimetable = json["ctatt"] as? [String:Any]
if let estArrivalTime = ctattimetable["eta"] as? [[String:Any]]
for item in estArrivalTime
if let headingTowards = item["destNm"] as? String,
let arrivalTime = item["arrT"] as? String
if (headingTowards != "Howard")
let record = Destinations()
record.destination = headingTowards
let formattedDate = String(arrivalTime.characters.suffix(8))
let components = formattedDate.components(separatedBy: ":").flatMap(Int($0))
let time12h = String(format: "%d:%02d", components[0] % 12, components[1]) + (components[0] < 12 ? "am" : "pm")
record.time = String(time12h)
self.records.append(record)
self.dataAvailable = true
DispatchQueue.main.async
self.tableView.reloadData()
catch
task.resume()
以下是我尝试主要使用动态 tableViews 执行此操作时的结果,这导致为每个 Destination tableView 解析相同的 JSON 文件:
以下所有蓝线车站的 TableViewController:
import UIKit
class BlueLineTableViewController: UITableViewController
override func viewDidLoad()
super.viewDidLoad()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return bluelinestations.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "bluelinecell", for: indexPath)
let station = bluelinestations[indexPath.row]
cell.textLabel?.text = station.name
cell.imageView?.image = UIImage(named: station.image)
return cell
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let row = indexPath.row
if row == 0
BlueBelmontTableViewController().feed = "http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=mykey&mapid=40890&outputType=JSON"
if row == 1
BlueBelmontTableViewController().feed="http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=mykey&mapid=40820&outputType=JSON"
Destination Station tableViewController 的代码显示每个站点的到达时间
import UIKit
class BlueBelmontTableViewController: UITableViewController
class Destinations
var destination: String = ""
var time: String = ""
var feed = "http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=mykey&mapid=40440&outputType=JSON"
var dataAvailable = false
var records = [Destinations]()
override func viewDidLoad()
super.viewDidLoad()
parseData()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
for r in records
r.time = ""
r.destination = ""
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return dataAvailable ? records.count : 15
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
if (dataAvailable)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let destinationRow = records[indexPath.row]
cell.textLabel?.text = destinationRow.destination
cell.detailTextLabel?.text = destinationRow.time
return cell
else
let cell = tableView.dequeueReusableCell(withIdentifier: "PlaceholderCell", for: indexPath)
return cell
func parseData()
guard let feedURL = URL(string: feed) else
return
let request = URLRequest(url: feedURL)
let task = URLSession.shared.dataTask(with: request) (data, response, error) in
if error != nil
print("Error")
else
if let content = data
do
let json = try JSONSerialization.jsonObject(with: content, options: []) as? [String:Any] ?? [:]
print(json)
if let ctattimetable = json["ctatt"] as? [String:Any]
if let estArrivalTime = ctattimetable["eta"] as? [[String:Any]]
for item in estArrivalTime
if let headingTowards = item["destNm"] as? String,
let arrivalTime = item["arrT"] as? String
let record = Destinations()
record.destination = headingTowards
record.time = arrivalTime
self.records.append(record)
self.dataAvailable = true
DispatchQueue.main.async
self.tableView.reloadData()
catch
task.resume()
【问题讨论】:
【参考方案1】:因为你使用了静态单元格,所以当你为单元格选择事件定义一个动作时,你有很多作为静态单元格的 segue,一个 segue 将对应一个 table view,因此你将有很多 table view 来控制故事板。
我认为您应该将Train Table View
和Station Table View
都更改为动态。它减少了大量的表格,易于更改和编辑。它会更灵活。
像这样:
编辑:为 segue 的目标控制器传递数据
在你的 Station View Controller
中,添加这个 segue 委托函数:
// MARK: - segue perform handle
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
super.prepare(for: segue, sender: sender)
guard let segueIdentifier = segue.identifier else
return
switch segueIdentifier
case "your_segue_identifer":
let destinationViewController = segue.destination as? DestinationViewController
guard let selectedRowIndex = yourTableView.indexPathForSelectedRow?.row else
break
destinationViewController?.config(withStation station: yourStationList[selectedRowIndex])
default:
break
【讨论】:
谢谢。我会尽量让它动态工作。我编辑了上面的蓝线车站代码(参见最后一种方法),但我似乎无法将提要传递给目标视图控制器。您知道我将如何根据单击的行将 feed 变量设置为新的 url 字符串(在目标视图控制器代码中)吗? 检查我编辑的答案,我添加了代码块以将提要传递给目标视图控制器。以上是关于涉及 JSON 解析以及静态和动态 UITableView 单元格的 Swift3 项目 - 使其更加面向对象的主要内容,如果未能解决你的问题,请参考以下文章
Java中的方法调用分析!详细解析静态分派和动态分派的执行过程