Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 570
Noah Dyer Avatar asked Feb 24 '13 21:02

Noah Dyer


1 Answers

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.

like image 167
Richard Brown Avatar answered Nov 06 '22 13:11

Richard Brown