Hello,
For the below code please can you tell me why the test code print("line 64") is being printed after the test code print("line 84") ? (i.e. how do I stop that happening?)
I would like the program to wait until the results array has been parsed before continuing the code (otherwise it does not have content to present).
I'm a bit confused why this is happening because I haven't written "async" anywhere.
import UIKit
struct NewsFeed: Codable {
var id: String
var name: String
var country: String
var type: String
var situation: String
var timestamp: String
}
class QuoteTableViewController: UITableViewController {
var newsFeed: [[String: String]] = []
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// let selectedQuote = quotes[indexPath.row]
// performSegue(withIdentifier: "moveToQuoteDetail", sender: selectedQuote)
}
override func viewDidLoad() {
super.viewDidLoad()
// tableView.dataSource = self
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// (viewDidLoad loads after tableView)
// try getting array results here
let urlString = "https://www.notafunnyname.com/jsonmockup.php"
let url = URL(string: urlString)
let session = URLSession.shared
let dataTask = session.dataTask(with: url!) { (data, response, error) in
var dataString = String(data: data!, encoding: String.Encoding.utf8)
if error == nil && data != nil {
// Parse JSON
let decoder = JSONDecoder()
do {
var newsFeed = try decoder.decode([NewsFeed].self, from: data!)
print("line 64")
// print(newsFeed)
// print("line 125")
// print(newsFeed.count)
print(error)
}
catch{
print("Line 72, Error in JSON parsing")
print(error)
}
}
}
// Make the API Call
dataTask.resume()
// #warning Incomplete implementation, return the number of rows
print("line 84")
print(newsFeed.count)
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
let cell = UITableViewCell ()
cell.textLabel?.text = "test"
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
// getPrice()
print("test_segue")
if let quoteViewController = segue.destination as? QuoteDetailViewController{
if let selectedQuote = sender as? String {
quoteViewController.title = selectedQuote
}
}
}
}
Many thanks
why the test code print("line 64") is being printed after the test code print("line 84")
Because the session.dataTask
call on line 52 returns immediately and runs the code from line 78 onwards. The call to dataTask.resume
on line 80 also returns immediately, having caused the download to start asynchronously. The code in lines 53 to 76 runs only when the download has completed.
I would like the program to wait until the results array has been parsed before continuing the code (otherwise it does not have content to present).
Waiting in a method like this one would cause the UI to freeze until the download has finished, which is very undesirable.
You need to start your networking elsewhere. When the download completes, store the items and tell the view to update. Have the numberOfRowsInSection
method just return the current number of items, which will initially be zero. Possibly also present some sort of "wait" indication (spinner, etc) in this case.