views:

628

answers:

4

I have no problem to run the sample code below in a iPhone simulator, but when I run it in a iPhone , I always get a EXC_BAD_ACCESS when I call [asiRequest cancel]. anyone can help? thanks.

ASIHTTPRequest *asiRequest;

-(IBAction)request1{
    NSLog(@"request starting");
    [self sendRequest];
}
-(IBAction)cancel1{
    NSLog(@"request caceling");
    if(asiRequest)
        [asiRequest cancel];

}

-(void)sendRequest{
    asiRequest=[ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://maps.google.com/"]];
    [asiRequest setDelegate:self];
    [asiRequest startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    NSLog(@"requestFinished");
    asiRequest=nil;
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
    NSLog(@"request Error=%@",[request error]);
    asiRequest=nil;
}
+3  A: 

You need to retain your ASIHTTPRequest. Because the request was autoreleased via the use of a convenience constructor, you must retain it for it to stick around passed the end of the current run loop.

In addition, do note that you don't need to check if asiRequest is not nil in cancel1:: sending a message to nil does nothing, and has no adverse effects.

chpwn
Thanks chpwn...
owen
You could always click the checkmark to accept the answer :p.
chpwn
A: 

I thought ASIHTTPRequest will retain it for asynchronous request, because this problem doesn't happen when running in the simulator.

anyway, I have changed the code by following your suggestion but I still get the same problem.

If I comment out the two release in requestFailed and requestFinished, there is no EXE_BAD_ACCESS. So if I need to retain the request object, where shall I release it?

some logs might help

2010-01-25 13:24:04.540 TestWebView[151:207] request starting
2010-01-25 13:24:06.014 TestWebView[151:207] requestFinished
2010-01-25 13:24:07.898 TestWebView[151:207] request starting
2010-01-25 13:24:09.296 TestWebView[151:207] requestFinished
2010-01-25 13:24:16.294 TestWebView[151:207] request caceling
2010-01-25 13:24:18.342 TestWebView[151:207] request caceling
2010-01-25 13:24:21.261 TestWebView[151:207] request starting
2010-01-25 13:24:21.613 TestWebView[151:207] request caceling
2010-01-25 13:24:21.643 TestWebView[151:207] request Error=Error Domain=ASIHTTPRequestErrorDomain Code=4 UserInfo=0x13c2b0 "The request was cancelled"
Program received signal:  “EXC_BAD_ACCESS”.

also, thanks for the nil tips

-(IBAction)request1{
 NSLog(@"request starting");
 [self sendRequest];
}
-(IBAction)cancel1{
 NSLog(@"request caceling");
 [asiRequest cancel];
}

-(void)sendRequest{

 asiRequest=[[ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://maps.google.com/"]] retain];
 [asiRequest setDelegate:self];
 [asiRequest startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
 NSLog(@"requestFinished");
 [asiRequest release];
 asiRequest=nil;
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
 NSLog(@"request Error=%@",[request error]);
 [asiRequest release];
 asiRequest=nil;
}
owen
A: 

After checking the api, I think I shouldn't release it in requestFinished or requestFailed

by how can I release it when it finishs?

- (void)cancel
{
    #if DEBUG_REQUEST_STATUS
    NSLog(@"Request cancelled: %@",self);
    #endif
    [[self cancelledLock] lock];

    if ([self isCancelled] || [self complete]) {
        [[self cancelledLock] unlock];
        return;
    }

    [self failWithError:ASIRequestCancelledError];
    [self setComplete:YES];
    [self cancelLoad];
    [[self cancelledLock] unlock];

    // Must tell the operation to cancel after we unlock, as this request might be dealloced and then NSLock will log an error
    [super cancel];
}
owen
A: 

I changed my code again

it works fine now, I think the only thing I need to worry about is I need release the request somethere when requestFailed happens unexpectedly

-(IBAction)request1{
    NSLog(@"request starting");
    [self sendRequest];
}
-(IBAction)cancel1{
    NSLog(@"request caceling");
    if(asiRequest){
        [asiRequest cancel];
        [asiRequest release];
        asiRequest=nil;
    }
}

-(void)sendRequest{

    asiRequest=[[ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://maps.google.com/"]] retain];
    [asiRequest setDelegate:self];
    [asiRequest startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    NSLog(@"requestFinished");
    [asiRequest release];
    asiRequest=nil;
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
    NSLog(@"request Error=%@",[request error]);
}
owen
I have solved this problem , just release asiRequest in requestFinished when it is successful and don't release it in requestFailed, release it in somewhere else.
owen