Question

I have a code block for my NSURLConnection sendAsynchronousRequest, and when I try to set a UILabel's text, the text is never set, even though the values are there. Here's my code:

    NSString *address = [addresses objectAtIndex:indexPath.row];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://myurl.com/%@", address]]];
    [NSURLConnection sendAsynchronousRequest:urlRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if ([data length] > 0 && error == nil)
        {
            NSString *dataOfData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            if(![dataOfData isEqualToString:@"ERROR: address invalid"]) {
                [balanceLabel setText:[NSString stringWithFormat:@"Balance: %@", dataOfData]];
                if(data) {
                    qrCodeButton.alpha = 1;
                }
            } else {
                errorLabel.text = @"This address is invalid.";
            }
        }
        else if ([data length] == 0 && error == nil)
        {
            NSLog(@"Nothing was downloaded.");
            [balanceLabel setText:@"Server Error, Please Try Again"];
        }
        else if (error != nil){
            NSLog(@"Error = %@", error);
        }
    }];

Why is the UILabel's text never set? Is there a limitation to code blocks? If so, how would I fix my problem? Cheers!

Was it helpful?

Solution

It is because an NSOperationQueue is not the main thread. What you're doing is illegal. And the sad thing is that there is no need for it! Just say:

[NSURLConnection sendAsynchronousRequest:urlRequest 
     queue:[NSOperationQueue mainQueue]
     completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        // ... and the rest exactly as you have it now

All fixed. Your request is asynchronous on a background thread, but when it comes back to you on the completion handler, you'll be on the main thread and able to talk to the interface etc.

OTHER TIPS

Your code operates UI element should execute on main thread.

dispatch_async(dispatch_get_main_queue(), ^{
    if ([data length] > 0 && error == nil)
    {
        NSString *dataOfData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if(![dataOfData isEqualToString:@"ERROR: address invalid"]) {
            [balanceLabel setText:[NSString stringWithFormat:@"Balance: %@", dataOfData]];
            if(data) {
                qrCodeButton.alpha = 1;
            }
        } else {
            errorLabel.text = @"This address is invalid.";
        }
    }
    else if ([data length] == 0 && error == nil)
    {
        NSLog(@"Nothing was downloaded.");
        [balanceLabel setText:@"Server Error, Please Try Again"];
    }
    else if (error != nil){
        NSLog(@"Error = %@", error);
    }
}) ;

Make sure errorLabel is not nil and the UILabel is visible (It is added in the view hierarchy and its frame is appropriate).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top