为什么NSURLSession在没有必要时似乎超时?

时间:2015-12-22 10:33:48

标签: ios objective-c iphone nsurlsession

当我使用NSURLConnection执行restAPI请求时,一切都很好。既然NSURLSession在这里且NSURLConnection已弃用,我决定实施NSURLSession。我真的很喜欢使用它,但是每隔4-5次,我就会在API次出现我的应用程序时将请求发送到我的令牌页面。此页面是一个非常简单的php页面,它为我提供了一个json正文,其中包含访问令牌,刷新令牌和刷新间隔。我尝试使用browser执行请求,但它从未超时。我也尝试再次使用NSURLConnection,这也永远不会超时。与NSURLSession有什么不同之处在于它无法处理简单的请求?

这是我的代码:

static BOOL logCallbacks = NO;

static NSString* authUrl = @"****";
static NSString* apiUrl = @"****";

static NSURLSession *session;
static NSString* apiKey = @"****";
static NSString* apiSecret = @"****";

static NSString* accessToken = @"";
static NSString* refreshToken = @"";

static NSMutableDictionary* taskCompletionHandlerMap;
static NSMutableDictionary* taskBuffer;

@implementation APIclient

#pragma mark -
#pragma mark helpers

- (NSURLSession*) session {

    if (!taskCompletionHandlerMap) {
        taskCompletionHandlerMap = [[NSMutableDictionary alloc] init];
        taskBuffer = [[NSMutableDictionary alloc] init];
    }

    if (!session) {
        NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
        sessionConfig.allowsCellularAccess = YES;
        sessionConfig.timeoutIntervalForRequest = 30.0;
        sessionConfig.timeoutIntervalForResource = 60.0;
        sessionConfig.HTTPMaximumConnectionsPerHost = 1;

        session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
    }

    return session;
}

- (NSMutableURLRequest*) baseRequestUsingUrl:(NSString*)url {

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

    [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request addValue:@"application/json" forHTTPHeaderField:@"Accept"];

    [request addValue:[NSString stringWithFormat:@"bearer %@", accessToken] forHTTPHeaderField:@"authorization"];

    return request;
}

- (NSData*) jsonFromDictionary:(NSDictionary*)dictionary {
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
    if (! jsonData) {
        NSLog(@"Got an error: %@", error);
    } else {
        return [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] dataUsingEncoding:NSUTF8StringEncoding];
    }

    return nil;
}

- (void) InitAPIByUsername:(NSString*)username password:(NSString*)password completionHandler:
    (void (^)(NSDictionary* json))completionHandler {

    NSMutableURLRequest *request = [self baseRequestUsingUrl:authUrl];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[NSJSONSerialization dataWithJSONObject:[[NSDictionary alloc] initWithObjects:@[username,     password,       @"password",    apiKey,         apiSecret]
                                                                                               forKeys:@[@"username",  @"password",    @"grant_type",  @"client_id",   @"client_secret"]]
                                                         options:0
                                                           error:nil]];

    NSURLSessionTask* task = [[self session] dataTaskWithRequest:request];
    [taskCompletionHandlerMap setObject:completionHandler forKey:task];
    task.taskDescription = @"auth";
    [task resume];
}


#pragma mark -
#pragma mark callbacks

- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error {
    if (logCallbacks || error) NSLog(@"%s -> error: %@", __FUNCTION__, error);
}

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:
    (void (^)(NSURLRequest * __nullable))completionHandler {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:
    (void (^)(NSInputStream * __nullable bodyStream))completionHandler {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error {
    if (logCallbacks || error) NSLog(@"%s -> error: %@", __FUNCTION__, error);

    if ([taskCompletionHandlerMap objectForKey:task] && [taskBuffer objectForKey:task]) {
        NSDictionary* json = [NSJSONSerialization JSONObjectWithData:[taskBuffer objectForKey:task] options:0 error:nil];
        [taskBuffer removeObjectForKey:task];

        if (json) {
            if ([task.taskDescription isEqualToString:@"auth"]) {
                accessToken = [[json objectForKey:@"value"] objectForKey:@"access_token"];
                refreshToken = [[json objectForKey:@"value"] objectForKey:@"refresh_token"];
            }

            void (^ completionHandler)(NSDictionary*) = [taskCompletionHandlerMap objectForKey:task];
            [taskCompletionHandlerMap removeObjectForKey:task];
            completionHandler(json);
        }
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:
    (void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);

    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);

    if ([taskBuffer objectForKey:dataTask]) {
        NSMutableData* d = [[NSMutableData alloc] initWithData:[taskBuffer objectForKey:dataTask]];
        [d appendData:data];
        [taskBuffer setObject:d forKey:dataTask];
    } else {
        [taskBuffer setObject:data forKey:dataTask];
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:
    (void (^)(NSCachedURLResponse * __nullable cachedResponse))completionHandler {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);

    completionHandler(proposedResponse);
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
    if (logCallbacks) NSLog(@"%s", __FUNCTION__);
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:
    (void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {

    if (logCallbacks) NSLog(@"%s", __FUNCTION__);

    if (challenge.previousFailureCount == 0) {
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
    } else {
        NSLog(@"challenge error: %@", challenge.error);
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:
    (void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {

    if (logCallbacks) NSLog(@"%s", __FUNCTION__);

    if (challenge.previousFailureCount == 0) {
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
    } else {
        NSLog(@"challenge error: %@", challenge.error);
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
}

@end

然后我使用以下内容获取我的令牌:

[APP InitAPIByUsername:self.txt_username.text password:self.txt_password.text completionHandler:^(NSDictionary* json) {

    if (!json || [[json objectForKey:@"value"] objectForKey:@"error"]) {
        [self APIRequest:@"init_api" onError:json];
    } else {
        [self onInitAPIComplete:json];
    }
}];

0 个答案:

没有答案