0

I've found quite a lot of posts related to this topic, nevertheless I might keep doing something wrong...

After creating query, an instance of PFQuery, the request is implemented as query.findObjects() (runs on a background thread). During that request I'm not able to cancel its process like I would expect from the method query.cancel().

Scenario: Internet connection is missing, query.findObjects() tries to connect, fails, tries again. I implemented query.cancel() that is executed when the request first fails (in the if objects == nil that is executed at the mentioned point), still it is going for a second try. After the second try - each of those take around 15 seconds - has failed, it doesn't trigger a third.

Why does this happen, why is the process not interrupted when calling query.cancel()?

Thanks for any help!

EDIT 1: Some code

func getPost() {

    let queue = dispatch_queue_create("SerialBgQueue", DISPATCH_QUEUE_SERIAL)

    dispatch_async(queue, {

        var query = PFQuery(className: "Post")

        var objects = query.findObjects()

        if objects != nil {

            // do something

        } else {

            println("This part is executed now")

            // doesn't stop the ongoing (second) connection attempt:
            query.cancel()

           // do something

            return
        }
    })
}

EDIT 2: That's the logs - to me it looks like a second bundle of attempts, check the logs (attempt 2, 3, 4, ... then starting again 2, 3, 4, ...). The else {-part is executed once in between and a second time in the very end. After that, everything has stopped, no more "attempts".

2014-10-08 13:37:10.104 Instagram[9210:391955] Error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo=0x7fe708c545c0 {NSUnderlyingError=0x7fe708c53020 "The Internet connection appears to be offline.", NSErrorFailingURLStringKey=https://api.parse.com/2/find, NSErrorFailingURLKey=https://api.parse.com/2/find, _kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, NSLocalizedDescription=The Internet connection appears to be offline.} (Code: 100, Version: 1.3.0)

2014-10-08 13:37:10.105 Instagram[9210:391952] Network connection failed. Making attempt 2 after sleeping for 1.092226 seconds.

2014-10-08 13:37:11.311 ... (Code: 100, Version: 1.3.0) // same Error like in the very first line

2014-10-08 13:37:11.312 Instagram[9210:391945] Network connection failed. Making attempt 3 after sleeping for 2.184451 seconds.

2014-10-08 13:37:13.704 ... (Code: 100, Version: 1.3.0) 

2014-10-08 13:37:13.704 Instagram[9210:391952] Network connection failed. Making attempt 4 after sleeping for 4.368902 seconds.

2014-10-08 13:37:18.514 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:18.514 Instagram[9210:391952] Network connection failed. Making attempt 5 after sleeping for 8.737804 seconds.

2014-10-08 13:37:27.257 ... (Code: 100, Version: 1.3.0)

This part is executed now

2014-10-08 13:37:27.265 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:27.266 Instagram[9210:392183] Network connection failed. Making attempt 2 after sleeping for 1.387503 seconds.

2014-10-08 13:37:28.792 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:28.793 Instagram[9210:392202] Network connection failed. Making attempt 3 after sleeping for 2.775006 seconds.

2014-10-08 13:37:31.843 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:31.844 Instagram[9210:392205] Network connection failed. Making attempt 4 after sleeping for 5.550011 seconds.

2014-10-08 13:37:37.401 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:37.401 Instagram[9210:392202] Network connection failed. Making attempt 5 after sleeping for 11.100023 seconds.

2014-10-08 13:37:49.050 ... (Code: 100, Version: 1.3.0)

This part is executed now
alexeis
  • 2,152
  • 4
  • 23
  • 30
  • What do you mean by "(second) connection attempt"? Is there another query after `query`? – Khanh Nguyen Oct 07 '14 at 23:24
  • @KhanhNguyen Check Edit 2 – alexeis Oct 08 '14 at 11:48
  • You can't cancel it. The best you can do is to set a `_isCancelled` flag somewhere after a certain amount of time, and use an `if` to ignore the results if it is set. – Khanh Nguyen Oct 08 '14 at 20:29
  • What's the logical reason not being able to cancel it? Any other way of breaking that process? A flag doesn't help in that case - its about stoping the any (query) process. After the first fail I alert the user about it. But if it actually doesn't stop, a built-in refresh button (occasionally tapped again by the user) has no affect. That could be solved in a way of having no affect as long as a query is still active, but then some alerts that depend on the state/duration of the connection trial are getting mixed up and have a completely wrong timing what would totally confuse the user. – alexeis Oct 08 '14 at 22:35

1 Answers1

1

I think your assumption about findObjects() is incorrect. That variety blocks the thread on which it was started (your background thread in the posted case), and it returns upon success or failure. There's nothing to cancel at the point in your code when you call cancel.

The typical cancel pattern is when the code starts the query on a different thread, then decides that it needs to cancel, like this (in Objective-C... sorry)

PFQuery *query = [PFQuery queryWithClassName:@"Post"];    
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    // this block might get called more than once, depending on the cache policy
    // but it will be called with an error only once and stop after that
    // (no second attempt that I know about) so as far as I can tell, there's
    // no reason to ever call cancel here.
}];

Say you don't want the query to take any longer than 10 seconds. Then...

[query performSelector:@selector(cancel) withObject:nil afterDelay:10.0];
danh
  • 62,181
  • 10
  • 95
  • 136
  • I have to keep the `findObjects()` since some more code is coming afterwards that needs to wait for the query to be completed but cannot be written within the `...inBackgroundWithBlock`-part (at least at my current experience level). I'll take your input anyway and keep trying. Maybe my EDIT 2 with the logs gives some further information on what's happening. – alexeis Oct 08 '14 at 11:59
  • Where would I have to implement the performSelector within my example so it has the desired effect? – alexeis Oct 08 '14 at 22:39
  • performSelector would make sense if you used the ...inBackgroundWithBlock variety of find, and then you could place that line right before of after it. If parse really blocks this background thread while its retrying, you could keep a flag and cancel the iOS thread. See e.g. here http://stackoverflow.com/questions/10066897/objective-c-cancel-a-dispatch-queue-using-ui-event – danh Oct 08 '14 at 23:04
  • 1
    I think you should try to use the background variety of find. It will really simplify things. And I bet I can help you work out how to run something in the completion block. If you want, give that a try and post a different SO question. Leave me a link to it here. (see this from an old parse forum https://parse.com/questions/error-handling-when-network-connection-fails) – danh Oct 08 '14 at 23:07
  • Actually I'd like to give it a try, right! I just want to point out what the difficulty is: Within my table cells I have to resize an image so it fits the width of the screen and also knows its adapted height. So a method is calculating the aspect ratio needed and the resulting height. That's needed to set the cell's height correctly using auto-layout. After lots of trial-and-error the only bug-free variety was to ensure that the cell-configuration waits for the whole cell content to be fully prepared before start creating cells. That was difficult to accomplish with such background-processes. – alexeis Oct 09 '14 at 12:27
  • The `cellForRowAtIndexPath` includes the `customCell.setPostedImage(image)` that calls the method within the custom cell class. It calculates aspect/ratio and height and manually set the new constraints to auto-layout. The problem is that this cannot be done as long as the image is not fully loaded/ready. That's why I put everything "in order". I don't see through all this but before, when cells got already configured before the image was ready (and then had to reload again), the table had some "bugs" with white spaces, missing and jumping cells... Do you think there's another solution? – alexeis Oct 09 '14 at 12:44