0

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;
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
Mick
  • 147
  • 9
  • 2
    `dataWithContentsOfURL` should only be used to fetch data from a local file. You will need to use something like [`NSURLSessionDataTask`](https://developer.apple.com/documentation/foundation/nsurlsessiondatatask) – Paulw11 Oct 09 '22 at 03:55

1 Answers1

4

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];
    if (!url) {
        NSLog(@"%s URL error: %@", __FUNCTION__, stringURL);
        return;
    }

    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];
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044