Mamta
Mamta

Reputation: 921

'MBProgressHUD needs to be accessed on the main thread.' - Swift 3

I am getting 'MBProgressHUD needs to be accessed on the main thread.' error on hiding MBProgressHUD once page is loaded with data from web service. Please help me to solve this. Stuck on this issue since hours now. My code is :

                DispatchQueue.main.async {
                    self.spinnerActivity.hide(animated: true)
                    self.tableView.reloadData()
                    self.refreshControl.endRefreshing()
                }

I started the spinner in viewDidLoad as follows :

    spinnerActivity = MBProgressHUD.showAdded(to: self.view, animated: true);
    spinnerActivity.label.text = "Loading";
    spinnerActivity.detailsLabel.text = "Please Wait!!";

Please help.

Edit:

This is my whole code of that view controller :

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableView: UITableView!

var refreshControl: UIRefreshControl!
var spinnerActivity: MBProgressHUD! = nil

override func viewDidLoad() {
    super.viewDidLoad()

    refreshControl = UIRefreshControl()
    refreshControl.tintColor = UIColor.green
    refreshControl.attributedTitle = NSAttributedString(string: "Refreshing", attributes: [NSForegroundColorAttributeName: UIColor.white])
    refreshControl.addTarget(self, action: #selector(ViewController.refresh(sender:)), for: UIControlEvents.valueChanged)
    tableView.addSubview(refreshControl)

    spinnerActivity = MBProgressHUD.showAdded(to: self.view, animated: true);
    spinnerActivity.label.text = "Loading";
    spinnerActivity.detailsLabel.text = "Please Wait!!";

    self.navigationItem.hidesBackButton = true
    let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.back(sender:)))
    self.navigationItem.leftBarButtonItem = newBackButton

    navigationItem.title = city.uppercased()

    self.runWebService()
}

func runWebService(){


    let url = URL(string: "")!// have removed my url

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in // URLSession.shared().dataTask(with: url) { (data, response, error) is now URLSession.shared.dataTask(with: url) { (data, response, error)

        if error != nil {
            self.spinnerActivity.hide(animated: true)
            print(error)
        } else {
            if let urlContent = data {
                do {
                    guard let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as? [AnyObject] else {
                        self.spinnerActivity.hide(animated: true)
                        return
                    }
                    //processing web service
                    //DispatchQueue.global(qos: .userInitiated).async {
                    DispatchQueue.main.async {
                        self.spinnerActivity.hide(animated: true)
                        self.tableView.reloadData()
                        self.refreshControl.endRefreshing()
                    }
                } catch {
                    self.spinnerActivity.hide(animated: true)
                    print("JSON Processing Failed")
                }
            }
        }
    }
    task.resume()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func back(sender: UIBarButtonItem) {
    _ = navigationController?.popToRootViewController(animated: true)
}

func refresh(sender:AnyObject) {
    //pull to refresh
    self.runWebService()
}

//remaining are table view data source and delegate methods   }

Upvotes: 1

Views: 3713

Answers (1)

toddg
toddg

Reputation: 2916

You're trying to hide the MBProgressHUD from the background in all of your error handling. Switch over to the main thread to fix:

func runWebService(){

    let url = URL(string: "http://www.google.com")!// have removed my url

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in // URLSession.shared().dataTask(with: url) { (data, response, error) is now URLSession.shared.dataTask(with: url) { (data, response, error)

        if error != nil {
            DispatchQueue.main.async {
                self.spinnerActivity.hide(animated: true)
            }

            print(error)
        } else {
            if let urlContent = data {
                do {
                    guard let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as? [AnyObject] else {
                        DispatchQueue.main.async {
                            self.spinnerActivity.hide(animated: true)
                        }
                        return
                    }
                    //processing web service
                    //DispatchQueue.global(qos: .userInitiated).async {
                    DispatchQueue.main.async {
                        self.spinnerActivity.hide(animated: true)
                    }
                } catch {
                    DispatchQueue.main.async {
                        self.spinnerActivity.hide(animated: true)
                    }
                    print("JSON Processing Failed")
                }
            }
        }
    }
    task.resume()
}

** Note that I removed some of your code to test.

Upvotes: 2

Related Questions