4

I am having some difficulty with an asynchronous data fetch from a server (MySQL database which I access through some PHP web services). My code is below:

func RetreiveStaff() {
    SetProgramMode()

    self.astrUsers = [String]()
    self.pkvUser.reloadAllComponents()

    if self.booCurrentDataVersion == true {

        var url:NSURL = NSURL(string: "http://www.website.com.au/retrievestaff.php")!
        let task:NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
            if error == nil {
                let dataArray:[AnyObject] = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! [AnyObject]
                for data in dataArray {
                    let dictionary:[String:String] = data as! [String:String]
                    if dictionary["StaffID"] != nil {
                        self.astrUsers.append(dictionary["LastName"]! + ", " + dictionary["FirstName"]!)
                        self.astrUserIDs.append(dictionary["StaffID"]!)
                        self.pkvUser.reloadAllComponents()
                    }
                    self.pkvUser.reloadAllComponents()
                }
            } else {
                let actionSheet:UIAlertController = UIAlertController(title: "Connection Error", message: "\(strAppName) was unable to load data.  Check you are connected to the internet and restart the app.", preferredStyle: UIAlertControllerStyle.Alert)
                let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {
                    (alertAction:UIAlertAction!) in
                })
                actionSheet.addAction(firstAlertAction)
                self.presentViewController(actionSheet, animated: true, completion: nil)
            }
        })

        task.resume()

    }
}

When the code executes, the data is fetched as it should, but the view doesn't display it. Basically, as you can see, I grab the data, put it in an array and then reload my pickerView (which uses the array as its datasource). The pickerView remains visibly empty for about 20 seconds after the code is executed, and then suddenly appears. However, if the user taps on, drags, changes the value of, etc. the pickerView during the 20 seconds, the data appears.

From my understanding of the problem, this means that the data is being fetched and put into the pickerView but the view isn't reloading correctly, despite my numerous and probably excessive number of self.pkvUser.reloadAllComponents().

What am I doing wrong?

(I have also checked out these questions but they haven't solved the issue:

Swift: Asynchronous callback
Asynchronous Fetching Swift Xcode
iOS Swift: Displaying asynchronous data on a TableView )

Community
  • 1
  • 1
Matt Kelly
  • 1,451
  • 2
  • 13
  • 30

1 Answers1

3

displaying any view in IOS should ALWAYS be in the main thread.

when you are doing async requests, push the results to the user's view from main thread like this:

 var someView : UIView  = someAsyncCallBack..
 dispatch_async(dispatch_get_main_queue()) {
    currentView.addSubview(someView);
 }

try this code, after the async request is done, there's no problem to handle the response in the main queue, this also solves the display lag

if error == nil {
    dispatch_async(dispatch_get_main_queue()) {
        let dataArray:[AnyObject] = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! [AnyObject]
        for data in dataArray {
            let dictionary:[String:String] = data as! [String:String]
            if dictionary["StaffID"] != nil {
                self.astrUsers.append(dictionary["LastName"]! + ", " + dictionary["FirstName"]!)
                self.astrUserIDs.append(dictionary["StaffID"]!)
                self.pkvUser.reloadAllComponents()
            }
            self.pkvUser.reloadAllComponents()
        }
    }
}
Daniel Krom
  • 9,751
  • 3
  • 43
  • 44