Konstantinos Natsios
Konstantinos Natsios

Reputation: 2924

Swift 2 functions completion

I am dealing with an issue here. I'm making a query (within a function) on a table in Parse and i get some objectids. I push them into an array.

In the ViewDidLoad i have the following order

override func viewDidLoad() {
        super.viewDidLoad()

    refreshControl = UIRefreshControl()
    refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
    refreshControl.addTarget(self, action: #selector(Images.refresh),   forControlEvents: UIControlEvents.ValueChanged)
    self.imagesCollView!.addSubview(refreshControl)
    queryLikes()  // it calls first the likes query
    queryImages("")  // and when the previous query has done, it should run this query.
}

and at cellForItemAtIndexPath I'm checking if the object id of the image is contained inside the array of the objectids and then change the background of a button from unliked to liked. All good till now but i also have a refresh function which is something like that

@IBAction func refreshButt(sender: AnyObject) {
    queryLikes()  //this first call to the query of likes table
    searchBar.text = ""
    categoryStr = ""
    queryImages("")  //and when the previous query is ready, it should run this query.
}

So when someone refresh the view with the button sometimes it loads the second query first and then the first one.

IS there any working example to show me how to make the queryLikes runs ALWAYS first and when it is completed to run the queryImages ??

Thanks a lot!

Upvotes: 0

Views: 125

Answers (2)

user6375148
user6375148

Reputation:

This is a much simpler way to handle the situation. But I would recommend the answer of Diogo Antunes rather than this approach, you can go with this if you are a beginner.

func queryLikes(completion: (success : Bool) -> ()) {
  // After putting your statements
  completion(success: true)
}

If you are dealing with any conditions inside the function, try this.

func queryLikes(completion: (success : Bool) -> ()) {

            if condition {
                completion(success: true)
            }
            else {
                completion(success: false)
            }
        }

Using a for loop inside the function.

func queryLikes(completion: (success : Bool) -> ()) {

            let objects : [Int] = []

            for object in 0..<objects.count
            {
                if object == objects.endIndex
                {
                    completion(success: true)
                }
            }
        }

Upvotes: 2

Diogo Antunes
Diogo Antunes

Reputation: 2291

You can achieve this by using callbacks and chaining the requests:

enum Result<T> {
    case Success(T)
    case Failure(NSError)
}


func queryLikes(completion: Result<Void> -> Void) {
    if networkCallSuccess() { completion(.Success()) }
    else { completion(.Failure(.Error)) }
}

queryLikes() { result in
    switch result {
    case .Success: queryImages()
    case .Failure(let error): // Handle error
    }

}

Upvotes: 3

Related Questions