user3647675
user3647675

Reputation:

Dispatch async and ViewWillAppear

I am working on iOS application and came to one issue which is eating my time to understand. I can not put all source code here but I am trying to put which is related to issue.

 class MyItemsListVC: UIViewController, UITableViewDataSource,UITableViewDelegate {

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
    }


    func updateMyProductList() {

     //update data source array code here

      dispatch_async(dispatch_get_main_queue(), { () -> Void in
                productListTableView.reloadData()
      })


    } 
}

I have one parentViewController (UIViewController) of above class which holds object of his childViewController i.e MyItemsListVC object.

Based on some business logic when I call "updateMyProductList" method from parentViewController I get below method call sequence.

  1. Call to updateMyProductList from ParentViewController
  2. updateMyProductList get called
  3. "update data source array code here" from "updateMyProductList" method get called
  4. viewWillAppear get called

Here I am expecting after 3rd step, code inside "dispatch_async" block should get call which reloads table view. I am not sure why "viewWillAppear" get called. I am OK if "viewWillAppear" get called after "dispatch_async".

Here does dispatch_async(dispatch_get_main_queue() block code is having low priority over "viewWillAppear"? since both are in Main thread?

It will be really helpful if I get some hints to solve this.

Upvotes: 1

Views: 1106

Answers (3)

Chris
Chris

Reputation: 811

Your question is light on details, but it sounds like your asynchronous call is being returned after your viewWillAppear is called.

I would suggest moving your network code to a dedicated singleton class for handling all your network calls, then having your view load in such a way that it loads quickly and waits gracefully for new data (i.e. an activity indicator). Then when the new data returns you update the view.

Upvotes: 0

user7270881
user7270881

Reputation: 19

I have never written anything for iOS in that language, but from my experience I can tell you that updateMyProductList is called on the parent class not on yours, which obviously calls your viewWillAppear. :). I guess you must override updateMyProductList the same way:

override func updateMyProductList() {..}

I don't think you can get to the dispatch if your method is never called :). If it is executed after viewWillAppear you must sync them.

Upvotes: -1

Pang Ho Ming
Pang Ho Ming

Reputation: 1319

So hows the result right now? Which method call is not working? Can you specify?

My advise, you should create a separate class just for handling the data / api calls. Create a array for storing data in that class, set it to internal so that you can access the array in other classes. Here are some code snippet that you can read.

class APIManager : NSObject {
    static let sharedInstance = APIManager()
    typealias NerfireAPICompletionBlock = (_ value: AnyObject?, _ error: NSError?) -> Void
    internal var dataArray = Array()
    internal func callServerToFetchNewData(){
      //call api and store data to dataArray
       if error != nil {
            completion(nil, error as NSError?)
        } else {
            completion(true as AnyObject?, nil)
        }
    }
}

class MyItemsListVC: UIViewController, UITableViewDataSource,UITableViewDelegate {

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
    }

    func updateMyProductList(completion: @escaping NerfireAPICompletionBlock) {

     //update data source array code here

      APIManager.sharedInstance.callServerToFetchNewData(){ success, error -> Void in
         if error != nil {
            print(error?.description)
         } else {
           productListTableView.reloadData()
         }
      }
    } 
}

Upvotes: 0

Related Questions