显示UIAlertView会导致EXC_BAD_ACCESS

时间:2012-10-05 20:41:10

标签: iphone objective-c ios uialertview afnetworking

我正在使用AFNetworking发出网络请求。 Web请求完成后。我想要显示UIAlertView。我正在使用ARC,代码似乎适用于设备。如果我使用模拟器,则会出现错误:EXC_BAD_ACCESS

我做错了什么?

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];

3 个答案:

答案 0 :(得分:4)

关键问题是应该在主线程上调用UIKit个东西。

  

注意:在大多数情况下,UIKit类只能从应用程序的主线程中使用。对于从UIResponder派生的类或者涉及以任何方式操纵应用程序的用户界面的类,尤其如此。

UIKit Framework Reference

查看setCompletionBlock:

NSOperation的文档
  

<强>讨论   您的完成块的确切执行上下文无法保证,但通常是辅助线程。因此,您不应该使用此块来执行任何需要非常特定的执行上下文的工作。相反,您应该将该工作分流到应用程序的主线程或能够执行此操作的特定线程。

修改代码的最简单方法是调用主线程上的UIKit内容

- (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];
}

答案 1 :(得分:1)

EXC_BAD_ACCESS是由访问已发布的对象引起的。为了避免这种情况,请调用UIAlertView类型的模式:

//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];

我希望这会对你有帮助。

答案 2 :(得分: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];

希望这能解决您的问题。