Home > Blockchain >  Asynchronous loading of URL in Objective C
Asynchronous loading of URL in Objective C

Time:10-09

My App loads a URL to a .txt file on my web server. I'm getting this warning:

Synchronous URL loading of https://(path to my text file)/nowplaying.txt should not occur on this application's main thread as it may lead to UI unresponsiveness. Please switch to an asynchronous networking API such as URLSession.

I can't find any examples to modify my code. Here's what I'm using now that generates the error.

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *stringURL = @"https://(path to my text file)/nowplaying.txt";
    NSURL  *url = [NSURL URLWithString:stringURL];
    NSData *urlData = [NSData dataWithContentsOfURL:url];
    NSString *dataString = [NSString stringWithUTF8String:[urlData bytes]];
    _lblNowPlaying.text = dataString;
}

CodePudding user response:

You want to use NSURLSession:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *stringURL = @"https://(path to my text file)/nowplaying.txt";
    NSURL *url = [NSURL URLWithString:stringURL];
    NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (data) {
            NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            dispatch_async(dispatch_get_main_queue(), ^{
                self.lblNowPlaying.text = string;
            });
        }
    }];

    [task resume];
}

Note, NSURLSession runs its completion handler on a background serial queue, so you have to dispatch the update of the label to the main queue.


It is probably prudent to add some error checking, to check for NSError object and to check the status code returned by the web server:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *stringURL = @"https://(path to my text file)/nowplaying.txt";
    NSURL *url = [NSURL URLWithString:stringURL];
    NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"%s error: %@", __FUNCTION__, error);
            return;
        }

        if (![response isKindOfClass:[NSHTTPURLResponse class]]) {
            NSLog(@"%s response: %@", __FUNCTION__, response);
            return;
        }

        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

        if (httpResponse.statusCode < 200 || httpResponse.statusCode >= 300) {
            NSLog(@"%s statusCode %ld; response: %@", __FUNCTION__, httpResponse.statusCode, response);
            return;
        }

        if (data) {
            NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            dispatch_async(dispatch_get_main_queue(), ^{
                self.lblNowPlaying.text = string;
            });
        }
    }];

    [task resume];
}

CodePudding user response:

You need to call the big calculation or long waiting time in Background Thread. When finishing, switch to Main (UI) Thread to update UI,...

Run a big calculation or synchronous long waiting on Main Thread (from Main Queue) will freeze the UI.

//Start the HUD here

__weak MyObject *weakSelf = self;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSString *stringURL = @"https://(path to my text file)/nowplaying.txt";
    NSURL  *url = [NSURL URLWithString:stringURL];
    NSData *urlData = [NSData dataWithContentsOfURL:url];
    NSString *dataString = [NSString stringWithUTF8String:[urlData bytes]];

    dispatch_async(dispatch_get_main_queue(), ^(void) {
         //stop your HUD here
         //This is run on the main thread

        weakSelf._lblNowPlaying.text = dataString;
    });
});

Ref: https://stackoverflow.com/a/27375273/17286292

  • Related