How do display a UIAlertView from a block on iOS?

2019-07-11 04:23发布

What is the best way of displaying a UIAlertView from a block?

I have the following action in my code :

- (IBAction)connectWithTwitterClicked:(id)sender {
    ACAccountStore * account = [[ACAccountStore alloc]init];
    ACAccountType * accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

    [account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
        if (granted == YES){
            NSLog(@"Twitter account has been granted");
            NSArray * arrayOfAccounts = [account accountsWithAccountType:accountType];
            if([arrayOfAccounts count] > 0){
                ACAccount * twitterAccount = [arrayOfAccounts lastObject];
                NSLog(@"Found twitter Id of [%@]", twitterAccount.username);
                // continue on to use the twitter Id
            } else {
                // no twitter accounts found, display alert to notify user
            }
        } else{
            NSLog(@"No twitter accounts have been granted");
            // no twitter accounts found, display alert to notify user
        }
    }];
}

I've tried these solutions so far :

  1. On either of the 2 commented lines, directly create and show a UIAlertView, this crashes the application, I believe this is due to the block being an asynchronous process and not having access to the UI thread to display the alert
  2. Created an NSMutableString outside the block, marked it with __block, set it on the commented lines and then displayed after. Similar problem here whereby the block is run asynchronously so at the time of displaying the alert theres no guarantee the NSMutableString has been set.

Can anyone suggest a solution? I want to be able to notify the user somehow so they can either not use twitter, or to go off and setup an account in the device settings.

Thanks

2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-07-11 04:32

This is the GCD way to do it:

[SomeClass dispatchNastyAsyncBlock:^{
    // ... do stuff, then
    dispatch_async(dispatch_get_main_queue(), ^ {
        [[[[UIAlertView alloc] initWithTitle:t
                                     message:nil
                                    delegate:nil
                           cancelButtonTitle:@"OK"
                           otherButtonTitles:nil
        ] autorelease] show];
    });
}];
查看更多
男人必须洒脱
3楼-- · 2019-07-11 04:39

Create a method that shows the alert view, then perform its selector on the main thread:

- (void)showAlertWithTitle:(NSString *)t
{
    [[[[UIAlertView alloc] initWithTitle:t
                                 message:nil
                                delegate:nil
                       cancelButtonTitle:@"OK"
                       otherButtonTitles:nil
    ] autorelease] show];
}

Call it as follows:

[SomeClass dispatchNastyAsyncBlock:^{
    // ... do stuff, then
    [self performSelectorOnMainThread:@selector(showAlertWithTitle:)
                           withObject:@"Here comes the title"
                        waitUntilDone:YES];
}];
查看更多
登录 后发表回答