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=@";
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的理解更透徹。
參考資料:http://stackoverflow.com/questions/5701132/asihttprequest-crashes-my-app
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!