提问人:LordGrim 提问时间:1/25/2023 更新时间:1/25/2023 访问量:2167
必须在主线程上进行调用,我可以获取数据,但是当我希望它显示错误消息时,它会崩溃
Call must be made on main thread i can get the data but when i want it to show error message it crashes
问:
StartScreenVC
import UIKit
class StartScreenVC: UIViewController {
private var apiService = ApiService()
override func viewDidLoad() {
super.viewDidLoad()
loadPopularMoviesData()
}
private func loadPopularMoviesData() {
apiService.getPopularMoviesData { [weak self] (result) in
switch result {
case .success(let listOf):
print(result)
case .failure(let error):
self?.showAlertWith(title: "Could not connect!", message: "Plese check your internet connection \n or try again later")
print("Error processing json data: \(error)")
}
}
}
// MARK: - Show Alert
func showAlertWith(title: String, message: String, style: UIAlertController.Style = .alert) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: style)
let action = UIAlertAction(title: "OK", style: .default) { (action) in
self.dismiss(animated: true, completion: nil)
}
alertController.addAction(action)
self.present(alertController, animated: true, completion: nil)
}
}
Api服务
import Foundation
class ApiService {
private var dataTask: URLSessionDataTask?
// MARK: - Get popular movies data
func getPopularMoviesData(completion: @escaping (Result<MovieData, Error>) -> Void) {
let popularMoviesURL = "https://api.themoviedb.org/3/movie/popular?api_key=4e0be2c22f7268edffde97481d49064a&language=en-US&page=1"
guard let url = URL(string: popularMoviesURL) else {return}
// Create URL Session - work on the background
dataTask = URLSession.shared.dataTask(with: url) { (data, response, error) in
// Handle Error
if let error = error {
completion(.failure(error))
print("DataTask error: \(error.localizedDescription)")
return
}
guard let response = response as? HTTPURLResponse else {
// Handle Empty Response
print("Empty Response")
return
}
print("Response status code: \(response.statusCode)")
guard let data = data else {
// Hndle Empty Data
print("Empty Data")
return
}
do {
// Parse the data
let decoder = JSONDecoder()
let jsonData = try decoder.decode(MovieData.self, from: data)
// Back to the main thread
DispatchQueue.main.async {
completion(.success(jsonData))
}
} catch let error {
completion(.failure(error))
}
}
dataTask?.resume()
}
我收到的错误“必须在主线程上进行调用”
我获取数据没有任何问题,但我想给出错误的应用程序崩溃了。
dispatchQueue 部分是否存在错误?
为什么我在这里收到错误?
我想做的是在互联网被切断或 api 没有响应时毫无问题地将错误消息带到屏幕上。
答:
1赞
jacksoor
1/25/2023
#1
看看你的,有两个调用不会发生在主线程上,特别是在失败的情况下。尝试将它们也包裹起来,看看它是否有效。ApiService
completion
DispatchQueue.main
在我看来,确保视图控制器代码在主线程上运行不应该是的责任。更可靠的方法是将完成代码包装在:ApiService
DispatchQueue.main
private func loadPopularMoviesData() {
apiService.getPopularMoviesData { [weak self] (result) in
DispatchQueue.main.async {
switch result {
case .success(let listOf):
print(result)
case .failure(let error):
self?.showAlertWith(title: "Could not connect!", message: "Plese check your internet connection \n or try again later")
print("Error processing json data: \(error)")
}
}
}
}
评论
0赞
LordGrim
1/25/2023
谢谢杰克,你的回答奏效了,我明白了。感谢您的漂亮而简单的解释。
评论