0

I am new to multithreading and was wondering how I could run this function in the background? The function simply returns a NSURL that is used for XML parsing and is called from another function. Or is it even worth it to run in the background since the function that calls it does not continue until this function returns its NSURL. Basically, I am just trying to figure out how to speed this up because it is taking a little time to finish!

+ (NSURL *)parserURL {

    NSURL *theURL = [NSURL URLWithString:@"http://www.wccca.com/PITS/"];
    NSData *data = [[NSData alloc] initWithContentsOfURL:theURL];
    TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:data];
    NSArray *elements = [xpathParser searchWithXPathQuery:@"//input[@id='hidXMLID']//@value"];
    if (elements.count >= 1) {

        TFHppleElement *element = [elements objectAtIndex:0];
        TFHppleElement *child = [element.children objectAtIndex:0];
        NSString *idValue = [child content];

        NSString *stg = [NSString stringWithFormat:@"http://www.wccca.com/PITS/xml/fire_data_%@.xml", idValue];
        NSURL *url = [NSURL URLWithString:stg];

        return url;
    }
    return nil;
}
Mike Abdullah
  • 14,933
  • 2
  • 50
  • 75
Jon Erickson
  • 1,876
  • 4
  • 30
  • 73

1 Answers1

1

The main issue with your code is that you are using a blocking operation to get the data from the website. You definitely want to execute this in the background thread. However, I would recommend you to have a look at networking frameworks that help you do these kinds of operations very easily, i.e., AFNetworking,

In any case, the strategy that I would follow to multithread that operation, or a similar one is the following: It breaks down to dispatching it with GDC, and then executing a receiving completion block back in the main thread with the results.

Here is the code:

Description

First start by declaring your function to receive a block. The block will be executed in the end, once you've finished retrieving and parsing the data. The next thing the code does it asking GDC to execute a block of code in a background queue. When it is done, we ask the code to execute the completion block that was provided as parameter of the function in the main thread, supplying the parsed string to it.

+(void) parserURL:(NSURL *) theURL completion:(void (^) (NSURL *finalURL))completionBlock{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSData *data = [[NSData alloc] initWithContentsOfURL:theURL];
    TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:data];
    NSArray *elements = [xpathParser searchWithXPathQuery:@"//input[@id='hidXMLID']//@value"];
    NSURL *url;
    if (elements.count >= 1) {

        TFHppleElement *element = [elements objectAtIndex:0];
        TFHppleElement *child = [element.children objectAtIndex:0];
        NSString *idValue = [child content];

        NSString *stg = [NSString stringWithFormat:@"http://www.wccca.com/PITS/xml/fire_data_%@.xml", idValue];
        url = [NSURL URLWithString:stg];
    }else{
        url = nil;
    }
        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock(url);
        });
    });

}

You call the method the following way:

[URLParser parserURL:[NSURL URLWithString:@"http://www.wccca.com/PITS/"] completion:^(NSURL *finalURL) {
        NSLog(@"Parsed string %@", [finalURL absoluteString]);
    }];
Javier Quevedo
  • 2,066
  • 1
  • 17
  • 27