diff --git a/.gitignore b/.gitignore index d9b2144d3b..3ed6abd5fd 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,3 @@ DerivedData .idea/ Tests/Pods Tests/Podfile.lock -Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/ diff --git a/.travis.yml b/.travis.yml index 23db5e2fa1..9b56c0055c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,37 @@ language: objective-c -osx_image: xcode7 +osx_image: xcode7.1 +sudo: false +env: + global: + - LC_CTYPE=en_US.UTF-8 + - LANG=en_US.UTF-8 + matrix: + - DESTINATION="OS=9.1,name=iPhone 6s" TEST_SCHEME="iOS Tests" EXAMPLE_SCHEME="AFNetworking iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="YES" POD_LINT="NO" + - DESTINATION="OS=9.0,name=iPhone 6 Plus" TEST_SCHEME="iOS Tests" EXAMPLE_SCHEME="AFNetworking iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="YES" POD_LINT="NO" + - DESTINATION="OS=8.4,name=iPhone 6" TEST_SCHEME="iOS Tests" EXAMPLE_SCHEME="AFNetworking iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 5S" TEST_SCHEME="iOS Tests" EXAMPLE_SCHEME="AFNetworking iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" + - DESTINATION="OS=8.2,name=iPhone 5" TEST_SCHEME="iOS Tests" EXAMPLE_SCHEME="AFNetworking iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" + - DESTINATION="OS=8.1,name=iPhone 4S" TEST_SCHEME="iOS Tests" EXAMPLE_SCHEME="AFNetworking iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="YES" +# TESTS ARE CURRENTLY DISABLED FOR MAC OS X DUE TO THIS ISSUE: https://github.com/travis-ci/travis-ci/issues/4904 + - DESTINATION="arch=x86_64" TEST_SCHEME="OS X Tests" SDK=macosx10.11 EXAMPLE_SCHEME="AFNetworking Example" RUN_TESTS="NO" BUILD_EXAMPLE="YES" POD_LINT="NO" before_install: - - gem install cocoapods --no-rdoc --no-ri --no-document --quiet - - gem install xcpretty --no-rdoc --no-ri --no-document --quiet - - cd Tests && pod install && cd $TRAVIS_BUILD_DIR -script: rake test - + - gem install cocoapods --no-rdoc --no-ri --no-document --quiet + - gem install xcpretty --no-rdoc --no-ri --no-document --quiet + - cd Tests && pod install && cd $TRAVIS_BUILD_DIR +script: + - set -o pipefail + - xcodebuild -version + - xcodebuild -showsdks + - if [ $RUN_TESTS == "YES" ]; then + xcodebuild -workspace AFNetworking.xcworkspace -scheme "$TEST_SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c; + xcodebuild -workspace AFNetworking.xcworkspace -scheme "$TEST_SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO test | xcpretty -c; + fi + - if [ $BUILD_EXAMPLE == "YES" ]; then + xcodebuild -workspace AFNetworking.xcworkspace -scheme "$EXAMPLE_SCHEME" -destination "$DESTINATION" + -configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c; + xcodebuild -workspace AFNetworking.xcworkspace -scheme "$EXAMPLE_SCHEME" -destination "$DESTINATION" + -configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c; + fi + - if [ $POD_LINT == "YES" ]; then + pod lib lint --quick; + fi \ No newline at end of file diff --git a/AFNetworking.podspec b/AFNetworking.podspec index 66204cf67e..eae9331dc3 100644 --- a/AFNetworking.podspec +++ b/AFNetworking.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'AFNetworking' - s.version = '2.6.0' + s.version = '2.6.3' s.license = 'MIT' s.summary = 'A delightful iOS and OS X networking framework.' s.homepage = 'https://github.com/AFNetworking/AFNetworking' diff --git a/AFNetworking/AFHTTPRequestOperationManager.h b/AFNetworking/AFHTTPRequestOperationManager.h index d2385edc97..8170811654 100644 --- a/AFNetworking/AFHTTPRequestOperationManager.h +++ b/AFNetworking/AFHTTPRequestOperationManager.h @@ -160,7 +160,7 @@ NS_ASSUME_NONNULL_BEGIN /** The dispatch queue for the `completionBlock` of request operations. If `NULL` (default), the main queue is used. */ -#if OS_OBJECT_HAVE_OBJC_SUPPORT +#if OS_OBJECT_USE_OBJC @property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; #else @property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; @@ -169,7 +169,7 @@ NS_ASSUME_NONNULL_BEGIN /** The dispatch group for the `completionBlock` of request operations. If `NULL` (default), a private dispatch group is used. */ -#if OS_OBJECT_HAVE_OBJC_SUPPORT +#if OS_OBJECT_USE_OBJC @property (nonatomic, strong, nullable) dispatch_group_t completionGroup; #else @property (nonatomic, assign, nullable) dispatch_group_t completionGroup; @@ -227,7 +227,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable AFHTTPRequestOperation *)GET:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `HEAD` request. @@ -242,7 +242,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable AFHTTPRequestOperation *)HEAD:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(AFHTTPRequestOperation *operation))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `POST` request. @@ -257,7 +257,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable AFHTTPRequestOperation *)POST:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a multipart `POST` request. @@ -274,7 +274,7 @@ NS_ASSUME_NONNULL_BEGIN parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id formData))block success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `PUT` request. @@ -289,7 +289,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable AFHTTPRequestOperation *)PUT:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `PATCH` request. @@ -304,7 +304,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable AFHTTPRequestOperation *)PATCH:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `DELETE` request. @@ -319,7 +319,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable AFHTTPRequestOperation *)DELETE:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; @end diff --git a/AFNetworking/AFHTTPRequestOperationManager.m b/AFNetworking/AFHTTPRequestOperationManager.m index 60739e5f0d..ee682b794e 100644 --- a/AFNetworking/AFHTTPRequestOperationManager.m +++ b/AFNetworking/AFHTTPRequestOperationManager.m @@ -260,6 +260,10 @@ - (id)initWithCoder:(NSCoder *)decoder { self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; + AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; + if (decodedPolicy) { + self.securityPolicy = decodedPolicy; + } return self; } @@ -268,6 +272,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; + [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; } #pragma mark - NSCopying @@ -277,6 +282,7 @@ - (id)copyWithZone:(NSZone *)zone { HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; + HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; return HTTPClient; } diff --git a/AFNetworking/AFHTTPSessionManager.h b/AFNetworking/AFHTTPSessionManager.h index e516e6d661..04b087626f 100644 --- a/AFNetworking/AFHTTPSessionManager.h +++ b/AFNetworking/AFHTTPSessionManager.h @@ -152,7 +152,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `HEAD` request. @@ -167,7 +167,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `POST` request. @@ -182,7 +182,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. @@ -199,7 +199,7 @@ NS_ASSUME_NONNULL_BEGIN parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id formData))block success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `PUT` request. @@ -214,7 +214,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `PATCH` request. @@ -229,7 +229,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `DELETE` request. @@ -244,7 +244,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; @end diff --git a/AFNetworking/AFHTTPSessionManager.m b/AFNetworking/AFHTTPSessionManager.m index bd9163faa4..ed46b26d3c 100644 --- a/AFNetworking/AFHTTPSessionManager.m +++ b/AFNetworking/AFHTTPSessionManager.m @@ -290,6 +290,10 @@ - (id)initWithCoder:(NSCoder *)decoder { self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; + AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; + if (decodedPolicy) { + self.securityPolicy = decodedPolicy; + } return self; } @@ -305,6 +309,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { } [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; + [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; } #pragma mark - NSCopying @@ -314,7 +319,7 @@ - (id)copyWithZone:(NSZone *)zone { HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; - + HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; return HTTPClient; } diff --git a/AFNetworking/AFNetworkReachabilityManager.h b/AFNetworking/AFNetworkReachabilityManager.h index 5a445075e0..e2eb945df0 100644 --- a/AFNetworking/AFNetworkReachabilityManager.h +++ b/AFNetworking/AFNetworkReachabilityManager.h @@ -191,8 +191,8 @@ NS_ASSUME_NONNULL_BEGIN @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). */ -extern NSString * const AFNetworkingReachabilityDidChangeNotification; -extern NSString * const AFNetworkingReachabilityNotificationStatusItem; +FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem; ///-------------------- /// @name Functions @@ -201,7 +201,7 @@ extern NSString * const AFNetworkingReachabilityNotificationStatusItem; /** Returns a localized string representation of an `AFNetworkReachabilityStatus` value. */ -extern NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); +FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); NS_ASSUME_NONNULL_END #endif diff --git a/AFNetworking/AFNetworkReachabilityManager.m b/AFNetworking/AFNetworkReachabilityManager.m index 2e5e2edb15..fe67781e3c 100644 --- a/AFNetworking/AFNetworkReachabilityManager.m +++ b/AFNetworking/AFNetworkReachabilityManager.m @@ -33,12 +33,6 @@ typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); -typedef NS_ENUM(NSUInteger, AFNetworkReachabilityAssociation) { - AFNetworkReachabilityForAddress = 1, - AFNetworkReachabilityForAddressPair = 2, - AFNetworkReachabilityForName = 3, -}; - NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusNotReachable: @@ -76,20 +70,28 @@ static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetwork return status; } -static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { +/** + * Queue a status change notification for the main thread. + * + * This is done to ensure that the notifications are received in the same order + * as they are sent. If notifications are sent directly, it is possible that + * a queued notification (for an earlier status condition) is processed after + * the later update, resulting in the listener being left in the wrong state. + */ +static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) { AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); - AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info; - if (block) { - block(status); - } - - dispatch_async(dispatch_get_main_queue(), ^{ + if (block) { + block(status); + } NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; }); +} +static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { + AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info); } static const void * AFNetworkReachabilityRetainCallback(const void *info) { @@ -104,7 +106,6 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { @interface AFNetworkReachabilityManager () @property (readwrite, nonatomic, strong) id networkReachability; -@property (readwrite, nonatomic, assign) AFNetworkReachabilityAssociation networkReachabilityAssociation; @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; @end @@ -126,23 +127,24 @@ + (instancetype)sharedManager { return _sharedManager; } +#ifndef __clang_analyzer__ + (instancetype)managerForDomain:(NSString *)domain { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; - manager.networkReachabilityAssociation = AFNetworkReachabilityForName; return manager; } +#endif +#ifndef __clang_analyzer__ + (instancetype)managerForAddress:(const void *)address { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); - AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; - manager.networkReachabilityAssociation = AFNetworkReachabilityForAddress; return manager; } +#endif - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { self = [super init]; @@ -204,28 +206,12 @@ - (void)startMonitoring { SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context); SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); - switch (self.networkReachabilityAssociation) { - case AFNetworkReachabilityForName: - break; - case AFNetworkReachabilityForAddress: - case AFNetworkReachabilityForAddressPair: - default: { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ - SCNetworkReachabilityFlags flags; - SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags); - AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); - dispatch_async(dispatch_get_main_queue(), ^{ - callback(status); - - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; - - - }); - }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ + SCNetworkReachabilityFlags flags; + if (SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags)) { + AFPostReachabilityStatusChange(flags, callback); } - break; - } + }); } - (void)stopMonitoring { diff --git a/AFNetworking/AFSecurityPolicy.h b/AFNetworking/AFSecurityPolicy.h index 3c38da8307..d968f49d09 100644 --- a/AFNetworking/AFSecurityPolicy.h +++ b/AFNetworking/AFSecurityPolicy.h @@ -36,7 +36,7 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { NS_ASSUME_NONNULL_BEGIN -@interface AFSecurityPolicy : NSObject +@interface AFSecurityPolicy : NSObject /** The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. diff --git a/AFNetworking/AFSecurityPolicy.m b/AFNetworking/AFSecurityPolicy.m index e8eaa65f11..2624775605 100644 --- a/AFNetworking/AFSecurityPolicy.m +++ b/AFNetworking/AFSecurityPolicy.m @@ -251,11 +251,7 @@ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); if (self.SSLPinningMode == AFSSLPinningModeNone) { - if (self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust)){ - return YES; - } else { - return NO; - } + return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust); } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { return NO; } @@ -308,4 +304,44 @@ + (NSSet *)keyPathsForValuesAffectingPinnedPublicKeys { return [NSSet setWithObject:@"pinnedCertificates"]; } +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)decoder { + + self = [self init]; + if (!self) { + return nil; + } + + self.SSLPinningMode = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(SSLPinningMode))] unsignedIntegerValue]; + self.allowInvalidCertificates = [decoder decodeBoolForKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; + self.validatesDomainName = [decoder decodeBoolForKey:NSStringFromSelector(@selector(validatesDomainName))]; + self.pinnedCertificates = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(pinnedCertificates))]; + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:[NSNumber numberWithUnsignedInteger:self.SSLPinningMode] forKey:NSStringFromSelector(@selector(SSLPinningMode))]; + [coder encodeBool:self.allowInvalidCertificates forKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; + [coder encodeBool:self.validatesDomainName forKey:NSStringFromSelector(@selector(validatesDomainName))]; + [coder encodeObject:self.pinnedCertificates forKey:NSStringFromSelector(@selector(pinnedCertificates))]; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + AFSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init]; + securityPolicy.SSLPinningMode = self.SSLPinningMode; + securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates; + securityPolicy.validatesDomainName = self.validatesDomainName; + securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone]; + + return securityPolicy; +} + @end diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index c71bed4e94..c21119e2ba 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -334,11 +334,11 @@ NS_ASSUME_NONNULL_BEGIN /** Posted when an operation begins executing. */ -extern NSString * const AFNetworkingOperationDidStartNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationDidStartNotification; /** Posted when an operation finishes. */ -extern NSString * const AFNetworkingOperationDidFinishNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationDidFinishNotification; NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index d28d69a3ac..2126ca6f06 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -669,11 +669,11 @@ - (void)connection:(NSURLConnection __unused *)connection } break; - } - - if (self.outputStream.streamError) { + } else { [self.connection cancel]; - [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:self.outputStream.streamError]; + if (self.outputStream.streamError) { + [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:self.outputStream.streamError]; + } return; } } @@ -743,7 +743,7 @@ - (id)initWithCoder:(NSCoder *)decoder { return nil; } - self.state = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(state))] integerValue]; + self.state = (AFOperationState)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(state))] integerValue]; self.response = [decoder decodeObjectOfClass:[NSHTTPURLResponse class] forKey:NSStringFromSelector(@selector(response))]; self.error = [decoder decodeObjectOfClass:[NSError class] forKey:NSStringFromSelector(@selector(error))]; self.responseData = [decoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(responseData))]; diff --git a/AFNetworking/AFURLRequestSerialization.h b/AFNetworking/AFURLRequestSerialization.h index 513334b4be..15ced1dd0c 100644 --- a/AFNetworking/AFURLRequestSerialization.h +++ b/AFNetworking/AFURLRequestSerialization.h @@ -46,8 +46,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(nullable id)parameters - error:(NSError * __nullable __autoreleasing *)error; - + error:(NSError * __nullable __autoreleasing *)error +#ifdef NS_SWIFT_NOTHROW +NS_SWIFT_NOTHROW +#endif +; @end #pragma mark - @@ -438,7 +441,7 @@ forHTTPHeaderField:(NSString *)field; `AFURLRequestSerializationErrorDomain` AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. */ -extern NSString * const AFURLRequestSerializationErrorDomain; +FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain; /** ## User info dictionary keys @@ -452,7 +455,7 @@ extern NSString * const AFURLRequestSerializationErrorDomain; `AFNetworkingOperationFailingURLRequestErrorKey` The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`. */ -extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey; /** ## Throttling Bandwidth for HTTP Request Input Streams @@ -467,7 +470,7 @@ extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey; `kAFUploadStream3GSuggestedDelay` Duration of delay each time a packet is read. Equal to 0.2 seconds. */ -extern NSUInteger const kAFUploadStream3GSuggestedPacketSize; -extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; +FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize; +FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay; NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFURLRequestSerialization.m b/AFNetworking/AFURLRequestSerialization.m index 84317616f2..7e22454108 100644 --- a/AFNetworking/AFURLRequestSerialization.m +++ b/AFNetworking/AFURLRequestSerialization.m @@ -80,7 +80,32 @@ NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; - return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028 + // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + + static NSUInteger const batchSize = 50; + + NSUInteger index = 0; + NSMutableString *escaped = @"".mutableCopy; + + while (index < string.length) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wgnu" + NSUInteger length = MIN(string.length - index, batchSize); +#pragma GCC diagnostic pop + NSRange range = NSMakeRange(index, length); + + // To avoid breaking up character sequences such as 👴🏻👮🏽 + range = [string rangeOfComposedCharacterSequencesForRange:range]; + + NSString *substring = [string substringWithRange:range]; + NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + [escaped appendString:encoded]; + + index += range.length; + } + + return escaped; } #pragma mark - @@ -120,8 +145,8 @@ - (NSString *)URLEncodedStringValue { #pragma mark - -extern NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary); -extern NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value); +FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary); +FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value); static NSString * AFQueryStringFromParameters(NSDictionary *parameters) { NSMutableArray *mutablePairs = [NSMutableArray array]; @@ -499,8 +524,8 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request } }]; + NSString *query = nil; if (parameters) { - NSString *query = nil; if (self.queryStringSerialization) { NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); @@ -519,15 +544,21 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request break; } } + } - if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { + if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { + if (query) { mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; - } else { - if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { - [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; - } - [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } + } else { + // #2864: an empty string is a valid x-www-form-urlencoded payload + if (!query) { + query = @""; + } + if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { + [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; + } + [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } return mutableRequest; @@ -570,7 +601,7 @@ - (id)initWithCoder:(NSCoder *)decoder { } self.mutableHTTPRequestHeaders = [[decoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))] mutableCopy]; - self.queryStringSerializationStyle = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue]; + self.queryStringSerializationStyle = (AFHTTPRequestQueryStringSerializationStyle)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue]; return self; } @@ -1371,7 +1402,7 @@ - (id)initWithCoder:(NSCoder *)decoder { return nil; } - self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; + self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; self.writeOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writeOptions))] unsignedIntegerValue]; return self; diff --git a/AFNetworking/AFURLResponseSerialization.h b/AFNetworking/AFURLResponseSerialization.h index e14dc8a9d7..1578b78171 100644 --- a/AFNetworking/AFURLResponseSerialization.h +++ b/AFNetworking/AFURLResponseSerialization.h @@ -42,7 +42,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response data:(nullable NSData *)data - error:(NSError * __nullable __autoreleasing *)error; + error:(NSError * __nullable __autoreleasing *)error +#ifdef NS_SWIFT_NOTHROW +NS_SWIFT_NOTHROW +#endif +; @end @@ -286,7 +290,7 @@ NS_ASSUME_NONNULL_BEGIN `AFURLResponseSerializationErrorDomain` AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. */ -extern NSString * const AFURLResponseSerializationErrorDomain; +FOUNDATION_EXPORT NSString * const AFURLResponseSerializationErrorDomain; /** ## User info dictionary keys @@ -304,8 +308,8 @@ extern NSString * const 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; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey; -extern NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFURLResponseSerialization.m b/AFNetworking/AFURLResponseSerialization.m index f95834f1dd..cfa8287a26 100644 --- a/AFNetworking/AFURLResponseSerialization.m +++ b/AFNetworking/AFURLResponseSerialization.m @@ -501,7 +501,7 @@ - (id)initWithCoder:(NSCoder *)decoder { return nil; } - self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; + self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; self.readOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readOptions))] unsignedIntegerValue]; return self; diff --git a/AFNetworking/AFURLSessionManager.h b/AFNetworking/AFURLSessionManager.h index a718d964c1..4498c89294 100644 --- a/AFNetworking/AFURLSessionManager.h +++ b/AFNetworking/AFURLSessionManager.h @@ -165,7 +165,7 @@ NS_ASSUME_NONNULL_BEGIN /** The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. */ -#if OS_OBJECT_HAVE_OBJC_SUPPORT +#if OS_OBJECT_USE_OBJC @property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; #else @property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; @@ -174,7 +174,7 @@ NS_ASSUME_NONNULL_BEGIN /** The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. */ -#if OS_OBJECT_HAVE_OBJC_SUPPORT +#if OS_OBJECT_USE_OBJC @property (nonatomic, strong, nullable) dispatch_group_t completionGroup; #else @property (nonatomic, assign, nullable) dispatch_group_t completionGroup; @@ -428,7 +428,7 @@ NS_ASSUME_NONNULL_BEGIN @param block A block object to be executed when a download task has completed. The block returns the URL the download should be moved to, and takes three arguments: the session, the download task, and the temporary location of the downloaded file. If the file manager encounters an error while attempting to move the temporary file to the destination, an `AFURLSessionDownloadTaskDidFailToMoveFileNotification` will be posted, with the download task as its object, and the user info of the error. */ -- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; +- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * __nullable (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; /** Sets a block to be executed periodically to track download progress, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:`. @@ -457,98 +457,98 @@ NS_ASSUME_NONNULL_BEGIN @deprecated Use `AFNetworkingTaskDidResumeNotification` instead. */ -extern NSString * const AFNetworkingTaskDidStartNotification DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidStartNotification DEPRECATED_ATTRIBUTE; /** Posted when a task resumes. */ -extern NSString * const AFNetworkingTaskDidResumeNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification; /** Posted when a task finishes executing. Includes a userInfo dictionary with additional information about the task. @deprecated Use `AFNetworkingTaskDidCompleteNotification` instead. */ -extern NSString * const AFNetworkingTaskDidFinishNotification DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishNotification DEPRECATED_ATTRIBUTE; /** Posted when a task finishes executing. Includes a userInfo dictionary with additional information about the task. */ -extern NSString * const AFNetworkingTaskDidCompleteNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteNotification; /** Posted when a task suspends its execution. */ -extern NSString * const AFNetworkingTaskDidSuspendNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidSuspendNotification; /** Posted when a session is invalidated. */ -extern NSString * const AFURLSessionDidInvalidateNotification; +FOUNDATION_EXPORT NSString * const AFURLSessionDidInvalidateNotification; /** Posted when a session download task encountered an error when moving the temporary download file to a specified destination. */ -extern NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification; +FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification; /** The raw response data of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if response data exists for the task. @deprecated Use `AFNetworkingTaskDidCompleteResponseDataKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishResponseDataKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishResponseDataKey DEPRECATED_ATTRIBUTE; /** The raw response data of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if response data exists for the task. */ -extern NSString * const AFNetworkingTaskDidCompleteResponseDataKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseDataKey; /** The serialized response object of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the response was serialized. @deprecated Use `AFNetworkingTaskDidCompleteSerializedResponseKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishSerializedResponseKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishSerializedResponseKey DEPRECATED_ATTRIBUTE; /** The serialized response object of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the response was serialized. */ -extern NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey; /** The response serializer used to serialize the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the task has an associated response serializer. @deprecated Use `AFNetworkingTaskDidCompleteResponseSerializerKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishResponseSerializerKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishResponseSerializerKey DEPRECATED_ATTRIBUTE; /** The response serializer used to serialize the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the task has an associated response serializer. */ -extern NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey; /** The file path associated with the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an the response data has been stored directly to disk. @deprecated Use `AFNetworkingTaskDidCompleteAssetPathKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishAssetPathKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishAssetPathKey DEPRECATED_ATTRIBUTE; /** The file path associated with the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an the response data has been stored directly to disk. */ -extern NSString * const AFNetworkingTaskDidCompleteAssetPathKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey; /** Any error associated with the task, or the serialization of the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an error exists. @deprecated Use `AFNetworkingTaskDidCompleteErrorKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishErrorKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishErrorKey DEPRECATED_ATTRIBUTE; /** Any error associated with the task, or the serialization of the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an error exists. */ -extern NSString * const AFNetworkingTaskDidCompleteErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey; NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFURLSessionManager.m b/AFNetworking/AFURLSessionManager.m index a795a0717a..8ec0f0843b 100644 --- a/AFNetworking/AFURLSessionManager.m +++ b/AFNetworking/AFURLSessionManager.m @@ -272,14 +272,14 @@ - (void)URLSession:(__unused NSURLSession *)session * - https://github.com/AFNetworking/AFNetworking/pull/2702 */ -static inline void af_swizzleSelector(Class class, SEL originalSelector, SEL swizzledSelector) { - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); +static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) { + Method originalMethod = class_getInstanceMethod(theClass, originalSelector); + Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod); } -static inline BOOL af_addMethod(Class class, SEL selector, Method method) { - return class_addMethod(class, selector, method_getImplementation(method), method_getTypeEncoding(method)); +static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) { + return class_addMethod(theClass, selector, method_getImplementation(method), method_getTypeEncoding(method)); } static NSString * const AFNSURLSessionTaskDidResumeNotification = @"com.alamofire.networking.nsurlsessiontask.resume"; @@ -324,11 +324,13 @@ + (void)load { 7) If the current class implementation of `resume` is not equal to the super class implementation of `resume` AND the current implementation of `resume` is not equal to the original implementation of `af_resume`, THEN swizzle the methods 8) Set the current class to the super class, and repeat steps 3-8 */ + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration]; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnonnull" - NSURLSessionDataTask *localDataTask = [[NSURLSession sessionWithConfiguration:nil] dataTaskWithURL:nil]; + NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil]; #pragma clang diagnostic pop - IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([_AFURLSessionTaskSwizzling class], @selector(af_resume))); + IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume))); Class currentClass = [localDataTask class]; while (class_getInstanceMethod(currentClass, @selector(resume))) { @@ -343,18 +345,21 @@ + (void)load { } [localDataTask cancel]; + [session finishTasksAndInvalidate]; } } -+ (void)swizzleResumeAndSuspendMethodForClass:(Class)class { ++ (void)swizzleResumeAndSuspendMethodForClass:(Class)theClass { Method afResumeMethod = class_getInstanceMethod(self, @selector(af_resume)); Method afSuspendMethod = class_getInstanceMethod(self, @selector(af_suspend)); - - af_addMethod(class, @selector(af_resume), afResumeMethod); - af_addMethod(class, @selector(af_suspend), afSuspendMethod); - - af_swizzleSelector(class, @selector(resume), @selector(af_resume)); - af_swizzleSelector(class, @selector(suspend), @selector(af_suspend)); + + if (af_addMethod(theClass, @selector(af_resume), afResumeMethod)) { + af_swizzleSelector(theClass, @selector(resume), @selector(af_resume)); + } + + if (af_addMethod(theClass, @selector(af_suspend), afSuspendMethod)) { + af_swizzleSelector(theClass, @selector(suspend), @selector(af_suspend)); + } } - (NSURLSessionTaskState)state { diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a34799fff..b7dc7354b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,84 @@ All notable changes to this project will be documented in this file. `AFNetworking` adheres to [Semantic Versioning](http://semver.org/). ---- +--- + +##[2.6.3](https://github.com/AFNetworking/AFNetworking/releases/tag/2.6.3) (11/11/2015) +Released on Wednesday, November 11, 2015. All issues associated with this milestone can be found using this [filter](https://github.com/AFNetworking/AFNetworking/issues?q=milestone%3A2.6.3+is%3Aclosed). + +#### Fixed +* Fixed clang analyzer warning suppression that prevented building under some project configurations + * Fixed by [kcharwood](https://github.com/kcharwood) in [#3142](https://github.com/AFNetworking/AFNetworking/pull/3142). +* Restored Xcode 6 compatibility + * Fixed by [jcayzac](https://github.com/jcayzac) in [#3139](https://github.com/AFNetworking/AFNetworking/pull/3139). + + +##[2.6.2](https://github.com/AFNetworking/AFNetworking/releases/tag/2.6.2) (11/06/2015) +Released on Friday, November 06, 2015. All issues associated with this milestone can be found using this [filter](https://github.com/AFNetworking/AFNetworking/issues?q=milestone%3A2.6.2+is%3Aclosed). + +### Important Upgrade Note for Swift +* [#3130](https://github.com/AFNetworking/AFNetworking/pull/3130) fixes a swift interop error that does have a breaking API change if you are using Swift. This was [identified](https://github.com/AFNetworking/AFNetworking/issues/3137) after 2.6.2 was released. It changes the method from `throws` to an error pointer, since that method does return an object and also handles an error pointer, which does not play nicely with the Swift/Objective-C error conversion. See [#2810](https://github.com/AFNetworking/AFNetworking/issues/2810) for additional notes. This affects `AFURLRequestionSerializer` and `AFURLResponseSerializer`. + +#### Added +* `AFHTTPSessionManager` now copies its `securityPolicy` + * Fixed by [mohamede1945](https://github.com/mohamede1945) in [#2887](https://github.com/AFNetworking/AFNetworking/pull/2887). + +#### Updated +* Updated travis to run on 7.1 + * Fixed by [kcharwood](https://github.com/kcharwood) in [#3132](https://github.com/AFNetworking/AFNetworking/pull/3132). +* Simplifications of if and return statements in `AFSecurityPolicy` + * Fixed by [TorreyBetts](https://github.com/TorreyBetts) in [#3063](https://github.com/AFNetworking/AFNetworking/pull/3063). + +#### Fixed +* Fixed swift interop issue that prevented returning a nil NSURL for a download task + * Fixed by [kcharwood](https://github.com/kcharwood) in [#3133](https://github.com/AFNetworking/AFNetworking/pull/3133). +* Suppressed false positive memory leak warning in Reachability Manager + * Fixed by [kcharwood](https://github.com/kcharwood) in [#3131](https://github.com/AFNetworking/AFNetworking/pull/3131). +* Fixed swift interop issue with throws and Request/Response serialization. + * Fixed by [kcharwood](https://github.com/kcharwood) in [#3130](https://github.com/AFNetworking/AFNetworking/pull/3130). +* Fixed race condition in reachability callback delivery + * Fixed by [MichaelHackett](https://github.com/MichaelHackett) in [#3117](https://github.com/AFNetworking/AFNetworking/pull/3117). +* Fixed URLs that were redirecting in the README + * Fixed by [frankenbot](https://github.com/frankenbot) in [#3109](https://github.com/AFNetworking/AFNetworking/pull/3109). +* Fixed Project Warnings + * Fixed by [kcharwood](https://github.com/kcharwood) in [#3102](https://github.com/AFNetworking/AFNetworking/pull/3102). +* Fixed README link to WWDC session + * Fixed by [wrtsprt](https://github.com/wrtsprt) in [#3099](https://github.com/AFNetworking/AFNetworking/pull/3099). +* Switched from `OS_OBJECT_HAVE_OBJC_SUPPORT` to `OS_OBJECT_USE_OBJC` for watchOS 2 support. + * Fixed by [kylef](https://github.com/kylef) in [#3065](https://github.com/AFNetworking/AFNetworking/pull/3065). +* Added missing __nullable attributes to failure blocks in `AFHTTPRequestOperationManager` and `AFHTTPSessionManager` + * Fixed by [hoppenichu](https://github.com/hoppenichu) in [#3057](https://github.com/AFNetworking/AFNetworking/pull/3057). +* Fixed memory leak in NSURLSession handling + * Fixed by [olegnaumenko](https://github.com/olegnaumenko) in [#2794](https://github.com/AFNetworking/AFNetworking/pull/2794). + + +## [2.6.1](https://github.com/AFNetworking/AFNetworking/releases/tag/2.6.1) (10-13-2015) +Released on Tuesday, October 13th, 2015. All issues associated with this milestone can be found using this [filter](https://github.com/AFNetworking/AFNetworking/issues?q=milestone%3A2.6.1+is%3Aclosed). + +###Future Compatibility Note +Note that AFNetworking 3.0 will soon be released, and will drop support for all `NSURLConnection` based API's (`AFHTTPRequestOperationManager`, `AFHTTPRequestOperation`, and `AFURLConnectionOperation`. If you have not already migrated to `NSURLSession` based API's, please do so soon. For more information, please see the [3.0 migration guide](https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-3.0-Migration-Guide). + +####Fixed +* Fixed a bug that prevented empty x-www-form-urlencoded bodies. + * Fixed by [Julien Cayzac](https://github.com/jcayzac) in [#2868](https://github.com/AFNetworking/AFNetworking/pull/2868). +* Fixed bug that prevented AFNetworking from being installed for watchOS via Cocoapods. + * Fixed by [Kevin Harwood](https://github.com/kcharwood) in [#2909](https://github.com/AFNetworking/AFNetworking/issues/2909). +* Added missing nullable attributes to `AFURLRequestSerialization` and `AFURLSessionManager`. + * Fixed by [andrewtoth](https://github.com/andrewtoth) in [#2911](https://github.com/AFNetworking/AFNetworking/pull/2911). +* Migrated to `OS_OBJECT_USE_OBJC`. + * Fixed by [canius](https://github.com/canius) in [#2930](https://github.com/AFNetworking/AFNetworking/pull/2930). +* Added missing nullable tags to UIKit extensions. + * Fixed by [Kevin Harwood](https://github.com/kcharwood) in [#3000](https://github.com/AFNetworking/AFNetworking/pull/3000). +* Fixed potential infinite recursion loop if multiple versions of AFNetworking are loaded in a target. + * Fixed by [Kevin Harwood](https://github.com/kcharwood) in [#2743](https://github.com/AFNetworking/AFNetworking/issues/2743). +* Updated Travis CI test script + * Fixed by [Kevin Harwood](https://github.com/kcharwood) in [#3032](https://github.com/AFNetworking/AFNetworking/issues/3032). +* Migrated to `FOUNDATION_EXPORT` from `extern`. + * Fixed by [Andrey Mikhaylov](https://github.com/pronebird) in [#3041](https://github.com/AFNetworking/AFNetworking/pull/3041). +* Fixed issue where `AFURLConnectionOperation` could get stuck in an infinite loop. + * Fixed by [Mattt Thompson](https://github.com/mattt) in [#2496](https://github.com/AFNetworking/AFNetworking/pull/2496). +* Fixed regression where URL request serialization would crash on iOS 8 for long URLs. + * Fixed by [softenhard](https://github.com/softenhard) in [#3028](https://github.com/AFNetworking/AFNetworking/pull/3028). ## [2.6.0](https://github.com/AFNetworking/AFNetworking/releases/tag/2.6.0) (08-19-2015) Released on Wednesday, August 19th, 2015. All issues associated with this milestone can be found using this [filter](https://github.com/AFNetworking/AFNetworking/issues?q=milestone%3A2.6.0+is%3Aclosed). diff --git a/Example/AFNetworking OS X Example.xcodeproj/project.pbxproj b/Example/AFNetworking OS X Example.xcodeproj/project.pbxproj index 0d4635fbc4..fd9261b916 100644 --- a/Example/AFNetworking OS X Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking OS X Example.xcodeproj/project.pbxproj @@ -227,7 +227,7 @@ F8129BF21591061B009BFE23 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0710; }; buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking OS X Example" */; compatibilityVersion = "Xcode 3.2"; @@ -297,9 +297,11 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -336,6 +338,7 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -357,6 +360,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Prefix.pch; INFOPLIST_FILE = "Mac-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.alamofire.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -371,6 +375,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Prefix.pch; INFOPLIST_FILE = "Mac-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.alamofire.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; diff --git a/Example/AFNetworking OS X Example.xcodeproj/xcshareddata/xcschemes/AFNetworking Example.xcscheme b/Example/AFNetworking OS X Example.xcodeproj/xcshareddata/xcschemes/AFNetworking Example.xcscheme new file mode 100644 index 0000000000..b97e123ad6 --- /dev/null +++ b/Example/AFNetworking OS X Example.xcodeproj/xcshareddata/xcschemes/AFNetworking Example.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj b/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj index 9d93a32d97..63466c4a37 100644 --- a/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj +++ b/Example/AFNetworking iOS Example.xcodeproj/project.pbxproj @@ -1218,6 +1218,7 @@ 29900D261B6FB14000DE5662 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 29900D291B6FB14000DE5662 /* Build configuration list for PBXNativeTarget "AFNetworking watchOS" */ = { isa = XCConfigurationList; @@ -1226,6 +1227,7 @@ 29900D241B6FB14000DE5662 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; EBE11F591B62EDD200753127 /* Build configuration list for PBXNativeTarget "Today Extension" */ = { isa = XCConfigurationList; diff --git a/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/AFNetworking iOS Example.xcscheme b/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/AFNetworking iOS Example.xcscheme new file mode 100644 index 0000000000..1d72440c9f --- /dev/null +++ b/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/AFNetworking iOS Example.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/AFNetworking watchOS.xcscheme b/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/AFNetworking watchOS.xcscheme new file mode 100644 index 0000000000..8b0dffb196 --- /dev/null +++ b/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/AFNetworking watchOS.xcscheme @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/Today Extension.xcscheme b/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/Today Extension.xcscheme new file mode 100644 index 0000000000..6c3920aabc --- /dev/null +++ b/Example/AFNetworking iOS Example.xcodeproj/xcshareddata/xcschemes/Today Extension.xcscheme @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/AFNetworking watchOS Extension/Info.plist b/Example/AFNetworking watchOS Extension/Info.plist index b752306b9f..d932c4e866 100644 --- a/Example/AFNetworking watchOS Extension/Info.plist +++ b/Example/AFNetworking watchOS Extension/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 1 + 1.0.0 NSExtension NSExtensionAttributes diff --git a/Example/AFNetworking watchOS/Info.plist b/Example/AFNetworking watchOS/Info.plist index 6c4f88c560..557baf0e30 100644 --- a/Example/AFNetworking watchOS/Info.plist +++ b/Example/AFNetworking watchOS/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 1 + 1.0.0 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/Example/Mac-Info.plist b/Example/Mac-Info.plist index fc1c1f64b4..f0068898b2 100644 --- a/Example/Mac-Info.plist +++ b/Example/Mac-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.alamofire.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Example/Today Extension/Info.plist b/Example/Today Extension/Info.plist index 13eb2a2ece..5b7906020b 100644 --- a/Example/Today Extension/Info.plist +++ b/Example/Today Extension/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 1 + 1.0.0 NSExtension NSExtensionMainStoryboard diff --git a/README.md b/README.md index f25efe0890..87ec4b20a5 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Choose AFNetworking for your next project, or migrate over your existing project ### Installation with CocoaPods -[CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like AFNetworking in your projects. See the ["Getting Started" guide for more information](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking). +[CocoaPods](https://cocoapods.org/) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like AFNetworking in your projects. See the ["Getting Started" guide for more information](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking). #### Podfile @@ -263,7 +263,7 @@ NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]}; * Network reachability is a useful tool for determining why a request might have failed. * After a network request has failed, telling the user they're offline is better than giving them a more technical but accurate error, such as "request timed out." -See also [WWDC 2012 session 706, "Networking Best Practices."](https://developer.apple.com/videos/wwdc/2012/#706). +See also [WWDC 2012 session 706, "Networking Best Practices."](https://developer.apple.com/videos/play/wwdc2012-706/). #### Shared Network Reachability @@ -360,7 +360,7 @@ NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...] ## Unit Tests -AFNetworking includes a suite of unit tests within the Tests subdirectory. In order to run the unit tests, you must install the testing dependencies via [CocoaPods](http://cocoapods.org/): +AFNetworking includes a suite of unit tests within the Tests subdirectory. In order to run the unit tests, you must install the testing dependencies via [CocoaPods](https://cocoapods.org/): $ cd Tests $ pod install @@ -369,7 +369,7 @@ Once testing dependencies are installed, you can execute the test suite via the ### Running Tests from the Command Line -Tests can also be run from the command line or within a continuous integration environment. The [`xcpretty`](https://github.com/mneorr/xcpretty) utility needs to be installed before running the tests from the command line: +Tests can also be run from the command line or within a continuous integration environment. The [`xcpretty`](https://github.com/supermarin/xcpretty) utility needs to be installed before running the tests from the command line: $ gem install xcpretty @@ -379,11 +379,11 @@ Once `xcpretty` is installed, you can execute the suite via `rake test`. AFNetworking is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). -AFNetworking was originally created by [Scott Raymond](https://github.com/sco/) and [Mattt Thompson](https://github.com/mattt/) in the development of [Gowalla for iPhone](http://en.wikipedia.org/wiki/Gowalla). +AFNetworking was originally created by [Scott Raymond](https://github.com/sco/) and [Mattt Thompson](https://github.com/mattt/) in the development of [Gowalla for iPhone](https://en.wikipedia.org/wiki/Gowalla). AFNetworking's logo was designed by [Alan Defibaugh](http://www.alandefibaugh.com/). -And most of all, thanks to AFNetworking's [growing list of contributors](https://github.com/AFNetworking/AFNetworking/contributors). +And most of all, thanks to AFNetworking's [growing list of contributors](https://github.com/AFNetworking/AFNetworking/graphs/contributors). ### Security Disclosure diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 45172b69d0..0000000000 --- a/Rakefile +++ /dev/null @@ -1,89 +0,0 @@ -include FileUtils::Verbose - -namespace :test do - task :prepare do - mkdir_p "Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes" - cp Dir.glob('Tests/Schemes/*.xcscheme'), "Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/" - end - - desc "Run the AFNetworking Tests for iOS" - task :ios => :prepare do - simulators = get_ios_simulators - destinations = Array.new - simulators.each {|version, available_simulators| - destinations.push("platform=iOS Simulator,OS=#{available_simulators[:runtime]},name=#{available_simulators[:device_names][0]}") - puts "Will run tests for iOS Simulator on iOS #{available_simulators[:runtime]} using #{available_simulators[:device_names][0]}" - } - - run_tests('iOS Tests', 'iphonesimulator', destinations) - tests_failed('iOS') unless $?.success? - end - - desc "Run the AFNetworking Tests for Mac OS X" - task :osx => :prepare do - run_tests('OS X Tests', 'macosx', ['platform=OS X,arch=x86_64']) - tests_failed('OSX') unless $?.success? - end -end - -desc "Run the AFNetworking Tests for iOS & Mac OS X" -task :test do - Rake::Task['test:ios'].invoke - Rake::Task['test:osx'].invoke if is_mavericks_or_above -end - -task :default => 'test' - - -private - -def run_tests(scheme, sdk, destinations) - destinations = destinations.map! { |destination| "-destination \'#{destination}\'" }.join(' ') - sh("xcodebuild -workspace AFNetworking.xcworkspace -scheme '#{scheme}' -sdk '#{sdk}' #{destinations} -configuration Release clean test | xcpretty -c ; exit ${PIPESTATUS[0]}") rescue nil -end - -def is_mavericks_or_above - osx_version = `sw_vers -productVersion`.chomp - Gem::Version.new(osx_version) >= Gem::Version.new('10.9') -end - -def tests_failed(platform) - puts red("#{platform} unit tests failed") - exit $?.exitstatus -end - -def red(string) - "\033[0;31m! #{string}" -end - -def get_ios_simulators - device_section_regex = /== Devices ==(.*?)(?=(?===)|\z)/m - runtime_section_regex = /== Runtimes ==(.*?)(?=(?===)|\z)/m - runtime_version_regex = /iOS (.*) \((.*) - .*?\) (\(.*\))/ - xcrun_output = `xcrun simctl list` - puts "Available iOS Simulators: \n#{xcrun_output}" - - simulators = Hash.new - runtimes_section = xcrun_output.scan(runtime_section_regex)[0] - runtimes_section[0].scan(runtime_version_regex) {|result| - if result[2] !~ /unavailable/ - simulators[result[0]] = Hash.new - simulators[result[0]][:runtime] = result[1] - end - } - - device_section = xcrun_output.scan(device_section_regex)[0] - version_regex = /-- iOS (.*?) --(.*?)(?=(?=-- .*? --)|\z)/m - simulator_name_regex = /(.*) \([A-F0-9-]*\) \(.*\)/ - device_section[0].scan(version_regex) {|result| - if simulators.has_key?(result[0]) - simulators[result[0]][:device_names] = Array.new - result[1].scan(simulator_name_regex) { |device_name_result| - device_name = device_name_result[0].strip - simulators[result[0]][:device_names].push(device_name) - } - end - } - return simulators -end - diff --git a/Tests/AFNetworking Tests.xcodeproj/project.pbxproj b/Tests/AFNetworking Tests.xcodeproj/project.pbxproj index e6136a95bf..724a1d50de 100644 --- a/Tests/AFNetworking Tests.xcodeproj/project.pbxproj +++ b/Tests/AFNetworking Tests.xcodeproj/project.pbxproj @@ -370,6 +370,7 @@ 2902D27517DF4E1100C81C5A /* Frameworks */, 2902D27617DF4E1100C81C5A /* Resources */, DFF6BB8B6C8D4F8ABC235667 /* Copy Pods Resources */, + 52EFA949F9B961EBF551E519 /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -389,6 +390,7 @@ 2902D28917DF4E2900C81C5A /* Frameworks */, 2902D28A17DF4E2900C81C5A /* Resources */, D728EB5862164B87922C9B80 /* Copy Pods Resources */, + 2EF045980BC7CC4F5DE8BA5D /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -472,6 +474,36 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 2EF045980BC7CC4F5DE8BA5D /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-osx/Pods-osx-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 52EFA949F9B961EBF551E519 /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ios/Pods-ios-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 54CD36584E3B40719F14C3C9 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/OS X Tests.xcscheme b/Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/OS X Tests.xcscheme new file mode 100644 index 0000000000..401f987829 --- /dev/null +++ b/Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/OS X Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/iOS Tests.xcscheme b/Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/iOS Tests.xcscheme new file mode 100644 index 0000000000..758dd59c2d --- /dev/null +++ b/Tests/AFNetworking Tests.xcodeproj/xcshareddata/xcschemes/iOS Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/Tests/AFHTTPRequestSerializationTests.m b/Tests/Tests/AFHTTPRequestSerializationTests.m index 3226f2178f..0fd29e8e99 100644 --- a/Tests/Tests/AFHTTPRequestSerializationTests.m +++ b/Tests/Tests/AFHTTPRequestSerializationTests.m @@ -65,6 +65,34 @@ - (void)setUp { #pragma mark - +- (void)testThatAFHTTPRequestSerializationSerializesPOSTRequestsProperly { + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]]; + request.HTTPMethod = @"POST"; + + NSURLRequest *serializedRequest = [self.requestSerializer requestBySerializingRequest:request withParameters:@{@"key":@"value"} error:nil]; + NSString *contentType = serializedRequest.allHTTPHeaderFields[@"Content-Type"]; + + XCTAssertNotNil(contentType); + XCTAssertEqualObjects(contentType, @"application/x-www-form-urlencoded"); + + XCTAssertNotNil(serializedRequest.HTTPBody); + XCTAssertEqualObjects(serializedRequest.HTTPBody, [@"key=value" dataUsingEncoding:NSUTF8StringEncoding]); +} + +- (void)testThatAFHTTPRequestSerializationSerializesPOSTRequestsProperlyWhenNoParameterIsProvided { + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]]; + request.HTTPMethod = @"POST"; + + NSURLRequest *serializedRequest = [self.requestSerializer requestBySerializingRequest:request withParameters:nil error:nil]; + NSString *contentType = serializedRequest.allHTTPHeaderFields[@"Content-Type"]; + + XCTAssertNotNil(contentType); + XCTAssertEqualObjects(contentType, @"application/x-www-form-urlencoded"); + + XCTAssertNotNil(serializedRequest.HTTPBody); + XCTAssertEqualObjects(serializedRequest.HTTPBody, [NSData data]); +} + - (void)testThatAFHTTPRequestSerialiationSerializesQueryParametersCorrectly { NSURLRequest *originalRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]]; NSURLRequest *serializedRequest = [self.requestSerializer requestBySerializingRequest:originalRequest withParameters:@{@"key":@"value"} error:nil]; @@ -148,4 +176,22 @@ - (void)testQueryStringSerializationCanFailWithError { expect(error).to.equal(serializerError); } +#pragma mark - #3028 tests +//https://github.com/AFNetworking/AFNetworking/pull/3028 + +- (void)testThatEmojiIsProperlyEncoded { + //Start with an odd number of characters so we can cross the 50 character boundry + NSMutableString *parameter = [NSMutableString stringWithString:@"!"]; + while (parameter.length < 50) { + [parameter appendString:@"👴🏿👷🏻👮🏽"]; + } + + AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; + NSURLRequest *request = [serializer requestWithMethod:@"GET" + URLString:@"http://test.com" + parameters:@{@"test":parameter} + error:nil]; + XCTAssertTrue([request.URL.query isEqualToString:@"test=%21%F0%9F%91%B4%F0%9F%8F%BF%F0%9F%91%B7%F0%9F%8F%BB%F0%9F%91%AE%F0%9F%8F%BD%F0%9F%91%B4%F0%9F%8F%BF%F0%9F%91%B7%F0%9F%8F%BB%F0%9F%91%AE%F0%9F%8F%BD%F0%9F%91%B4%F0%9F%8F%BF%F0%9F%91%B7%F0%9F%8F%BB%F0%9F%91%AE%F0%9F%8F%BD%F0%9F%91%B4%F0%9F%8F%BF%F0%9F%91%B7%F0%9F%8F%BB%F0%9F%91%AE%F0%9F%8F%BD%F0%9F%91%B4%F0%9F%8F%BF%F0%9F%91%B7%F0%9F%8F%BB%F0%9F%91%AE%F0%9F%8F%BD"]); +} + @end diff --git a/Tests/Tests/AFHTTPSessionManagerTests.m b/Tests/Tests/AFHTTPSessionManagerTests.m index 2f996164bc..bd2ddae5ad 100644 --- a/Tests/Tests/AFHTTPSessionManagerTests.m +++ b/Tests/Tests/AFHTTPSessionManagerTests.m @@ -139,6 +139,26 @@ - (void)testDownloadFileCompletionSpecifiesURLInCompletionBlock { expect(downloadFilePath).willNot.beNil(); } +- (void)testThatSerializationErrorGeneratesErrorAndNullTaskForGET { + XCTestExpectation *expectation = [self expectationWithDescription:@"Serialization should fail"]; + + [self.manager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error) { + *error = [NSError errorWithDomain:@"Custom" code:-1 userInfo:nil]; + return @""; + }]; + + NSURLSessionTask *nilTask; + nilTask = [self.manager + GET:@"test" + parameters:@{@"key":@"value"} + success:nil + failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { + XCTAssertNil(task); + [expectation fulfill]; + }]; + XCTAssertNil(nilTask); + [self waitForExpectationsWithTimeout:10.0 handler:nil]; +} @end diff --git a/Tests/Tests/AFNetworkActivityManagerTests.m b/Tests/Tests/AFNetworkActivityManagerTests.m index 40b1c4aed4..2f58c1835b 100644 --- a/Tests/Tests/AFNetworkActivityManagerTests.m +++ b/Tests/Tests/AFNetworkActivityManagerTests.m @@ -22,12 +22,11 @@ #import "AFTestCase.h" #import "AFNetworkActivityIndicatorManager.h" -#import "AFHTTPRequestOperation.h" +#import "AFHTTPSessionManager.h" @interface AFNetworkActivityManagerTests : AFTestCase @property (nonatomic, strong) AFNetworkActivityIndicatorManager *networkActivityIndicatorManager; -@property (nonatomic, assign) BOOL isNetworkActivityIndicatorVisible; -@property (nonatomic, strong) id mockApplication; +@property (nonatomic, strong) AFHTTPSessionManager *sessionManager; @end #pragma mark - @@ -37,71 +36,63 @@ @implementation AFNetworkActivityManagerTests - (void)setUp { [super setUp]; + self.sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:self.baseURL sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + self.networkActivityIndicatorManager = [[AFNetworkActivityIndicatorManager alloc] init]; self.networkActivityIndicatorManager.enabled = YES; - - self.mockApplication = [OCMockObject mockForClass:[UIApplication class]]; - [[[self.mockApplication stub] andReturn:self.mockApplication] sharedApplication]; - - [[[self.mockApplication stub] andDo:^(NSInvocation *invocation) { - [invocation setReturnValue:(void *)&_isNetworkActivityIndicatorVisible]; - }] isNetworkActivityIndicatorVisible]; - - [[[self.mockApplication stub] andDo:^(NSInvocation *invocation) { - [invocation getArgument:&_isNetworkActivityIndicatorVisible atIndex:2]; - }] setNetworkActivityIndicatorVisible:YES]; } - (void)tearDown { [super tearDown]; - [self.mockApplication stopMocking]; - - self.mockApplication = nil; self.networkActivityIndicatorManager = nil; + + [self.sessionManager invalidateSessionCancelingTasks:YES]; } #pragma mark - - (void)testThatNetworkActivityIndicatorTurnsOffIndicatorWhenRequestSucceeds { - NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/get" relativeToURL:self.baseURL]]; - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { - expect([self.mockApplication isNetworkActivityIndicatorVisible]).will.beFalsy(); - } failure:nil]; - - [operation start]; - - expect([self.mockApplication isNetworkActivityIndicatorVisible]).will.beTruthy(); + XCTestExpectation *requestCompleteExpectation = [self expectationWithDescription:@"Request should succeed"]; + [self.sessionManager + GET:@"/delay/1" + parameters:nil + success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { + [requestCompleteExpectation fulfill]; + } + failure:nil]; + [self expectationForPredicate:[NSPredicate predicateWithFormat:@"isNetworkActivityIndicatorVisible == YES"] + evaluatedWithObject:self.networkActivityIndicatorManager + handler:nil]; + [self waitForExpectationsWithTimeout:10.0 handler:nil]; + + [self expectationForPredicate:[NSPredicate predicateWithFormat:@"isNetworkActivityIndicatorVisible == NO"] + evaluatedWithObject:self.networkActivityIndicatorManager + handler:nil]; + [self waitForExpectationsWithTimeout:5.0 handler:nil]; } - (void)testThatNetworkActivityIndicatorTurnsOffIndicatorWhenRequestFails { - NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/status/500" relativeToURL:self.baseURL]]; - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; - [operation setCompletionBlockWithSuccess:nil failure:^(AFHTTPRequestOperation *operation, NSError *error) { - expect([self.mockApplication isNetworkActivityIndicatorVisible]).will.beFalsy(); - }]; - - [operation start]; - - expect([self.mockApplication isNetworkActivityIndicatorVisible]).will.beTruthy(); -} - -- (void)testThatNetworkActivityIsUnchangedWhenManagerIsDisabled { - self.networkActivityIndicatorManager.enabled = NO; - - __block BOOL didChangeNetworkActivityIndicatorVisible = NO; - - [[[self.mockApplication stub] andDo:^(NSInvocation *invocation) { - didChangeNetworkActivityIndicatorVisible = YES; - }] setNetworkActivityIndicatorVisible:YES]; - - NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/get" relativeToURL:self.baseURL]]; - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; - [operation setCompletionBlockWithSuccess:nil failure:nil]; - - [operation start]; - - expect(didChangeNetworkActivityIndicatorVisible).will.beFalsy(); + XCTestExpectation *requestCompleteExpectation = [self expectationWithDescription:@"Request should succeed"]; + [self.sessionManager + GET:@"/status/500" + parameters:nil + success:nil + failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { + [requestCompleteExpectation fulfill]; + }]; + + [self + keyValueObservingExpectationForObject:self.networkActivityIndicatorManager + keyPath:@"isNetworkActivityIndicatorVisible" + handler:^BOOL(AFNetworkActivityIndicatorManager * observedObject, NSDictionary * _Nonnull change) { + return observedObject.isNetworkActivityIndicatorVisible; + }]; + [self waitForExpectationsWithTimeout:5.0 handler:nil]; + + [self expectationForPredicate:[NSPredicate predicateWithFormat:@"isNetworkActivityIndicatorVisible == NO"] + evaluatedWithObject:self.networkActivityIndicatorManager + handler:nil]; + [self waitForExpectationsWithTimeout:5.0 handler:nil]; } @end diff --git a/Tests/Tests/AFSecurityPolicyTests.m b/Tests/Tests/AFSecurityPolicyTests.m index e49ee823b7..21bd52b349 100644 --- a/Tests/Tests/AFSecurityPolicyTests.m +++ b/Tests/Tests/AFSecurityPolicyTests.m @@ -561,4 +561,41 @@ - (void)testThatPolicyWithInvalidCertificatesAllowedAndNoValidPinnedCertificates XCTAssertFalse([policy evaluateServerTrust:trust forDomain:@"foobar.com"], @"Policy should not allow server trust because invalid certificates are allowed but there are no pinned certificates"); } + +#pragma mark - NSCopying +- (void)testThatPolicyCanBeCopied { + AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; + policy.allowInvalidCertificates = YES; + policy.validatesDomainName = NO; + + AFSecurityPolicy *copiedPolicy = [policy copy]; + XCTAssertNotEqual(copiedPolicy, policy); + XCTAssertEqual(copiedPolicy.allowInvalidCertificates, policy.allowInvalidCertificates); + XCTAssertEqual(copiedPolicy.validatesDomainName, policy.validatesDomainName); + XCTAssertEqual(copiedPolicy.SSLPinningMode, policy.SSLPinningMode); + XCTAssertNotEqual(copiedPolicy.pinnedCertificates, policy.pinnedCertificates); + XCTAssertTrue([copiedPolicy.pinnedCertificates isEqualToArray:policy.pinnedCertificates]); +} + +- (void)testThatPolicyCanBeEncodedAndDecoded { + AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; + policy.allowInvalidCertificates = YES; + policy.validatesDomainName = NO; + + NSMutableData *archiveData = [NSMutableData new]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData]; + [archiver encodeObject:policy forKey:@"policy"]; + [archiver finishEncoding]; + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:archiveData]; + AFSecurityPolicy *unarchivedPolicy = [unarchiver decodeObjectOfClass:[AFSecurityPolicy class] forKey:@"policy"]; + + XCTAssertNotEqual(unarchivedPolicy, policy); + XCTAssertEqual(unarchivedPolicy.allowInvalidCertificates, policy.allowInvalidCertificates); + XCTAssertEqual(unarchivedPolicy.validatesDomainName, policy.validatesDomainName); + XCTAssertEqual(unarchivedPolicy.SSLPinningMode, policy.SSLPinningMode); + XCTAssertNotEqual(unarchivedPolicy.pinnedCertificates, policy.pinnedCertificates); + XCTAssertTrue([unarchivedPolicy.pinnedCertificates isEqualToArray:policy.pinnedCertificates]); +} + @end diff --git a/Tests/Tests/AFUIImageViewTests.m b/Tests/Tests/AFUIImageViewTests.m index 27d771c9be..8fd98f776c 100644 --- a/Tests/Tests/AFUIImageViewTests.m +++ b/Tests/Tests/AFUIImageViewTests.m @@ -59,18 +59,24 @@ - (void)tearDownSharedImageCache { - (void)testSetImageWithURLRequestUsesCachedImage { XCTestExpectation *expectation = [self expectationWithDescription:@"Image view uses cached image"]; - typeof(self) __weak weakSelf = self; + + __block NSURLRequest *responseRequest = nil; + __block UIImage *responseImage = nil; + __block NSHTTPURLResponse *urlResponse; [self.imageView setImageWithURLRequest:self.cachedImageRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { - XCTAssertEqual(request, weakSelf.cachedImageRequest, @"URL requests do not match"); - XCTAssertNil(response, @"Response should be nil when image is returned from cache"); - XCTAssertEqual(image, weakSelf.cachedImage, @"Cached images do not match"); + responseRequest = request; + responseImage = image; + urlResponse = response; [expectation fulfill]; } failure:nil]; [self waitForExpectationsWithTimeout:5.0 handler:nil]; + XCTAssertEqual(responseRequest, self.cachedImageRequest, @"URL requests do not match"); + XCTAssertNil(urlResponse, @"Response should be nil when image is returned from cache"); + XCTAssertEqual(responseImage, self.cachedImage, @"Cached images do not match"); } @end