简体   繁体   中英

Swift, URLSession, viewDidLoad, tableViewController

I've never really gotten the nuances of async operations so time and again, I get stymied. And I just can't figure it out.

I'm trying to do some very simple web scraping.

My local volleyball association has a page (verbose HTML, not responsive, not mobile-friendly, yaddah, yaddah, yaddah) which shows the refs assigned to each game of the season. I'm trying to write a silly little app which will scrape that page (no API, no direct access to db, etc.) and display the data in a grouped table. The first group will show today's matches (time, home team, away team). The second group will show tomorrow's matches. Third group shows the entire season's matches.

Using code I found elsewhere, my viewDidLoad loads the page, scrapes the data and parses it into an array. Once I've parsed the data, I have three arrays: today , tomorrow , and matches , all are [Match] .

override func viewDidLoad() {
  super.viewDidLoad()

  let url = URL(string: urlString)!
  let request = NSMutableURLRequest(url: url)
  let task = URLSession.shared.dataTask(with: request as URLRequest) {
    data, response, error in
    if let error = error {
      print (error)
    } else {
      if let unwrappedData = data {
        // scrape, scrape, parse, parse
        matchRow = ...
        self.matches.append(matchRow)

        if matchRow.date == todaysDate {
          self.today.append(matchRow)
        } else if matchRow.date == tomorrowsDate {
          self.tomorrow.append(matchRow)
        }
      }
    }
  }
  task.resume()
}

As I'm sure is no surprise to anyone who understands async operations, my table is empty. I've checked and I see the the data is there and properly parsed, etc. But I can't for the life of me figure out how get the data in my table. The way I have it now, the data is not ready when numberOfSections or numberOfRowsInSection is called.

I've found the Ray Wenderlich tutorial on URLSession and I also have a Udemy course (Rob Percival) that builds an app to get the weather using web scraping, but in both those instances, the app starts and waits for user input before going out to the web to get the data. I want my app to get the data immediately upon launch, without user interaction. But I just can't figure out what changes I need to make so that those examples work with my program.

Help, please.

You can simply reload the tableviews once the data arrays are getting populated from the URLSession completion block. Have you tried that. Sample snippet may be like the one follows.

let task = URLSession.shared.dataTask(with: request as URLRequest) {
    data, response, error in
    if let error = error {
      print (error)
    } else {
      if let unwrappedData = data {
        // scrape, scrape, parse, parse
        matchRow = ...
        self.matches.append(matchRow)

        if matchRow.date == todaysDate {
          self.today.append(matchRow)
        } else if matchRow.date == tomorrowsDate {
          self.tomorrow.append(matchRow)
        }
      }

      DispatchQueue.main.async { [weak self] in
        self?.todayTableView.reloadData()
        self?.tomorrowTableView.reloadData()
      }

    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM