简体   繁体   English

必须在主线程上进行调用我可以获得数据但是当我希望它显示错误消息时它崩溃了

[英]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.

相关问题 我收到此错误 [UITextView insertText:] 必须仅从主线程使用 - 我该如何解决? - I am getting this error [UITextView insertText:] must be used from main thread only - How can I resolve it? 我可以从后台线程调用或运行 Core Data Main Context (viewContext) 吗? - Can I call or run Core Data Main Context (viewContext) from a background thread? 我可以调用 semaphore.wait() 主线程吗? - can I call on semaphore.wait() main thread? 我可以在 Swift 中使用演员来始终在主线程上调用 function 吗? - Can I use actors in Swift to always call a function on the main thread? 我想将服务中的数据写入文本字段,但出现错误。 UITextField.text 只能在主线程中使用 - I want to write data from a service to a text field, but the error appears! UITextField.text should be used only from the main thread UIView.init() 只能在主线程中使用(当我转到这个控制器时) - UIView.init() must be used from main thread only (when i segue to this controller) 解析XML时显示错误消息 - I show an error message when I parse XML 从 API 检索数据以在 arrays 中使用它们时,如何摆脱“必须从主线程调用 API 方法”问题? Swift - how to get rid of the 'The API method must be called from the main thread' problem when retrieving data from an API to use them in arrays? Swift 当我删除 DispatchQueue.main.async 时,我没有收到任何错误 - When i remove DispatchQueue.main.async I get no error iOS更改UI时应从主线程调用什么? - iOS What should I call from the main thread when changing UI?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM