当前位置:数据库 > Access >>

ASIHTTPRequest的startAsynchronous调用EXC_BAD_ACCESS

一个简单的iOS应用,在主视图控制器类中,实现了ASIHTTPRequest的委托方法- (void)requestFinished:(ASIHTTPRequest *)request和- (void)requestFailed:(ASIHTTPRequest *)request。
在这个类的viewDidLoad方法中,调用ASIHTTPRequest的异步请求。
请求对象的定义为retain,如@property(retain)ASIHTTPRequest* theRequest;
在- (void)viewDidLoad方法中,调用的类中的方法是这个。
- (IBAction)showCheckcode:(id)sender {    
    NSString *imgURL=@"https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=sjrand";    
    self.theRequest=[ASIHTTPRequest requestWithURL:[NSURL URLWithString:imgURL]] ;    
    self.theRequest.accessibilityLabel=@"imgCode";    
    [self.theRequest setTag:100];    
    [self.theRequest setValidatesSecureCertificate:NO];    
    //[theRequest applyCookieHeader];    
    self.theRequest.delegate=(id<ASIHTTPRequestDelegate>)self;    
    [self.theRequest startAsynchronous];   
}
并且,在- (void)viewDidLoad方法中,又调用另外一个自定义类的方法,请求一个异步操作。而且这个类也实现了ASIHTTPRequest的委托方法。
应用一运行,就出现错误,在控制台中看到错误信息是EXC_BAD_ACCESS。
 
遇到问题第一个反应应该是,冷静。
虽然这个问题很麻烦,明显是和ASIHTTPRequest相关,而它是一个开源的框架,不是我所熟悉的。
ASIHTTPRequest的开发说不再维护它了,但ASIHTTPRequest也不失为一个非常好的网络访问框架,而且对于一般应用是足够的。ASIHTTPRequest是基于MRC下,我的应用是ARC下,所以在将ASIHTTPRequest拖进应用包时,需要做一个简单的调整。
1.选择target,然后选择Build Phases标签,展开Compile Sources;
2.在所有和ASI..相关的文件后面的(Compile Flags)加入编译选项”-fno-objc-arc”
 
对了,我的开发工具是XCODE4.5。这里补充一下。
 
分析一下ASIHTTPRequest的框架,将ASIHTTPRequestConfig.h文件中配置调试项打开,再运行下。
虽然应用还是crash,但这回错误停在ASIHTTPRequest.m中一个方法上。
 
(void)requestReceivedResponseHeaders:(NSMutableDictionary *)newResponseHeaders { 
  if ([self error] || [self mainRequest]) { return; }  
--> if (delegate && [delegate respondsToSelector:didReceiveResponseHeadersSelector]) {
 
问题出在delegate的设置上。
 
在stackoverflow.com上,有网友提出了两个解决方法。
 
第一个,使用同一的delegate,并且应用一运行就初始化它。如果其他类要调用异步请求,将delegate发过去。
调用方法如下:
- (void)sendUrl: (NSString *) restUrl withCallBack:(NSObject*) delegate;
然后,在delegate的实现方法中利用request的tag来标识来自哪一个类的异步调用。
 
 
第二个,使用block直接实现异步请求,抛弃delegate。
 
使用"setCompletionBlock:^"代替delegate的"setDidFinishSelector"。
 
request做一个设置就可以,比原来通过设置request.delegate再实现delegate的方法简单多了。
 
    [request setCompletionBlock :^{
        // 请求响应结束,返回 responseString
        NSString *responseString = [request responseString ]; // 对于 2 进制数据,使用 NSData 返回 NSData *responseData = [request responseData];
        NSLog ( @"%@" ,responseString);
    }];
    [request setFailedBlock :^{
        // 请求响应失败,返回错误信息
        NSError *error = [request error ];
        NSLog ( @"error:%@" ,[error userInfo ]);
    }];
    
可见第二个方法比第一个方便多了。在iOS5.0版本中,就可以使用block了。没想到block这么管用。   
 
  
问题解决,按照个人惯例,需要简单总结一下。
1、在ARC怎么调用以前MRC开发的开源框架;
2、framework怎么编译,真机和模拟机的差别,release版和debug版的差别。这点在文档中没有提及,但也做了尝试,虽然结果很失败。
3、多线程,ASIHTTPRequest的异步请求就是多线程调用。
4、NSOperationQueue的一些基础,但现在还不明白。
5、delegate的理解更透彻。
补充:移动开发 , IOS ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,