[英]Call must be made on main thread i can get the data but when i want it to show error message it crashes
StartScreenVC启动屏幕VC
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)
}
}
ApiService接口服务
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()
}
The error I got 'Call must be made on main thread'我得到的错误“必须在主线程上进行调用”
I'm getting the data without any problems, but the application I want to give an error crashes.我正在毫无问题地获取数据,但我想给出错误的应用程序崩溃了。
Is there a bug in the dispatchQueue parts? dispatchQueue 部分有错误吗?
Why am I getting an error here?为什么我会在这里出错?
What I want to do is bring the error message to the screen without any problems, when the inte.net is cut off or the api is not responding.当 inte.net 被切断或 api 没有响应时,我想要做的是将错误消息毫无问题地显示在屏幕上。
Looking at your ApiService
there are two calls to completion
which do not happen on the main thread, specifically in the failure cases.查看您的ApiService
有两个completion
调用不会发生在主线程上,特别是在失败情况下。 Try wrapping them in DispatchQueue.main
as well and see if it works.尝试将它们也包装在DispatchQueue.main
中,看看它是否有效。
In my opinion, it should not be the responsibility of the ApiService
to make sure your view controller code runs on the main thread.在我看来,确保您的视图 controller 代码在主线程上运行不应该是ApiService
的责任。 A more solid approach would be to wrap completion code in DispatchQueue.main
:更可靠的方法是将完成代码包装在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)")
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.