Noah Dyer
Noah Dyer

Reputation: 407

UIAlertView doesn't work in completion handler block

I'm writing code to gain access to a users Twitter account, but am having trouble handling the case where no accounts are on the device. What I'd like to do is display an alert telling the user that in order to authenticate with Twitter, they'll first need to create the account in their settings.

Here's my code:

self.accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountTypeTwitter = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

[self.accountStore requestAccessToAccountsWithType:accountTypeTwitter options:nil completion:^(BOOL granted, NSError *error) {
    if(granted) {
        //Doesn't matter for the present case
    } else if (error){

        [SVProgressHUD dismiss]; //not directly relevant to the present question, but it also doesn't work within the block, so I'm leaving it as a clue

        switch ([error code]){
            case (6):

                UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"No Twitter Account Detected" message:@"Please go into your device's settings menu to add your Twitter account." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show]; //triggers an error
                break;

        }
    } 
}];

I'm no expert with the Xcode debugger, but apparently the error is occurring in the ACAccountStoreReply thread, about 25 calls deep after [alert show] is called, in a process called ucol_getVersion. Debugger states EXC_BAD_ACCESS(code=2, address=0xcc).

I've searched on Stack Overflow and the internet at large for solutions regarding UIAlertViews not working in blocks, and also for general problems showing alerts (I've tried different values for the delegate), and also for general problems with calls to requestAccessToAccountsWithType.

I've also attempted to brush up on my understanding of blocks by reading various online resources, and the relevant pages of Programming in Objective-C, 4th addition.

Any help is appreciated.

Upvotes: 6

Views: 2829

Answers (1)

Richard Brown
Richard Brown

Reputation: 11436

You should always make sure any UI interaction is done on the main thread. Wrap your UIAlertView call in a dispatch_async:

dispatch_async(dispatch_get_main_queue(), ^{
   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No Twitter Account Detected" message:@"Please go into your device's settings menu to add your Twitter account." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
   [alert show];
});

You also had two nils at the end of the call.

Upvotes: 22

Related Questions