diff --git a/.travis.yml b/.travis.yml index 15c6111..59d59bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,3 +3,7 @@ xcode_project: QiniuSDK.xcodeproj xcode_scheme: QiniuSDKTests xcode_sdk: - iphonesimulator7.1 +before_install: + - brew update + - brew upgrade xctool + - gem install cocoapods diff --git a/CHANGELOG.md b/CHANGELOG.md index 48b58c9..f93cc3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## CHANGE LOG +### v6.3.3 + +- [#101] 升级AFNetworking + ### v6.3.2 - [#94] 上传进度指示调整 diff --git a/QiniuSDK/AFNetworking/AFHTTPRequestOperation.m b/QiniuSDK/AFNetworking/AFHTTPRequestOperation.m index 723a3b3..1de5812 100644 --- a/QiniuSDK/AFNetworking/AFHTTPRequestOperation.m +++ b/QiniuSDK/AFNetworking/AFHTTPRequestOperation.m @@ -168,7 +168,7 @@ - (void)pause { self.request = mutableURLRequest; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; @@ -194,7 +194,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { - AFHTTPRequestOperation *operation = [[[self class] allocWithZone:zone] initWithRequest:self.request]; + AFHTTPRequestOperation *operation = [super copyWithZone:zone]; operation.responseSerializer = [self.responseSerializer copyWithZone:zone]; operation.completionQueue = self.completionQueue; diff --git a/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.h b/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.h index d7f6d42..9f39029 100644 --- a/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.h +++ b/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.h @@ -75,12 +75,12 @@ Network reachability status and change monitoring is available through the `reachabilityManager` property. Applications may choose to monitor network reachability conditions in order to prevent or suspend any outbound requests. See `AFNetworkReachabilityManager` for more details. - ## NSecureCoding & NSCopying Caveats + ## NSSecureCoding & NSCopying Caveats - `AFHTTPRequestOperationManager` conforms to the `NSecureCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. There are a few minor caveats to keep in mind, however: + `AFHTTPRequestOperationManager` conforms to the `NSSecureCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. There are a few minor caveats to keep in mind, however: - Archives and copies of HTTP clients will be initialized with an empty operation queue. - - NSecureCoding cannot serialize / deserialize block properties, so an archive of an HTTP client will not include any reachability callback block that may be set. + - NSSecureCoding cannot serialize / deserialize block properties, so an archive of an HTTP client will not include any reachability callback block that may be set. */ @interface AFHTTPRequestOperationManager : NSObject diff --git a/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.m b/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.m index 03116cc..4ae7275 100644 --- a/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.m +++ b/QiniuSDK/AFNetworking/AFHTTPRequestOperationManager.m @@ -213,7 +213,7 @@ - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.operationQueue]; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; diff --git a/QiniuSDK/AFNetworking/AFHTTPSessionManager.m b/QiniuSDK/AFNetworking/AFHTTPSessionManager.m index 5abfe7e..6413297 100644 --- a/QiniuSDK/AFNetworking/AFHTTPSessionManager.m +++ b/QiniuSDK/AFNetworking/AFHTTPSessionManager.m @@ -109,23 +109,11 @@ - (NSURLSessionDataTask *)GET:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; + NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure]; - __block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { - if (error) { - if (failure) { - failure(task, error); - } - } else { - if (success) { - success(task, responseObject); - } - } - }]; + [dataTask resume]; - [task resume]; - - return task; + return dataTask; } - (NSURLSessionDataTask *)HEAD:(NSString *)URLString @@ -133,23 +121,15 @@ - (NSURLSessionDataTask *)HEAD:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"HEAD" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - - __block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id __unused responseObject, NSError *error) { - if (error) { - if (failure) { - failure(task, error); - } - } else { - if (success) { - success(task); - } + NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters success:^(NSURLSessionDataTask *task, __unused id responseObject) { + if (success) { + success(task); } - }]; + } failure:failure]; - [task resume]; + [dataTask resume]; - return task; + return dataTask; } - (NSURLSessionDataTask *)POST:(NSString *)URLString @@ -157,23 +137,11 @@ - (NSURLSessionDataTask *)POST:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - - __block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { - if (error) { - if (failure) { - failure(task, error); - } - } else { - if (success) { - success(task, responseObject); - } - } - }]; + NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters success:success failure:failure]; - [task resume]; + [dataTask resume]; - return task; + return dataTask; } - (NSURLSessionDataTask *)POST:(NSString *)URLString @@ -182,7 +150,20 @@ - (NSURLSessionDataTask *)POST:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil]; + NSError *serializationError = nil; + NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; + if (serializationError) { + if (failure) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu" + dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ + failure(nil, serializationError); + }); +#pragma clang diagnostic pop + } + + return nil; + } __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { @@ -206,23 +187,11 @@ - (NSURLSessionDataTask *)PUT:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PUT" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; + NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters success:success failure:failure]; - __block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { - if (error) { - if (failure) { - failure(task, error); - } - } else { - if (success) { - success(task, responseObject); - } - } - }]; + [dataTask resume]; - [task resume]; - - return task; + return dataTask; } - (NSURLSessionDataTask *)PATCH:(NSString *)URLString @@ -230,23 +199,11 @@ - (NSURLSessionDataTask *)PATCH:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PATCH" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - - __block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { - if (error) { - if (failure) { - failure(task, error); - } - } else { - if (success) { - success(task, responseObject); - } - } - }]; + NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters success:success failure:failure]; - [task resume]; + [dataTask resume]; - return task; + return dataTask; } - (NSURLSessionDataTask *)DELETE:(NSString *)URLString @@ -254,23 +211,48 @@ - (NSURLSessionDataTask *)DELETE:(NSString *)URLString success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"DELETE" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; + NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters success:success failure:failure]; + + [dataTask resume]; + + return dataTask; +} + +- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method + URLString:(NSString *)URLString + parameters:(id)parameters + success:(void (^)(NSURLSessionDataTask *, id))success + failure:(void (^)(NSURLSessionDataTask *, NSError *))failure +{ + NSError *serializationError = nil; + NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; + if (serializationError) { + if (failure) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu" + dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ + failure(nil, serializationError); + }); +#pragma clang diagnostic pop + } + + return nil; + } - __block NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { + __block NSURLSessionDataTask *dataTask = nil; + dataTask = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { if (failure) { - failure(task, error); + failure(dataTask, error); } } else { if (success) { - success(task, responseObject); + success(dataTask, responseObject); } } }]; - [task resume]; - - return task; + return dataTask; } #pragma mark - NSObject @@ -279,7 +261,7 @@ - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue]; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; @@ -291,7 +273,7 @@ - (id)initWithCoder:(NSCoder *)decoder { if (!configuration) { NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"]; if (configurationIdentifier) { -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100) +#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100) configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier]; #else configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier]; diff --git a/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.h b/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.h index 6320783..5e610d8 100644 --- a/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.h +++ b/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.h @@ -23,12 +23,6 @@ #import #import -#import -#import -#import -#import -#import - typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusUnknown = -1, AFNetworkReachabilityStatusNotReachable = 0, @@ -88,11 +82,11 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { /** Creates and returns a network reachability manager for the socket address. - @param address The socket address used to evaluate network reachability. + @param address The socket address (`sockaddr_in`) used to evaluate network reachability. @return An initialized network reachability manager, actively monitoring the specified socket address. */ -+ (instancetype)managerForAddress:(const struct sockaddr_in *)address; ++ (instancetype)managerForAddress:(const void *)address; /** Initializes an instance of a network reachability manager from the specified reachability object. diff --git a/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.m b/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.m index 71adaef..1da1482 100644 --- a/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.m +++ b/QiniuSDK/AFNetworking/AFNetworkReachabilityManager.m @@ -22,6 +22,12 @@ #import "AFNetworkReachabilityManager.h" +#import +#import +#import +#import +#import + NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; @@ -128,7 +134,7 @@ + (instancetype)managerForDomain:(NSString *)domain { return manager; } -+ (instancetype)managerForAddress:(const struct sockaddr_in *)address { ++ (instancetype)managerForAddress:(const void *)address { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; diff --git a/QiniuSDK/AFNetworking/AFURLConnectionOperation.m b/QiniuSDK/AFNetworking/AFURLConnectionOperation.m index e5e6839..d8b55e3 100644 --- a/QiniuSDK/AFNetworking/AFURLConnectionOperation.m +++ b/QiniuSDK/AFNetworking/AFURLConnectionOperation.m @@ -339,7 +339,6 @@ - (void)pause { } [self.lock lock]; - if ([self isExecuting]) { [self performSelector:@selector(operationDidPause) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]]; @@ -350,7 +349,6 @@ - (void)pause { } self.state = AFOperationPausedState; - [self.lock unlock]; } @@ -466,6 +464,7 @@ - (void)operationDidStart { [self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode]; } + [self.outputStream open]; [self.connection start]; } [self.lock unlock]; @@ -642,8 +641,6 @@ - (void)connection:(NSURLConnection __unused *)connection didReceiveResponse:(NSURLResponse *)response { self.response = response; - - [self.outputStream open]; } - (void)connection:(NSURLConnection __unused *)connection @@ -726,7 +723,7 @@ - (NSCachedURLResponse *)connection:(NSURLConnection *)connection } } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; diff --git a/QiniuSDK/AFNetworking/AFURLRequestSerialization.h b/QiniuSDK/AFNetworking/AFURLRequestSerialization.h index 161b551..17a4e49 100644 --- a/QiniuSDK/AFNetworking/AFURLRequestSerialization.h +++ b/QiniuSDK/AFNetworking/AFURLRequestSerialization.h @@ -135,6 +135,15 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field; +/** + Returns the value for the HTTP headers set in the request serializer. + + @param field The HTTP header to retrieve the default value for + + @return The value set as default for the specified header, or `nil` + */ +- (NSString *)valueForHTTPHeaderField:(NSString *)field; + /** Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. @@ -334,7 +343,7 @@ forHTTPHeaderField:(NSString *)field; Appends HTTP headers, followed by the encoded data and the multipart form boundary. @param headers The HTTP headers to be appended to the form data. - @param body The data to be encoded and appended to the form data. + @param body The data to be encoded and appended to the form data. This parameter must not be `nil`. */ - (void)appendPartWithHeaders:(NSDictionary *)headers body:(NSData *)body; diff --git a/QiniuSDK/AFNetworking/AFURLRequestSerialization.m b/QiniuSDK/AFNetworking/AFURLRequestSerialization.m index 45df7a0..aea41d9 100644 --- a/QiniuSDK/AFNetworking/AFURLRequestSerialization.m +++ b/QiniuSDK/AFNetworking/AFURLRequestSerialization.m @@ -169,7 +169,20 @@ - (NSMutableURLRequest *)requestByFinalizingMultipartFormData; #pragma mark - +static NSArray * AFHTTPRequestSerializerObservedKeyPaths() { + static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))]; + }); + + return _AFHTTPRequestSerializerObservedKeyPaths; +} + +static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerObserverContext; + @interface AFHTTPRequestSerializer () +@property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders; @property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle; @property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization; @@ -188,12 +201,6 @@ - (instancetype)init { } self.stringEncoding = NSUTF8StringEncoding; - self.allowsCellularAccess = YES; - self.cachePolicy = NSURLRequestUseProtocolCachePolicy; - self.HTTPShouldHandleCookies = YES; - self.HTTPShouldUsePipelining = NO; - self.networkServiceType = NSURLNetworkServiceTypeDefault; - self.timeoutInterval = 60; self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary]; @@ -229,20 +236,39 @@ - (instancetype)init { // HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil]; + self.mutableObservedChangedKeyPaths = [NSMutableSet set]; + for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { + [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext]; + } + return self; } +- (void)dealloc { + for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { + [self removeObserver:self forKeyPath:keyPath context:AFHTTPRequestSerializerObserverContext]; + } +} + #pragma mark - - (NSDictionary *)HTTPRequestHeaders { return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders]; } -- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field { +- (void)setValue:(NSString *)value +forHTTPHeaderField:(NSString *)field +{ [self.mutableHTTPRequestHeaders setValue:value forKey:field]; } -- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username password:(NSString *)password { +- (NSString *)valueForHTTPHeaderField:(NSString *)field { + return [self.mutableHTTPRequestHeaders valueForKey:field]; +} + +- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username + password:(NSString *)password +{ NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", username, password]; [self setValue:[NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)] forHTTPHeaderField:@"Authorization"]; } @@ -289,12 +315,12 @@ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url]; mutableRequest.HTTPMethod = method; - mutableRequest.allowsCellularAccess = self.allowsCellularAccess; - mutableRequest.cachePolicy = self.cachePolicy; - mutableRequest.HTTPShouldHandleCookies = self.HTTPShouldHandleCookies; - mutableRequest.HTTPShouldUsePipelining = self.HTTPShouldUsePipelining; - mutableRequest.networkServiceType = self.networkServiceType; - mutableRequest.timeoutInterval = self.timeoutInterval; + + for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { + if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) { + [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath]; + } + } mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy]; @@ -422,7 +448,16 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request if (parameters) { NSString *query = nil; if (self.queryStringSerialization) { - query = self.queryStringSerialization(request, parameters, error); + NSError *serializationError; + query = self.queryStringSerialization(request, parameters, &serializationError); + + if (serializationError) { + if (error) { + *error = serializationError; + } + + return nil; + } } else { switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: @@ -435,8 +470,7 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; } else { if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { - NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding)); - [mutableRequest setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"]; + [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } @@ -445,7 +479,23 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request return mutableRequest; } -#pragma mark - NSecureCoding +#pragma mark - NSKeyValueObserving + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(__unused id)object + change:(NSDictionary *)change + context:(void *)context +{ + if (context == AFHTTPRequestSerializerObserverContext) { + if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) { + [self.mutableObservedChangedKeyPaths removeObject:keyPath]; + } else { + [self.mutableObservedChangedKeyPaths addObject:keyPath]; + } + } +} + +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; @@ -650,7 +700,6 @@ - (void)appendPartWithInputStream:(NSInputStream *)inputStream [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"]; [mutableHeaders setValue:mimeType forKey:@"Content-Type"]; - AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init]; bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = mutableHeaders; @@ -747,6 +796,9 @@ @interface AFMultipartBodyStream () @implementation AFMultipartBodyStream #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wimplicit-atomic-properties" +#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100) +@synthesize delegate; +#endif @synthesize streamStatus; @synthesize streamError; #pragma clang diagnostic pop @@ -957,6 +1009,8 @@ - (NSInputStream *)inputStream { _inputStream = [NSInputStream inputStreamWithURL:self.body]; } else if ([self.body isKindOfClass:[NSInputStream class]]) { _inputStream = self.body; + } else { + _inputStream = [NSInputStream inputStreamWithData:[NSData data]]; } } @@ -1124,7 +1178,7 @@ - (id)copyWithZone:(NSZone *)zone { @implementation AFJSONRequestSerializer + (instancetype)serializer { - return [self serializerWithWritingOptions:0]; + return [self serializerWithWritingOptions:(NSJSONWritingOptions)0]; } + (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions @@ -1167,7 +1221,7 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request return mutableRequest; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; @@ -1247,7 +1301,7 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request return mutableRequest; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; diff --git a/QiniuSDK/AFNetworking/AFURLResponseSerialization.h b/QiniuSDK/AFNetworking/AFURLResponseSerialization.h index 36ed33e..ed1204c 100644 --- a/QiniuSDK/AFNetworking/AFURLResponseSerialization.h +++ b/QiniuSDK/AFNetworking/AFURLResponseSerialization.h @@ -285,10 +285,18 @@ extern NSString * const AFURLResponseSerializationErrorDomain; These keys may exist in the user info dictionary, in addition to those defined for NSError. - `NSString * const AFNetworkingOperationFailingURLResponseErrorKey` + - `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey` ### Constants `AFNetworkingOperationFailingURLResponseErrorKey` The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. + + `AFNetworkingOperationFailingURLResponseDataErrorKey` + The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. */ extern NSString * const AFNetworkingOperationFailingURLResponseErrorKey; + +extern NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; + + diff --git a/QiniuSDK/AFNetworking/AFURLResponseSerialization.m b/QiniuSDK/AFNetworking/AFURLResponseSerialization.m index cc1e00b..7b042f7 100644 --- a/QiniuSDK/AFNetworking/AFURLResponseSerialization.m +++ b/QiniuSDK/AFNetworking/AFURLResponseSerialization.m @@ -30,6 +30,7 @@ NSString * const AFURLResponseSerializationErrorDomain = @"com.alamofire.error.serialization.response"; NSString * const AFNetworkingOperationFailingURLResponseErrorKey = @"com.alamofire.serialization.response.error.response"; +NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey = @"com.alamofire.serialization.response.error.data"; static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) { if (!error) { @@ -113,26 +114,33 @@ - (BOOL)validateResponse:(NSHTTPURLResponse *)response if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) { if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]]) { if ([data length] > 0) { - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]], - NSURLErrorFailingURLErrorKey:[response URL], - AFNetworkingOperationFailingURLResponseErrorKey: response - }; + NSMutableDictionary *mutableUserInfo = [@{ + NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]], + NSURLErrorFailingURLErrorKey:[response URL], + AFNetworkingOperationFailingURLResponseErrorKey: response, + } mutableCopy]; + if (data) { + mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data; + } - validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo], validationError); + validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError); } responseIsValid = NO; } if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode]) { - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode], - NSURLErrorFailingURLErrorKey:[response URL], - AFNetworkingOperationFailingURLResponseErrorKey: response - }; + NSMutableDictionary *mutableUserInfo = [@{ + NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode], + NSURLErrorFailingURLErrorKey:[response URL], + AFNetworkingOperationFailingURLResponseErrorKey: response, + } mutableCopy]; - validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo], validationError); + if (data) { + mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data; + } + + validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError); responseIsValid = NO; } @@ -156,7 +164,7 @@ - (id)responseObjectForResponse:(NSURLResponse *)response return data; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; @@ -196,7 +204,7 @@ - (id)copyWithZone:(NSZone *)zone { @implementation AFJSONResponseSerializer + (instancetype)serializer { - return [self serializerWithReadingOptions:0]; + return [self serializerWithReadingOptions:(NSJSONReadingOptions)0]; } + (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions { @@ -256,8 +264,8 @@ - (id)responseObjectForResponse:(NSURLResponse *)response } } else { NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", nil, @"AFNetworking"), - NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", nil, @"AFNetworking"), responseString] + NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", @"AFNetworking", nil), + NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", @"AFNetworking", nil), responseString] }; serializationError = [NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo]; @@ -270,13 +278,13 @@ - (id)responseObjectForResponse:(NSURLResponse *)response } if (error) { - *error = AFErrorWithUnderlyingError(serializationError, *error);; + *error = AFErrorWithUnderlyingError(serializationError, *error); } return responseObject; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; @@ -285,6 +293,7 @@ - (id)initWithCoder:(NSCoder *)decoder { } self.readingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readingOptions))] unsignedIntegerValue]; + self.removesKeysWithNullValues = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))] boolValue]; return self; } @@ -293,6 +302,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; [coder encodeObject:@(self.readingOptions) forKey:NSStringFromSelector(@selector(readingOptions))]; + [coder encodeObject:@(self.removesKeysWithNullValues) forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))]; } #pragma mark - NSCopying @@ -300,6 +310,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { - (id)copyWithZone:(NSZone *)zone { AFJSONResponseSerializer *serializer = [[[self class] allocWithZone:zone] init]; serializer.readingOptions = self.readingOptions; + serializer.removesKeysWithNullValues = self.removesKeysWithNullValues; return serializer; } @@ -394,7 +405,7 @@ - (id)responseObjectForResponse:(NSURLResponse *)response return document; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; @@ -481,7 +492,7 @@ - (id)responseObjectForResponse:(NSURLResponse *)response return responseObject; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; @@ -580,6 +591,8 @@ - (id)copyWithZone:(NSZone *)zone { if (colorSpaceModel == kCGColorSpaceModelRGB) { uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wassign-enum" if (alpha == kCGImageAlphaNone) { bitmapInfo &= ~kCGBitmapAlphaInfoMask; bitmapInfo |= kCGImageAlphaNoneSkipFirst; @@ -587,6 +600,7 @@ - (id)copyWithZone:(NSZone *)zone { bitmapInfo &= ~kCGBitmapAlphaInfoMask; bitmapInfo |= kCGImageAlphaPremultipliedFirst; } +#pragma clang diagnostic pop } CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); @@ -662,7 +676,7 @@ - (id)responseObjectForResponse:(NSURLResponse *)response return nil; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; @@ -748,7 +762,7 @@ - (id)responseObjectForResponse:(NSURLResponse *)response return [super responseObjectForResponse:response data:data error:error]; } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; diff --git a/QiniuSDK/AFNetworking/AFURLSessionManager.h b/QiniuSDK/AFNetworking/AFURLSessionManager.h index 6432027..6939b7d 100644 --- a/QiniuSDK/AFNetworking/AFURLSessionManager.h +++ b/QiniuSDK/AFNetworking/AFURLSessionManager.h @@ -42,6 +42,7 @@ - `URLSession:didBecomeInvalidWithError:` - `URLSession:didReceiveChallenge:completionHandler:` + - `URLSessionDidFinishEventsForBackgroundURLSession:` ### `NSURLSessionTaskDelegate` @@ -56,7 +57,6 @@ - `URLSession:dataTask:didBecomeDownloadTask:` - `URLSession:dataTask:didReceiveData:` - `URLSession:dataTask:willCacheResponse:completionHandler:` - - `URLSessionDidFinishEventsForBackgroundURLSession:` ### `NSURLSessionDownloadDelegate` diff --git a/QiniuSDK/AFNetworking/AFURLSessionManager.m b/QiniuSDK/AFNetworking/AFURLSessionManager.m index 194cdfa..0775c4d 100644 --- a/QiniuSDK/AFNetworking/AFURLSessionManager.m +++ b/QiniuSDK/AFNetworking/AFURLSessionManager.m @@ -24,6 +24,16 @@ #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) +static dispatch_queue_t url_session_manager_creation_queue() { + static dispatch_queue_t af_url_session_manager_creation_queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL); + }); + + return af_url_session_manager_creation_queue; +} + static dispatch_queue_t url_session_manager_processing_queue() { static dispatch_queue_t af_url_session_manager_processing_queue; static dispatch_once_t onceToken; @@ -67,7 +77,7 @@ static dispatch_group_t url_session_manager_completion_group() { static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock"; -static NSUInteger const AFMaximumNumberOfToRecreateBackgroundSessionUploadTask = 3; +static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3; static void * AFTaskStateChangedContext = &AFTaskStateChangedContext; @@ -76,6 +86,7 @@ static dispatch_group_t url_session_manager_completion_group() { typedef NSURLRequest * (^AFURLSessionTaskWillPerformHTTPRedirectionBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request); typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionTaskDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential); +typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session); typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task); typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend); @@ -85,7 +96,6 @@ static dispatch_group_t url_session_manager_completion_group() { typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask); typedef void (^AFURLSessionDataTaskDidReceiveDataBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data); typedef NSCachedURLResponse * (^AFURLSessionDataTaskWillCacheResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse); -typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session); typedef NSURL * (^AFURLSessionDownloadTaskDidFinishDownloadingBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location); typedef void (^AFURLSessionDownloadTaskDidWriteDataBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite); @@ -253,6 +263,7 @@ @interface AFURLSessionManager () @property (readwrite, nonatomic, strong) NSLock *lock; @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid; @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; +@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession; @property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection; @property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge; @property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream; @@ -262,7 +273,6 @@ @interface AFURLSessionManager () @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask; @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData; @property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse; -@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession; @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading; @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData; @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume; @@ -284,20 +294,21 @@ - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)config configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; } - self.operationQueue = [[NSOperationQueue alloc] init]; - self.operationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount; + self.sessionConfiguration = configuration; - self.responseSerializer = [AFJSONResponseSerializer serializer]; + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 1; - self.sessionConfiguration = configuration; self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue]; - self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; + self.responseSerializer = [AFJSONResponseSerializer serializer]; self.securityPolicy = [AFSecurityPolicy defaultPolicy]; self.reachabilityManager = [AFNetworkReachabilityManager sharedManager]; + self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; + self.lock = [[NSLock alloc] init]; self.lock.name = AFURLSessionManagerLockName; @@ -337,8 +348,8 @@ - (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate NSParameterAssert(task); NSParameterAssert(delegate); + [task addObserver:self forKeyPath:NSStringFromSelector(@selector(state)) options:(NSKeyValueObservingOptions)(NSKeyValueObservingOptionOld |NSKeyValueObservingOptionNew) context:AFTaskStateChangedContext]; [self.lock lock]; - [task addObserver:self forKeyPath:NSStringFromSelector(@selector(state)) options:NSKeyValueObservingOptionOld |NSKeyValueObservingOptionNew context:AFTaskStateChangedContext]; self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate; [self.lock unlock]; } @@ -393,13 +404,11 @@ - (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate.manager = self; delegate.completionHandler = completionHandler; - delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) { - if (destination) { + if (destination) { + delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) { return destination(location, task.response); - } - - return location; - }; + }; + } if (progress) { *progress = delegate.progress; @@ -411,8 +420,8 @@ - (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask - (void)removeDelegateForTask:(NSURLSessionTask *)task { NSParameterAssert(task); - [self.lock lock]; [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(state)) context:AFTaskStateChangedContext]; + [self.lock lock]; [self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)]; [self.lock unlock]; } @@ -466,11 +475,13 @@ - (NSArray *)downloadTasks { #pragma mark - - (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks { - if (cancelPendingTasks) { - [self.session invalidateAndCancel]; - } else { - [self.session finishTasksAndInvalidate]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + if (cancelPendingTasks) { + [self.session invalidateAndCancel]; + } else { + [self.session finishTasksAndInvalidate]; + } + }); } #pragma mark - @@ -486,7 +497,10 @@ - (void)setResponseSerializer:(id )responseSerialize - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { - NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request]; + __block NSURLSessionDataTask *dataTask = nil; + dispatch_sync(url_session_manager_creation_queue(), ^{ + dataTask = [self.session dataTaskWithRequest:request]; + }); [self addDelegateForDataTask:dataTask completionHandler:completionHandler]; @@ -500,9 +514,13 @@ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request progress:(NSProgress * __autoreleasing *)progress completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { - NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL]; + __block NSURLSessionUploadTask *uploadTask = nil; + dispatch_sync(url_session_manager_creation_queue(), ^{ + uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL]; + }); + if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) { - for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfToRecreateBackgroundSessionUploadTask; attempts++) { + for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) { uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL]; } } @@ -517,7 +535,10 @@ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request progress:(NSProgress * __autoreleasing *)progress completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { - NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData]; + __block NSURLSessionUploadTask *uploadTask = nil; + dispatch_sync(url_session_manager_creation_queue(), ^{ + uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData]; + }); [self addDelegateForUploadTask:uploadTask progress:progress completionHandler:completionHandler]; @@ -528,7 +549,10 @@ - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)reques progress:(NSProgress * __autoreleasing *)progress completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { - NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithStreamedRequest:request]; + __block NSURLSessionUploadTask *uploadTask = nil; + dispatch_sync(url_session_manager_creation_queue(), ^{ + uploadTask = [self.session uploadTaskWithStreamedRequest:request]; + }); [self addDelegateForUploadTask:uploadTask progress:progress completionHandler:completionHandler]; @@ -542,7 +566,10 @@ - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler { - NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request]; + __block NSURLSessionDownloadTask *downloadTask = nil; + dispatch_sync(url_session_manager_creation_queue(), ^{ + downloadTask = [self.session downloadTaskWithRequest:request]; + }); [self addDelegateForDownloadTask:downloadTask progress:progress destination:destination completionHandler:completionHandler]; @@ -554,7 +581,10 @@ - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler { - NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithResumeData:resumeData]; + __block NSURLSessionDownloadTask *downloadTask = nil; + dispatch_sync(url_session_manager_creation_queue(), ^{ + downloadTask = [self.session downloadTaskWithResumeData:resumeData]; + }); [self addDelegateForDownloadTask:downloadTask progress:progress destination:destination completionHandler:completionHandler]; @@ -581,6 +611,10 @@ - (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChalle self.sessionDidReceiveAuthenticationChallenge = block; } +- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block { + self.didFinishEventsForBackgroundURLSession = block; +} + #pragma mark - - (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block { @@ -621,10 +655,6 @@ - (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSessio self.dataTaskWillCacheResponse = block; } -- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block { - self.didFinishEventsForBackgroundURLSession = block; -} - #pragma mark - - (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block { @@ -936,6 +966,7 @@ - (void)URLSession:(NSURLSession *)session if (error) { [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo]; } + return; } } @@ -973,7 +1004,7 @@ - (void)URLSession:(NSURLSession *)session } } -#pragma mark - NSecureCoding +#pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; diff --git a/README.md b/README.md index 461436f..93a5a02 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ [![Qiniu Logo](http://qiniu-brand.qiniudn.com/5/logo-white-195x105.png)](http://www.qiniu.com/) +## 新版SDK +6.X版本基本不再更新, 建议使用新版本SDK,https://github.com/qiniu/objc-sdk ## 下载