0

Below is my function in which I have highlighted the code that works (i.e. asynchronous), but what I want is the synchronous code with PFQuery.countObjects(error: NSErrorPointer) to work.

//Count how many violations User has.
func checkViolationStatus(usr: PFUser) -> Int32 {
    var violations: Int32 = 0
    var query = PFQuery(className: PF_BLOCKEDUSERS_CLASS_NAME)
    query.includeKey(PF_BLOCKEDUSERS_USER)
    query.whereKey(PF_BLOCKEDUSERS_USER, equalTo: usr)

    //THIS WORKS BUT IS ASYNCHRONOUS AND I WANT IT TO BE SYNCHRONOUS
    //        query.countObjectsInBackgroundWithBlock {
    //            (count: Int32, error: NSError?) -> Void in
    //            if error == nil {
    //                print("Sean has played \(count) games")
    //                violations = count
    //            }
    //        }

    //WANT TO MAKE IT SYNCHRONOUS -- THIS DOES NOT WORK
    violations = query.countObjects(<#T##error: NSErrorPointer##NSErrorPointer#>)

    return violations

}

How to use query.countObjects(...) correctly here?

user1406716
  • 9,565
  • 22
  • 96
  • 151
  • What's your design reason for wanting it to be synchronous? If there are a lot of objects and it ties up the main thread then it will obviously lead to poor performance. – pbush25 Oct 18 '15 at 23:23
  • this is a screen where this is the key information to be shown. I am guessing one of the errors I can get is a timeout. Also in general, I am having trouble with how to do synchronous reads from Parse so would like to understand the right syntax better. – user1406716 Oct 18 '15 at 23:25
  • @user1406716 what is the error that you receive? – Daniel Zhang Oct 18 '15 at 23:29
  • @DanielZhang no error but i dont know what to put for `<#T##error: NSErrorPointer##NSErrorPointer#>` above – user1406716 Oct 18 '15 at 23:32

2 Answers2

1

You should never network synchrously. It freezes the interface, and the WatchDog process will kill your app dead before the user's very eyes if that goes on for too long.

It would be better if you would learn how asynchronous code works and keep this asynchronous. You cannot return a value from the code that launches asynchronous code in the way that you are doing; your checkViolationStatus returns before the asynchronous code has a chance to set violations to anything. Instead, make checkViolationStatus take a PFUser and a completion handler that the caller passes you. Inside the asynchronous block, call the completion handler, handing it count.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • You are right, did some research and can use completion handler here. I will work on it. Sorry couldnt mark this as the answer, but did +1 it. – user1406716 Oct 18 '15 at 23:42
  • Thanks. You're quite right about the correct answer, which is explaining the error pointer syntax. – matt Oct 19 '15 at 00:35
  • I made an attempt at completion handlers, but the result is not as expected. Shouldn't the result in the calling function be triggered AFTER the asynchronous call is done? I opened a new issue: http://stackoverflow.com/questions/33205527/completion-handler-not-working-as-expected-in-swift – user1406716 Oct 19 '15 at 02:06
  • But you're making exactly the same mistake again. You are calling the completion handler outside the asynch block, which means that you are calling it before the asynch block ever runs. Try to wrap your head around what asynchronous means! My answer here is very specific: call the completion handler _inside the asynch block_! – matt Oct 19 '15 at 02:10
1

Here is the syntax for passing an NSError in countObjects along with code for printing the error should you receive one:

var error: NSError?
violations = query.countObjects(&error)

if error != nil {
    print(error?.localizedDescription)
}

Here is a little explanation to help you further understand that error type.

The NSErrorPointer type is essentially the same as NSError** in Objective-C and indicates that the address of an object, where it actually lives and not just the object’s pointer, is needed to fulfill the argument type. This is a common error-handling pattern in Objective-C.

The & operator allows you to pass such an address to a function. The argument that is passed in can than be modified instead of being limited to only the scope of the function. This is known as an in-out parameter in Swift terminology because what goes in also goes out.

Daniel Zhang
  • 5,778
  • 2
  • 23
  • 28