2012-10-05 2 views
2

J'utilise AFNetworking pour effectuer une requête Web. Une fois la requête Web terminée. Je veux qu'un UIAlertView soit montré. J'utilise ARC et le code semble fonctionner sur les appareils. Si j'utilise un simulateur, j'obtiens une erreur: EXC_BAD_ACCESSAffichage d'un UIAlertView provoque EXC_BAD_ACCESS

Qu'est-ce que je fais de mal?

UIAlertView* postSubmitAlertView = [[UIAlertView alloc] init]; 
postSubmitAlertView.delegate = self; 
[postSubmitAlertView addButtonWithTitle:@"Ok"]; 

AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] 
    initWithRequest:request]; 

[op setCompletionBlock:^(void) { 
    if(op.response.statusCode == 200) { 

     postSubmitAlertView.title = @"Submission Good"; 
     postSubmitAlertView.message = @"GOOD"; 

    } else { 

     postSubmitAlertView.title = @"Submission Failed."; 
     postSubmitAlertView.message = @"FAIL"; 
    } 

    [postSubmitAlertView show]; 
}]; 
[op start]; 

Répondre

4

Le problème principal est que UIKit doit être appelée sur le thread principal.

Note: For the most part, UIKit classes should be used only from an application’s main thread. This is particularly true for classes derived from UIResponder or that involve manipulating your application’s user interface in any way.

UIKit Framework Reference

En regardant les documents pour NSOperation sous setCompletionBlock:

Discussion The exact execution context for your completion block is not guaranteed but is typically a secondary thread. Therefore, you should not use this block to do any work that requires a very specific execution context. Instead, you should shunt that work to your application’s main thread or to the specific thread that is capable of doing it.

La solution la plus simple de modifier votre code est d'appeler les choses UIKit sur le thread principal

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSURL *URL = [NSURL URLWithString:@"http://www.google.com"]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 

    AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] 
           initWithRequest:request]; 

    [op setCompletionBlock:^(void) { 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     UIAlertView* postSubmitAlertView = [[UIAlertView alloc] init]; 
     postSubmitAlertView.delegate = self; 
     [postSubmitAlertView addButtonWithTitle:@"Ok"]; 

     if(op.response.statusCode == 200) { 

     postSubmitAlertView.title = @"Submission Good"; 
     postSubmitAlertView.message = @"GOOD"; 

     } else { 

     postSubmitAlertView.title = @"Submission Failed."; 
     postSubmitAlertView.message = @"FAIL"; 

     } 

     [postSubmitAlertView show]; 
    }); 

    }]; 
    [op start]; 
} 
+0

J'ai essayé la méthode ci-dessus et rien ne semble fonctionner dans le bloc d'achèvement. Y at-il autre chose que je pourrais essayer? – mmattax

+0

J'ai donné un exemple complet qui fonctionne bien pour moi ... –

+0

ah, j'ai oublié d'appeler dispatch_, fonctionne parfaitement! Merci. – mmattax

0
UIAlertView* postSubmitAlertView = [[UIAlertView alloc] init]; 
postSubmitAlertView.delegate = self; 
[postSubmitAlertView addButtonWithTitle:@"Ok"]; 

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request]; 
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 

     NSLog(@"success: %@", operation.responseString); 
     postSubmitAlertView.title = @"Submission Good"; 
     postSubmitAlertView.message = @"GOOD"; 

} 
    failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     NSLog(@"error: %@", operation.responseString); 
     postSubmitAlertView.title = @"Submission Failed."; 
     postSubmitAlertView.message = @"FAIL"; 

} 
]; 

[postSubmitAlertView show]; 

Espérons que cela résoudra votre problème.

1

Le EXC_BAD_ACCESS est provoquée par l'accès à un objet publié. Pour éviter cela faire appel à UIAlertView type modal:

//Function body: 

-(void)checkSaving 
{ 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Do you want to add these results to your database?" 
                message:@"\n\n" 
                delegate:self 
              cancelButtonTitle:@"No" 
              otherButtonTitles:@"Save", nil]; 
    alert.alertViewStyle = UIAlertViewStyleDefault; 
    [alert show]; 

    //this prevent the ARC to clean up : 
    NSRunLoop *rl = [NSRunLoop currentRunLoop]; 
    NSDate *d; 
    d = (NSDate*)[d init]; 
    while ([alert isVisible]) { 
     [rl runUntilDate:d]; 
    } 
} 

//Your choice result: 

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 
    // the user clicked one of the OK/Cancel buttons 
    if (buttonIndex == 1)//Save 
    { 
     //do something  
    } 
    if (buttonIndex == 0)//NO 
    { 
     //do something 
    } 
} 

//Register the functions in the interface declaration: 

@interface yourViewController() 
-(void)checkSaving 
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 
//... 
@end 


//To call: 

[self checkSaving]; 

Je souhaite que cela vous aidera.

+0

S'il vous plaît modifier votre réponse et formater le code pour le rendre lisible. – kleopatra

Questions connexes