Swift中viewDidLoad内数组count始终返回0的问题求助
解决Swift中异步网络请求后数组count在viewDidLoad中为0的问题
Hey there! I see exactly what's going on here—this is a classic asynchronous operation timing issue. Let's break it down and fix it step by step.
问题原因
Your initialization function uses URLSession.dataTask, which runs asynchronously in the background. That means when your viewDidLoad runs:
- You call
initialization, but the network request starts immediately in the background and doesn't block the rest of the code. - The line
print(days.count)runs right away, before the network request finishes andself.days = downloadDays.listgets executed. Sodaysis still an empty array at that point. - The
completedclosure you pass in only runs after the network request succeeds anddaysis populated, which is whyprint(self.days.count)inside it works correctly.
修复方案
Here's how to adjust your code to handle this properly:
- Move table view updates to the completion closure: You need to reload your table view only after the data is ready, so it can display the new content.
- Fix duplicate delegate setup: You accidentally set
tableView.delegate = selftwice—we'll clean that up. - Set the table view data source: You're missing
tableView.dataSource = self(you'll also need to conform toUITableViewDataSourceto implement required methods).
修改后的完整代码
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // Add UITableViewDataSource conformance // Object array for weather var objectArray = [WeaObject]() var days = [List]() @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Setup table view delegates once tableView.delegate = self tableView.dataSource = self initialization { [weak self] in // Use [weak self] to avoid retain cycles print("success") print(self?.days.count ?? 0) // Reload table view now that data is ready self?.tableView.reloadData() } // This print will still show 0, and that's expected! print("Early days count (before network request finishes): \(days.count)") } func initialization(completed:@escaping () -> ()){ let jsonUrlString="http://api.openweathermap.org/data/2.5/forecast?zip=22003&appid=c632597b1892b4d415c64ca0e9fca1f1" guard let url = URL(string: jsonUrlString) else { return } URLSession.shared.dataTask(with: url) { [weak self] (data, response, err) in // Add [weak self] here too guard let data = data else { return } do { let downloadDays = try JSONDecoder().decode(TestingClass.self, from: data) self?.days = downloadDays.list DispatchQueue.main.async { completed() } } catch let jsonErr { print("Error serializing json:", jsonErr) } }.resume() } // MARK: - UITableViewDataSource Required Methods func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return days.count // Now this will return the correct count after data loads } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier", for: indexPath) // Configure your cell using days[indexPath.row] return cell } }
额外注意事项
- Retain Cycles: I added
[weak self]in both the dataTask closure and thecompletedclosure to prevent memory leaks. Always use weak references when self is captured in asynchronous closures. - Error Handling: Right now, if the network request fails, your
completedclosure never runs. You might want to add a failure case to handle errors gracefully (e.g., show an alert to the user).
内容的提问来源于stack exchange,提问作者Benjamin So
相关产品推荐
相关产品推荐

