ASIHTTPRequestTester: Asynchronous not working

2019-08-01 04:56发布

问题:

I'm trying to make a App for iOS using ASIHTTPRequest, but I'm facing some issues using it. To demonstrate my problems, I've uploaded an test-project, which you can download from here: http://uploads.demaweb.dk/ASIHTTPRequestTester.zip.

I've created a WebService class which use the ASIHTTPRequestDelegate protocol:

#import "WebService.h"
#import "ASIHTTPRequest.h"

@implementation WebService

- (void)requestFinished:(ASIHTTPRequest *)request {
    NSLog(@"requestFinished");
}
- (void)requestFailed:(ASIHTTPRequest *)request {
    NSLog(@"requestFailed");
}

- (void) testSynchronous {
    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    NSLog(@"starting Synchronous");
    [request startSynchronous];
    NSError *error = [request error];
    if (!error) {
        NSLog(@"got response");
    }
}

- (void) testAsynchronous {
    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];

    NSLog(@"starting Asynchronous");
    [request startAsynchronous];
}

@end

The synchronous method is working fine, but the asynchronous is not working at all. First the requestFinished and requestFailed was never called and right now I'm getting an EXC_BAD_ACCESS. The two test-methods is called from my ViewController's viewDidLoad. I hope someone can help me making this work.

EDIT1: As per this topic, it is possible because of the Automatic Reference Counting which is enabled for my project. The topic advice to add a [self retain], but I cannot do this with ARC turned on. Anyone with a solution for this?

EDIT2: Update as per answer from MrMage.

@interface ViewController()
@property (nonatomic,strong) WebService *ws;
@end

@implementation ViewController

@synthesize ws = _ws;

#pragma mark - View lifecycle
- (void)viewDidLoad
{
    [super viewDidLoad];

    [self setWs:[[WebService alloc] init]];
    [self.ws testSynchronous];
    [self.ws testAsynchronous];
}

@end

回答1:

You could add your WebService instance as a strong reference to an object that stays around for long enough (say your view controller), then tell that class to get rid of the WebService after it has done its job (i.e. in requestFinished and requestFailed you call back to the view controller, telling it to release the WebService instance).



回答2:

I got the same issue on delegation with ASIHTTPRequest and ARC.

I just end up using blocks to solve it.

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

//set request like this to avoid retain cycle on blocks
__weak ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

//if request succeeded
[request setCompletionBlock:^{        
    [self requestFinished:request];
}];

//if request failed
[request setFailedBlock:^{        
    [self requestFailed:request];
}];

[request startAsynchronous];