当我使用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];
}
}];