IOS, terminate the function when you press the back button

The app is made up of navigation views. I am calling a function in viewDidAppear which

[self extractInfoWithWebsite:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];

      

This function parses HTML from the current web page on the Internet. The code takes a long time to share, but the idea is that it fetches data from a website.

The problem is that if the user decides to click on the navigation back button before that information is loaded, the page will remain the same and the app will stop functioning (not crash, but become static, doesn't do it anymore).

Is there a solution? Thank you in advance

EDIT:

I changed the code to the following: NSOperationQueue * queue = [NSOperationQueue new];

    /* Create our NSInvocationOperation to call loadDataWithOperation, passing in nil */
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                            selector:@selector(extractInfoWithWebsite:)
                                                                              object:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];

    /* Add the operation to the queue */
    [queue addOperation:operation];
    [operation release];

      

Now I can hit the back button without hanging, but now it crashes with the following error: Tried to get the weblock from a stream other than the main stream or web stream. This could be the result of calling UIKit from a secondary thread. Crashing now ... I guess it's because my function is still running in the background. How to solve this problem?

+3


source to share


4 answers


I would look at NSOperation

The standard approach inside NSOperations is to check if they have been canceled before doing the heavy processing.

Here is a good link to start your research.



EDIT: I thought I would clarify the canceled part

NSOperations have main () and inner main (), it is good practice to do something like

NSData* chunkyReply = nil;

if (!self.isCancelled) {
    chunkyReply = [NSURL stuff];
}    


if (!self.isCancelled) {
    //parse chunkyReply
}

      

+2


source


You can run the download code in the background using:

    [self performSelectorInBackground:<#(SEL)#> withObject:<#(id)#>];

      



And then you have control of the back button pressed and you can grab it.

0


source


There are different approaches that work best for me, encapsulating the process inside an NSOperation that you create in the ViewDidLoad and stop in the ViewWillDisappear.

Another approach is to create an object with a delegate and then set the delegate to nil when the controller exits.

0


source


It's hard to give you a better answer without knowing exactly what it looks like extractInfoWithWebsite:

, but I'm going to assume it's broken down into two parts:

  • Get data from the url you are passing.
  • Parse this data

In the first part, if you use [NSData dataWithContentsOfURL:...]

or [NSURLConnection sendSynchronoushRequest:returningResponse:error:]

, you need to change them. Neither of these two URL fetch methods will allow you to cancel the request. Apple has good documentation on how to use asynchronous cancellation methods.

The next step is the parsing that you perform on the data that you retrieve. If you are not getting the order in megabytes from the internet, your parsing probably shouldn't be canceled. However, you have to do the heavy lifting on a background thread:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //perform parsing
    dispatch_async(dispatch_get_main_queue(), ^{
        if (!self.view.window)
            return; //won't update UI if we've moved offscreen
        //call methods to update the UI
    });
});

      

This will cause parsing in the default priority background queue and refreshing the UI (any text fields, etc.) in the main queue after parsing.

Yes, that doesn't override, but as I said, unless you are processing a lot of data, it is probably safe not to encapsulate the parsing in an NSOperation. You will spend a little time on the processor, but I'll try this approach first, and if the performance isn't where you need it, move on to NSOperation

later. There is no point in early optimization if you don't need it.

0


source







All Articles