2012-07-10 71 views
0

我發佈到REST風格的web服務並收到響應,如果我只返回一些記錄,這很有用,但是有一個閾值,didReceiveData停止被調用(6條記錄)和它只是掛起。 (無所謂記錄,只是號碼)NSURLConnection在特定條件下掛起

我似乎無法弄清楚爲什麼。我在didReceiveResponse中收到200 application/json的狀態消息:但是,這是我從連接中收到的最後一次消息。

從其他客戶端我可以得到任何數量的記錄的完整數據,所以它與我的NSURLConnection代碼有關。

查看完整的NSURLConnection下面的Post類。

的.H

#import <Foundation/Foundation.h> 
#import "MBProgressHUD.h" 

@protocol PostJsonDelegate <NSObject, NSURLConnectionDelegate> 
@optional 
- (void) downloadFinished; 
- (void) downloadReceivedData; 
- (void) dataDownloadFailed: (NSString *) reason; 
@end 

@interface PostURLJson : NSObject { 
    NSMutableData *receivedData; 
    int expectedLength; 
    MBProgressHUD *HUD; 
} 

@property (strong, nonatomic) NSMutableData *receivedData; 
@property (weak) id <PostJsonDelegate> delegate; 
@property (assign, nonatomic) int expectedLength; 

+ (id)initWithURL:(NSString *)url dictionary:(NSDictionary *)dictionary withDelegate:(id <PostJsonDelegate>)delegate; 

@end 

的.M

#import "PostURLJson.h" 
#define SAFE_PERFORM_WITH_ARG(THE_OBJECT, THE_SELECTOR, THE_ARG) (([THE_OBJECT respondsToSelector:THE_SELECTOR]) ? [THE_OBJECT performSelector:THE_SELECTOR withObject:THE_ARG] : nil) 

@implementation PostURLJson 

@synthesize delegate; 

@synthesize receivedData; 
@synthesize expectedLength; 

+ (id)initWithURL:(NSString *)url dictionary:(NSDictionary *)dictionary withDelegate:(id <PostJsonDelegate>)delegate 
{  
    if (!url) 
    { 
     NSLog(@"Error. No URL"); 
     return nil; 
    } 

    PostURLJson *postJson = [[self alloc] init]; 
    postJson.delegate = delegate; 

    [postJson loadWithURL:url dictionary:dictionary]; 

    return postJson; 
} 

- (void)loadWithURL:(NSString *)url dictionary:(NSDictionary *)dictionary 
{ 
    [self setExpectedLength:0]; 

    receivedData = [[NSMutableData alloc] init]; 

    NSError* error; 

    NSDictionary *tmp = [[NSDictionary alloc] initWithDictionary:dictionary]; 

    NSData *postdata = [NSJSONSerialization dataWithJSONObject:tmp options:0 error:&error]; 

    NSString *someString = [[NSString alloc] initWithData:postdata encoding:NSASCIIStringEncoding]; 
    NSLog(@"%@",someString); 

    NSString *postLength = [NSString stringWithFormat:@"%d", [postdata length]]; 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    [request setURL:[NSURL URLWithString:url]]; 
    [request setHTTPMethod:@"POST"]; 
    [request setTimeoutInterval:10.0f]; 

    [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
    [request setHTTPBody:postdata]; 

    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self]; 
    [connection start]; 
    [self setLoadingModeEnabled:YES]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *) response; 
    int errorCode = httpResponse.statusCode; 
    NSString *fileMIMEType = [[httpResponse MIMEType] lowercaseString]; 

    NSLog(@"%d",errorCode); 
    NSLog(@"%@",fileMIMEType); 

    [receivedData setLength:0]; 

    // Check for bad connection 
    expectedLength = [response expectedContentLength]; 
    if (expectedLength == NSURLResponseUnknownLength) 
    { 
     NSString *reason = [NSString stringWithFormat:@"Invalid URL"]; 
     SAFE_PERFORM_WITH_ARG(delegate, @selector(dataDownloadFailed:), reason); 
     [connection cancel]; 
     return; 
    } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [receivedData appendData:data]; 
    SAFE_PERFORM_WITH_ARG(delegate, @selector(downloadReceivedData), nil); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    SAFE_PERFORM_WITH_ARG(delegate, @selector(downloadFinished), nil); 
    [self setLoadingModeEnabled:NO]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog(@"Something went wrong..."); 
    HUD.labelText = @"Something went wrong..."; 
    [self performSelector:@selector(didFailHideHud) withObject:nil afterDelay:2]; 
} 

- (void)setLoadingModeEnabled:(BOOL)isLoading 
{ 
    //when network action, toggle network indicator and activity indicator 
    if (isLoading) { 
     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

     UIWindow *window = [UIApplication sharedApplication].keyWindow; 
     HUD = [[MBProgressHUD alloc] initWithWindow:window]; 
     [window addSubview:HUD]; 
     HUD.labelText = @"Loading"; 
     [HUD show:YES]; 
    } else { 
     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 

     [HUD hide:YES]; 
     [HUD removeFromSuperview]; 
    } 

} 

-(void)didFailHideHud 
{ 
    [HUD hide:YES]; 
    [HUD removeFromSuperview]; 
} 

@end 

編輯服務器具有一定規模的觸發NSURLResponseUnknownLength我有誤,沒有記錄,所以我之後沒有回饋的有效長度在控制檯中未收到「無效的URL」消息。

if (expectedLength == NSURLResponseUnknownLength) 
    { 
     NSString *reason = [NSString stringWithFormat:@"Invalid URL"]; 
     SAFE_PERFORM_WITH_ARG(delegate, @selector(dataDownloadFailed:), reason); 
     [connection cancel]; 
     return; 
    } 
+0

典型的超時間隔大約是60秒,當你增加你的時間會發生什麼? – 2012-07-10 15:33:01

+0

同樣的事情,實際上我設置了這麼短的超時時間來嘗試和調試這個問題。 – KDM 2012-07-10 15:38:54

+0

您是否訪問過connectionDidFinishLoading或didFailWithError? – Aymarick 2012-07-10 15:58:27

回答

0

試試這個:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 
[connection start]; 

因爲如果你運行在NSDefaultRunLoopMode的連接,並有UITableView的滾動,它將掛斷連接委託。

但是你的問題是不同的。某些服務器將限制來自單個客戶端的同時連接數量。如果你是這種情況,那麼第一次連接會成功,其他連接將掛起,直到以前的連接完成。