diff --git a/25519/Classes/Curve25519.h b/25519/Classes/Curve25519.h index bc42258..ea50174 100644 --- a/25519/Classes/Curve25519.h +++ b/25519/Classes/Curve25519.h @@ -16,6 +16,10 @@ } -(NSData*) publicKey; +-(NSData*) privateKey; + +- (instancetype)initWithPublic:(NSData*)pubkey + private:(NSData*)privKey; @end diff --git a/25519/Classes/Curve25519.m b/25519/Classes/Curve25519.m index 8e3e697..64bc822 100644 --- a/25519/Classes/Curve25519.m +++ b/25519/Classes/Curve25519.m @@ -69,10 +69,25 @@ +(ECKeyPair*)generateKeyPair{ return keyPair; } + +- (instancetype)initWithPublic:(NSData*)pubkey + private:(NSData*)privKey{ + self = [super init]; + + memcpy(self->privateKey, [privKey bytes], 32); + memcpy(self->publicKey, [pubkey bytes], 32); + + return self; +} + -(NSData*) publicKey { return [NSData dataWithBytes:self->publicKey length:32]; } +-(NSData*) privateKey { + return [NSData dataWithBytes:self->privateKey length:32]; +} + -(NSData*) sign:(NSData*)data{ Byte signatureBuffer[ECCSignatureLength]; NSData *randomBytes = [Randomness generateRandomBytes:64]; diff --git a/AFNetworking/AFNetworking/AFHTTPRequestOperation.h b/AFNetworking/AFNetworking/AFHTTPRequestOperation.h index 321d4e7..cf6def4 100644 --- a/AFNetworking/AFNetworking/AFHTTPRequestOperation.h +++ b/AFNetworking/AFNetworking/AFHTTPRequestOperation.h @@ -22,6 +22,8 @@ #import #import "AFURLConnectionOperation.h" +NS_ASSUME_NONNULL_BEGIN + /** `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. */ @@ -34,7 +36,7 @@ /** The last HTTP response received by the operation's connection. */ -@property (readonly, nonatomic, strong) NSHTTPURLResponse *response; +@property (readonly, nonatomic, strong, nullable) NSHTTPURLResponse *response; /** Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an AFHTTPResponse serializer, which uses the raw data as its response object. The serializer validates the status code to be in the `2XX` range, denoting success. If the response serializer generates an error in `-responseObjectForResponse:data:error:`, the `failure` callback of the session task or request operation will be executed; otherwise, the `success` callback will be executed. @@ -46,7 +48,7 @@ /** An object constructed by the `responseSerializer` from the response and response data. Returns `nil` unless the operation `isFinished`, has a `response`, and has `responseData` with non-zero content length. If an error occurs during serialization, `nil` will be returned, and the `error` property will be populated with the serialization error. */ -@property (readonly, nonatomic, strong) id responseObject; +@property (readonly, nonatomic, strong, nullable) id responseObject; ///----------------------------------------------------------- /// @name Setting Completion Block Success / Failure Callbacks @@ -60,7 +62,9 @@ @param success The block to be executed on the completion of a successful request. This block has no return value and takes two arguments: the receiver operation and the object constructed from the response data of the request. @param failure The block to be executed on the completion of an unsuccessful request. This block has no return value and takes two arguments: the receiver operation and the error that occurred during the request. */ -- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (void)setCompletionBlockWithSuccess:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; @end + +NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h b/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h index 17caa78..d2385ed 100644 --- a/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h +++ b/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h @@ -43,6 +43,8 @@ #endif #endif +NS_ASSUME_NONNULL_BEGIN + /** `AFHTTPRequestOperationManager` encapsulates the common patterns of communicating with a web application over HTTP, including request creation, response serialization, network reachability monitoring, and security, as well as request operation management. @@ -94,7 +96,7 @@ /** The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. */ -@property (readonly, nonatomic, strong) NSURL *baseURL; +@property (readonly, nonatomic, strong, nullable) NSURL *baseURL; /** Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. @@ -131,7 +133,7 @@ @see AFURLConnectionOperation -credential */ -@property (nonatomic, strong) NSURLCredential *credential; +@property (nonatomic, strong, nullable) NSURLCredential *credential; ///------------------------------- /// @name Managing Security Policy @@ -159,18 +161,18 @@ The dispatch queue for the `completionBlock` of request operations. If `NULL` (default), the main queue is used. */ #if OS_OBJECT_HAVE_OBJC_SUPPORT -@property (nonatomic, strong) dispatch_queue_t completionQueue; +@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; #else -@property (nonatomic, assign) dispatch_queue_t completionQueue; +@property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; #endif /** The dispatch group for the `completionBlock` of request operations. If `NULL` (default), a private dispatch group is used. */ #if OS_OBJECT_HAVE_OBJC_SUPPORT -@property (nonatomic, strong) dispatch_group_t completionGroup; +@property (nonatomic, strong, nullable) dispatch_group_t completionGroup; #else -@property (nonatomic, assign) dispatch_group_t completionGroup; +@property (nonatomic, assign, nullable) dispatch_group_t completionGroup; #endif ///--------------------------------------------- @@ -191,7 +193,7 @@ @return The newly-initialized HTTP client */ -- (instancetype)initWithBaseURL:(NSURL *)url NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithBaseURL:(nullable NSURL *)url NS_DESIGNATED_INITIALIZER; ///--------------------------------------- /// @name Managing HTTP Request Operations @@ -205,8 +207,8 @@ @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes two arguments:, the created request operation and the `NSError` object describing the network or parsing error that occurred. */ - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; ///--------------------------- /// @name Making HTTP Requests @@ -222,10 +224,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)GET:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (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; /** Creates and runs an `AFHTTPRequestOperation` with a `HEAD` request. @@ -237,10 +239,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)HEAD:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)HEAD:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation))success + failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `POST` request. @@ -252,10 +254,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)POST:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (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; /** Creates and runs an `AFHTTPRequestOperation` with a multipart `POST` request. @@ -268,11 +270,11 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)POST:(NSString *)URLString - parameters:(id)parameters - constructingBodyWithBlock:(void (^)(id formData))block - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)POST:(NSString *)URLString + 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; /** Creates and runs an `AFHTTPRequestOperation` with a `PUT` request. @@ -284,10 +286,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)PUT:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (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; /** Creates and runs an `AFHTTPRequestOperation` with a `PATCH` request. @@ -299,10 +301,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)PATCH:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (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; /** Creates and runs an `AFHTTPRequestOperation` with a `DELETE` request. @@ -314,10 +316,11 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)DELETE:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (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; @end +NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFNetworking/AFHTTPSessionManager.h b/AFNetworking/AFNetworking/AFHTTPSessionManager.h index cc98bab..e516e6d 100644 --- a/AFNetworking/AFNetworking/AFHTTPSessionManager.h +++ b/AFNetworking/AFNetworking/AFHTTPSessionManager.h @@ -20,7 +20,9 @@ // THE SOFTWARE. #import +#if !TARGET_OS_WATCH #import +#endif #import #if __IPHONE_OS_VERSION_MIN_REQUIRED @@ -77,14 +79,16 @@ @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. */ -#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) +#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) || TARGET_OS_WATCH + +NS_ASSUME_NONNULL_BEGIN @interface AFHTTPSessionManager : AFURLSessionManager /** - The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. + The URL used to construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. */ -@property (readonly, nonatomic, strong) NSURL *baseURL; +@property (readonly, nonatomic, strong, nullable) NSURL *baseURL; /** Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. @@ -116,7 +120,7 @@ @return The newly-initialized HTTP client */ -- (instancetype)initWithBaseURL:(NSURL *)url; +- (instancetype)initWithBaseURL:(nullable NSURL *)url; /** Initializes an `AFHTTPSessionManager` object with the specified base URL. @@ -128,8 +132,8 @@ @return The newly-initialized HTTP client */ -- (instancetype)initWithBaseURL:(NSURL *)url - sessionConfiguration:(NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithBaseURL:(nullable NSURL *)url + sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; ///--------------------------- /// @name Making HTTP Requests @@ -145,10 +149,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)GET:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (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; /** Creates and runs an `NSURLSessionDataTask` with a `HEAD` request. @@ -160,10 +164,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)HEAD:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task))success + failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `POST` request. @@ -175,10 +179,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)POST:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (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; /** Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. @@ -191,11 +195,11 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)POST:(NSString *)URLString - parameters:(id)parameters - constructingBodyWithBlock:(void (^)(id formData))block - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString + 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; /** Creates and runs an `NSURLSessionDataTask` with a `PUT` request. @@ -207,10 +211,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)PUT:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (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; /** Creates and runs an `NSURLSessionDataTask` with a `PATCH` request. @@ -222,10 +226,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)PATCH:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (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; /** Creates and runs an `NSURLSessionDataTask` with a `DELETE` request. @@ -237,11 +241,13 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)DELETE:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (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; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/AFNetworking/AFHTTPSessionManager.m b/AFNetworking/AFNetworking/AFHTTPSessionManager.m index 2b8352e..bd9163f 100644 --- a/AFNetworking/AFNetworking/AFHTTPSessionManager.m +++ b/AFNetworking/AFNetworking/AFHTTPSessionManager.m @@ -21,7 +21,7 @@ #import "AFHTTPSessionManager.h" -#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) +#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) || TARGET_WATCH_OS #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" @@ -37,8 +37,10 @@ #import #endif -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS #import +#elif TARGET_OS_WATCH +#import #endif @interface AFHTTPSessionManager () diff --git a/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h b/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h index 4ce2a36..e2eb945 100644 --- a/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h +++ b/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h @@ -20,6 +20,8 @@ // THE SOFTWARE. #import + +#if !TARGET_OS_WATCH #import #ifndef NS_DESIGNATED_INITIALIZER @@ -37,6 +39,8 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusReachableViaWiFi = 2, }; +NS_ASSUME_NONNULL_BEGIN + /** `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. @@ -136,7 +140,7 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. */ -- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block; +- (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; @end @@ -187,8 +191,8 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { @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 @@ -197,4 +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/AFNetworking/AFNetworkReachabilityManager.m b/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m index 25e9581..2e5e2ed 100644 --- a/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m +++ b/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m @@ -20,6 +20,7 @@ // THE SOFTWARE. #import "AFNetworkReachabilityManager.h" +#if !TARGET_OS_WATCH #import #import @@ -102,7 +103,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { } @interface AFNetworkReachabilityManager () -@property (readwrite, nonatomic, assign) SCNetworkReachabilityRef networkReachability; +@property (readwrite, nonatomic, strong) id networkReachability; @property (readwrite, nonatomic, assign) AFNetworkReachabilityAssociation networkReachabilityAssociation; @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; @@ -149,19 +150,19 @@ - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { return nil; } - self.networkReachability = reachability; + self.networkReachability = CFBridgingRelease(reachability); self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; return self; } +- (instancetype)init NS_UNAVAILABLE +{ + return nil; +} + - (void)dealloc { [self stopMonitoring]; - - if (_networkReachability) { - CFRelease(_networkReachability); - _networkReachability = NULL; - } } #pragma mark - @@ -198,9 +199,10 @@ - (void)startMonitoring { }; + id networkReachability = self.networkReachability; SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; - SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); - SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); + SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context); + SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); switch (self.networkReachabilityAssociation) { case AFNetworkReachabilityForName: @@ -210,7 +212,7 @@ - (void)startMonitoring { default: { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ SCNetworkReachabilityFlags flags; - SCNetworkReachabilityGetFlags(self.networkReachability, &flags); + SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags); AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); dispatch_async(dispatch_get_main_queue(), ^{ callback(status); @@ -231,7 +233,7 @@ - (void)stopMonitoring { return; } - SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); + SCNetworkReachabilityUnscheduleFromRunLoop((__bridge SCNetworkReachabilityRef)self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); } #pragma mark - @@ -257,3 +259,4 @@ + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { } @end +#endif diff --git a/AFNetworking/AFNetworking/AFNetworking.h b/AFNetworking/AFNetworking/AFNetworking.h index 68273da..6d442bb 100644 --- a/AFNetworking/AFNetworking/AFNetworking.h +++ b/AFNetworking/AFNetworking/AFNetworking.h @@ -29,14 +29,16 @@ #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" #import "AFSecurityPolicy.h" +#if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" - #import "AFURLConnectionOperation.h" #import "AFHTTPRequestOperation.h" #import "AFHTTPRequestOperationManager.h" +#endif #if ( ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || \ - ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) ) + ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) || \ + TARGET_OS_WATCH ) #import "AFURLSessionManager.h" #import "AFHTTPSessionManager.h" #endif diff --git a/AFNetworking/AFNetworking/AFSecurityPolicy.h b/AFNetworking/AFNetworking/AFSecurityPolicy.h index c6cec83..3c38da8 100644 --- a/AFNetworking/AFNetworking/AFSecurityPolicy.h +++ b/AFNetworking/AFNetworking/AFSecurityPolicy.h @@ -33,6 +33,9 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. */ + +NS_ASSUME_NONNULL_BEGIN + @interface AFSecurityPolicy : NSObject /** @@ -41,14 +44,9 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; /** - Whether to evaluate an entire SSL certificate chain, or just the leaf certificate. Defaults to `YES`. - */ -@property (nonatomic, assign) BOOL validatesCertificateChain; - -/** - The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. + The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. Note that if you create an array with duplicate certificates, the duplicate certificates will be removed. Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. */ -@property (nonatomic, strong) NSArray *pinnedCertificates; +@property (nonatomic, strong, nullable) NSArray *pinnedCertificates; /** Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. @@ -112,10 +110,12 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { @return Whether or not to trust the server. */ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust - forDomain:(NSString *)domain; + forDomain:(nullable NSString *)domain; @end +NS_ASSUME_NONNULL_END + ///---------------- /// @name Constants ///---------------- diff --git a/AFNetworking/AFNetworking/AFSecurityPolicy.m b/AFNetworking/AFNetworking/AFSecurityPolicy.m index 2bbff62..e8eaa65 100644 --- a/AFNetworking/AFNetworking/AFSecurityPolicy.m +++ b/AFNetworking/AFNetworking/AFSecurityPolicy.m @@ -23,7 +23,7 @@ #import -#if !defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if !TARGET_OS_IOS && !TARGET_OS_WATCH static NSData * AFSecKeyGetData(SecKeyRef key) { CFDataRef data = NULL; @@ -41,7 +41,7 @@ #endif static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS || TARGET_OS_WATCH return [(__bridge id)key1 isEqual:(__bridge id)key2]; #else return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; @@ -196,14 +196,13 @@ - (id)init { return nil; } - self.validatesCertificateChain = YES; self.validatesDomainName = YES; return self; } - (void)setPinnedCertificates:(NSArray *)pinnedCertificates { - _pinnedCertificates = pinnedCertificates; + _pinnedCertificates = [[NSOrderedSet orderedSetWithArray:pinnedCertificates] array]; if (self.pinnedCertificates) { NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]]; @@ -229,6 +228,19 @@ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust { - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain { + if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { + // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html + // According to the docs, you should only trust your provided certs for evaluation. + // Pinned certificates are added to the trust. Without pinned certificates, + // there is nothing to evaluate against. + // + // From Apple Docs: + // "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors). + // Instead, add your own (self-signed) CA certificate to the list of trusted anchors." + NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning."); + return NO; + } + NSMutableArray *policies = [NSMutableArray array]; if (self.validatesDomainName) { [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; @@ -264,25 +276,17 @@ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust return NO; } - if (!self.validatesCertificateChain) { - return YES; - } - NSUInteger trustedCertificateCount = 0; for (NSData *trustChainCertificate in serverCertificates) { if ([self.pinnedCertificates containsObject:trustChainCertificate]) { trustedCertificateCount++; } } - - return trustedCertificateCount == [serverCertificates count]; + return trustedCertificateCount > 0; } case AFSSLPinningModePublicKey: { NSUInteger trustedPublicKeyCount = 0; NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust); - if (!self.validatesCertificateChain && [publicKeys count] > 0) { - publicKeys = @[[publicKeys firstObject]]; - } for (id trustChainPublicKey in publicKeys) { for (id pinnedPublicKey in self.pinnedPublicKeys) { @@ -291,11 +295,10 @@ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust } } } - - return trustedPublicKeyCount > 0 && ((self.validatesCertificateChain && trustedPublicKeyCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedPublicKeyCount >= 1)); + return trustedPublicKeyCount > 0; } } - + return NO; } diff --git a/AFNetworking/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFNetworking/AFURLConnectionOperation.h index 0248e67..c21119e 100644 --- a/AFNetworking/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFNetworking/AFURLConnectionOperation.h @@ -73,10 +73,6 @@ Connections will be validated on all matching certificates with a `.cer` extension in the bundle root. - ## App Extensions - - When using AFNetworking in an App Extension, `#define AF_APP_EXTENSIONS` to avoid using unavailable APIs. - ## NSCoding & NSCopying Conformance `AFURLConnectionOperation` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. However, because of the intrinsic limitations of capturing the exact state of an operation at a particular moment, there are some important caveats to keep in mind: @@ -93,6 +89,8 @@ - Operation copies do not include `completionBlock`, as it often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied. */ +NS_ASSUME_NONNULL_BEGIN + @interface AFURLConnectionOperation : NSOperation ///------------------------------- @@ -116,12 +114,12 @@ /** The last response received by the operation's connection. */ -@property (readonly, nonatomic, strong) NSURLResponse *response; +@property (readonly, nonatomic, strong, nullable) NSURLResponse *response; /** The error, if any, that occurred in the lifecycle of the request. */ -@property (readonly, nonatomic, strong) NSError *error; +@property (readonly, nonatomic, strong, nullable) NSError *error; ///---------------------------- /// @name Getting Response Data @@ -130,12 +128,12 @@ /** The data received during the request. */ -@property (readonly, nonatomic, strong) NSData *responseData; +@property (readonly, nonatomic, strong, nullable) NSData *responseData; /** The string representation of the response data. */ -@property (readonly, nonatomic, copy) NSString *responseString; +@property (readonly, nonatomic, copy, nullable) NSString *responseString; /** The string encoding of the response. @@ -160,7 +158,7 @@ This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. */ -@property (nonatomic, strong) NSURLCredential *credential; +@property (nonatomic, strong, nullable) NSURLCredential *credential; ///------------------------------- /// @name Managing Security Policy @@ -187,7 +185,7 @@ By default, data is accumulated into a buffer that is stored into `responseData` upon completion of the request, with the intermediary `outputStream` property set to `nil`. When `outputStream` is set, the data will not be accumulated into an internal buffer, and as a result, the `responseData` property of the completed request will be `nil`. The output stream will be scheduled in the network thread runloop upon being set. */ -@property (nonatomic, strong) NSOutputStream *outputStream; +@property (nonatomic, strong, nullable) NSOutputStream *outputStream; ///--------------------------------- /// @name Managing Callback Queues @@ -196,19 +194,19 @@ /** The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. */ -#if OS_OBJECT_HAVE_OBJC_SUPPORT -@property (nonatomic, strong) dispatch_queue_t completionQueue; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; #else -@property (nonatomic, assign) dispatch_queue_t completionQueue; +@property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; #endif /** The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. */ -#if OS_OBJECT_HAVE_OBJC_SUPPORT -@property (nonatomic, strong) dispatch_group_t completionGroup; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_group_t completionGroup; #else -@property (nonatomic, assign) dispatch_group_t completionGroup; +@property (nonatomic, assign, nullable) dispatch_group_t completionGroup; #endif ///--------------------------------------------- @@ -219,6 +217,7 @@ The user info dictionary for the receiver. */ @property (nonatomic, strong) NSDictionary *userInfo; +// FIXME: It doesn't seem that this userInfo is used anywhere in the implementation. ///------------------------------------------------------ /// @name Initializing an AFURLConnectionOperation Object @@ -267,8 +266,8 @@ @param handler A handler to be called shortly before the application’s remaining background time reaches 0. The handler is wrapped in a block that cancels the operation, and cleans up and marks the end of execution, unlike the `handler` parameter in `UIApplication -beginBackgroundTaskWithExpirationHandler:`, which expects this to be done in the handler itself. The handler is called synchronously on the main thread, thus blocking the application’s suspension momentarily while the application is notified. */ -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) -- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler; +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(nullable void (^)(void))handler NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); #endif ///--------------------------------- @@ -280,14 +279,14 @@ @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes three arguments: the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread. */ -- (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block; +- (void)setUploadProgressBlock:(nullable void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block; /** Sets a callback to be called when an undetermined number of bytes have been downloaded from the server. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. */ -- (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block; +- (void)setDownloadProgressBlock:(nullable void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block; ///------------------------------------------------- /// @name Setting NSURLConnection Delegate Callbacks @@ -300,14 +299,14 @@ If `allowsInvalidSSLCertificate` is set to YES, `connection:willSendRequestForAuthenticationChallenge:` will attempt to have the challenge sender use credentials with invalid SSL certificates. */ -- (void)setWillSendRequestForAuthenticationChallengeBlock:(void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block; +- (void)setWillSendRequestForAuthenticationChallengeBlock:(nullable void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block; /** Sets a block to be executed when the server redirects the request from one URL to another URL, or when the request URL changed by the `NSURLProtocol` subclass handling the request in order to standardize its format, as handled by the `NSURLConnectionDataDelegate` method `connection:willSendRequest:redirectResponse:`. @param block A block object to be executed when the request URL was changed. The block returns an `NSURLRequest` object, the URL request to redirect, and takes three arguments: the URL connection object, the the proposed redirected request, and the URL response that caused the redirect. */ -- (void)setRedirectResponseBlock:(NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block; +- (void)setRedirectResponseBlock:(nullable NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block; /** @@ -315,16 +314,16 @@ @param block A block object to be executed to determine what response a connection will cache, if any. The block returns an `NSCachedURLResponse` object, the cached response to store in memory or `nil` to prevent the response from being cached, and takes two arguments: the URL connection object, and the cached response provided for the request. */ -- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block; +- (void)setCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block; /// /** */ -+ (NSArray *)batchOfRequestOperations:(NSArray *)operations - progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock - completionBlock:(void (^)(NSArray *operations))completionBlock; ++ (NSArray *)batchOfRequestOperations:(nullable NSArray *)operations + progressBlock:(nullable void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock + completionBlock:(nullable void (^)(NSArray *operations))completionBlock; @end @@ -335,9 +334,11 @@ /** 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/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFNetworking/AFURLConnectionOperation.m index 8d32092..0568005 100644 --- a/AFNetworking/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFNetworking/AFURLConnectionOperation.m @@ -37,12 +37,6 @@ typedef NS_ENUM(NSInteger, AFOperationState) { AFOperationFinishedState = 3, }; -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) -typedef UIBackgroundTaskIdentifier AFBackgroundTaskIdentifier; -#else -typedef id AFBackgroundTaskIdentifier; -#endif - static dispatch_group_t url_request_operation_completion_group() { static dispatch_group_t af_url_request_operation_completion_group; static dispatch_once_t onceToken; @@ -72,6 +66,7 @@ static dispatch_queue_t url_request_operation_completion_queue() { typedef void (^AFURLConnectionOperationAuthenticationChallengeBlock)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge); typedef NSCachedURLResponse * (^AFURLConnectionOperationCacheResponseBlock)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse); typedef NSURLRequest * (^AFURLConnectionOperationRedirectResponseBlock)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse); +typedef void (^AFURLConnectionOperationBackgroundTaskCleanupBlock)(); static inline NSString * AFKeyPathFromOperationState(AFOperationState state) { switch (state) { @@ -144,7 +139,7 @@ @interface AFURLConnectionOperation () @property (readwrite, nonatomic, copy) NSString *responseString; @property (readwrite, nonatomic, assign) NSStringEncoding responseStringEncoding; @property (readwrite, nonatomic, assign) long long totalBytesRead; -@property (readwrite, nonatomic, assign) AFBackgroundTaskIdentifier backgroundTaskIdentifier; +@property (readwrite, nonatomic, copy) AFURLConnectionOperationBackgroundTaskCleanupBlock backgroundTaskCleanup; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock uploadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationChallengeBlock authenticationChallenge; @@ -204,18 +199,20 @@ - (instancetype)initWithRequest:(NSURLRequest *)urlRequest { return self; } +- (instancetype)init NS_UNAVAILABLE +{ + return nil; +} + - (void)dealloc { if (_outputStream) { [_outputStream close]; _outputStream = nil; } - -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) - if (_backgroundTaskIdentifier) { - [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier]; - _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + + if (_backgroundTaskCleanup) { + _backgroundTaskCleanup(); } -#endif } #pragma mark - @@ -288,13 +285,22 @@ - (void)setOutputStream:(NSOutputStream *)outputStream { [self.lock unlock]; } -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) - (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler { [self.lock lock]; - if (!self.backgroundTaskIdentifier) { + if (!self.backgroundTaskCleanup) { UIApplication *application = [UIApplication sharedApplication]; + UIBackgroundTaskIdentifier __block backgroundTaskIdentifier = UIBackgroundTaskInvalid; __weak __typeof(self)weakSelf = self; - self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{ + + self.backgroundTaskCleanup = ^(){ + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + }; + + backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{ __strong __typeof(weakSelf)strongSelf = weakSelf; if (handler) { @@ -303,9 +309,7 @@ - (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))ha if (strongSelf) { [strongSelf cancel]; - - [application endBackgroundTask:strongSelf.backgroundTaskIdentifier]; - strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + strongSelf.backgroundTaskCleanup(); } }]; } @@ -498,7 +502,7 @@ - (void)cancel { - (void)cancelConnection { NSDictionary *userInfo = nil; if ([self.request URL]) { - userInfo = [NSDictionary dictionaryWithObject:[self.request URL] forKey:NSURLErrorFailingURLErrorKey]; + userInfo = @{NSURLErrorFailingURLErrorKey : [self.request URL]}; } NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo]; @@ -507,7 +511,7 @@ - (void)cancelConnection { [self.connection cancel]; [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:error]; } else { - // Accomodate race condition where `self.connection` has not yet been set before cancellation + // Accommodate race condition where `self.connection` has not yet been set before cancellation self.error = error; [self finish]; } @@ -665,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; } } diff --git a/AFNetworking/AFNetworking/AFURLRequestSerialization.h b/AFNetworking/AFNetworking/AFURLRequestSerialization.h index bb8d444..ef4d366 100644 --- a/AFNetworking/AFNetworking/AFURLRequestSerialization.h +++ b/AFNetworking/AFNetworking/AFURLRequestSerialization.h @@ -20,10 +20,14 @@ // THE SOFTWARE. #import -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS #import +#elif TARGET_OS_WATCH +#import #endif +NS_ASSUME_NONNULL_BEGIN + /** The `AFURLRequestSerialization` protocol is adopted by an object that encodes parameters for a specified HTTP requests. Request serializers may encode parameters as query strings, HTTP bodies, setting the appropriate HTTP header fields as necessary. @@ -40,9 +44,9 @@ @return A serialized request. */ -- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request - withParameters:(id)parameters - error:(NSError * __autoreleasing *)error; +- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request + withParameters:(nullable id)parameters + error:(NSError * __nullable __autoreleasing *)error; @end @@ -136,7 +140,7 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { @param field The HTTP header to set a default value for @param value The value set as default for the specified header, or `nil` */ -- (void)setValue:(NSString *)value +- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field; /** @@ -146,7 +150,7 @@ forHTTPHeaderField:(NSString *)field; @return The value set as default for the specified header, or `nil` */ -- (NSString *)valueForHTTPHeaderField:(NSString *)field; +- (nullable 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. @@ -191,7 +195,7 @@ forHTTPHeaderField:(NSString *)field; @param block A block that defines a process of encoding parameters into a query string. This block returns the query string and takes three arguments: the request, the parameters to encode, and the error that occurred when attempting to encode parameters for the given request. */ -- (void)setQueryStringSerializationWithBlock:(NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block; +- (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block; ///------------------------------- /// @name Creating Request Objects @@ -212,14 +216,14 @@ forHTTPHeaderField:(NSString *)field; @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. This parameter must not be `nil`. @param URLString The URL string used to create the request URL. @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body. - @param error The error that occured while constructing the request. + @param error The error that occurred while constructing the request. @return An `NSMutableURLRequest` object. */ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString - parameters:(id)parameters - error:(NSError * __autoreleasing *)error; + parameters:(nullable id)parameters + error:(NSError * __nullable __autoreleasing *)error; /** @deprecated This method has been deprecated. Use -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error: instead. @@ -238,15 +242,15 @@ forHTTPHeaderField:(NSString *)field; @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. - @param error The error that occured while constructing the request. + @param error The error that occurred while constructing the request. @return An `NSMutableURLRequest` object */ - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method URLString:(NSString *)URLString - parameters:(NSDictionary *)parameters - constructingBodyWithBlock:(void (^)(id formData))block - error:(NSError * __autoreleasing *)error; + parameters:(nullable NSDictionary *)parameters + constructingBodyWithBlock:(nullable void (^)(id formData))block + error:(NSError * __nullable __autoreleasing *)error; /** Creates an `NSMutableURLRequest` by removing the `HTTPBodyStream` from a request, and asynchronously writing its contents into the specified file, invoking the completion handler when finished. @@ -261,7 +265,7 @@ forHTTPHeaderField:(NSString *)field; */ - (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request writingStreamContentsToFile:(NSURL *)fileURL - completionHandler:(void (^)(NSError *error))handler; + completionHandler:(nullable void (^)(NSError * __nullable error))handler; @end @@ -285,7 +289,7 @@ forHTTPHeaderField:(NSString *)field; */ - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name - error:(NSError * __autoreleasing *)error; + error:(NSError * __nullable __autoreleasing *)error; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary. @@ -302,7 +306,7 @@ forHTTPHeaderField:(NSString *)field; name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType - error:(NSError * __autoreleasing *)error; + error:(NSError * __nullable __autoreleasing *)error; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary. @@ -313,7 +317,7 @@ forHTTPHeaderField:(NSString *)field; @param length The length of the specified input stream in bytes. @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`. */ -- (void)appendPartWithInputStream:(NSInputStream *)inputStream +- (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream name:(NSString *)name fileName:(NSString *)fileName length:(int64_t)length @@ -349,7 +353,7 @@ forHTTPHeaderField:(NSString *)field; @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. This parameter must not be `nil`. */ -- (void)appendPartWithHeaders:(NSDictionary *)headers +- (void)appendPartWithHeaders:(nullable NSDictionary *)headers body:(NSData *)body; /** @@ -434,7 +438,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 @@ -448,7 +452,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 @@ -463,5 +467,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/AFNetworking/AFURLRequestSerialization.m b/AFNetworking/AFNetworking/AFURLRequestSerialization.m index 5b55b5f..e387c24 100644 --- a/AFNetworking/AFNetworking/AFURLRequestSerialization.m +++ b/AFNetworking/AFNetworking/AFURLRequestSerialization.m @@ -61,16 +61,48 @@ return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding]; } -static NSString * const kAFCharactersToBeEscapedInQueryString = @":/?&=;+!@#$()',*"; +/** + Returns a percent-escaped string following RFC 3986 for a query string key or value. + RFC 3986 states that the following characters are "reserved" characters. + - General Delimiters: ":", "#", "[", "]", "@", "?", "/" + - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" -static NSString * AFPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - static NSString * const kAFCharactersToLeaveUnescapedInQueryStringPairKey = @"[]."; + In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow + query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" + should be percent-escaped in the query string. + - parameter string: The string to be percent-escaped. + - returns: The percent-escaped string. + */ +static NSString * AFPercentEscapedStringFromString(NSString *string) { + static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4 + static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; - return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kAFCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding)); -} + NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; + + // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028 + // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + + static NSUInteger const batchSize = 50; + + NSInteger index = 0; + NSMutableString *escaped = @"".mutableCopy; + + while (index < string.length) { + NSUInteger length = MIN(string.length - index, batchSize); + 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; + } -static NSString * AFPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kAFCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding)); + return escaped; } #pragma mark - @@ -81,7 +113,7 @@ @interface AFQueryStringPair : NSObject - (id)initWithField:(id)field value:(id)value; -- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding; +- (NSString *)URLEncodedStringValue; @end @implementation AFQueryStringPair @@ -98,11 +130,11 @@ - (id)initWithField:(id)field value:(id)value { return self; } -- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding { +- (NSString *)URLEncodedStringValue { if (!self.value || [self.value isEqual:[NSNull null]]) { - return AFPercentEscapedQueryStringKeyFromStringWithEncoding([self.field description], stringEncoding); + return AFPercentEscapedStringFromString([self.field description]); } else { - return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedQueryStringKeyFromStringWithEncoding([self.field description], stringEncoding), AFPercentEscapedQueryStringValueFromStringWithEncoding([self.value description], stringEncoding)]; + return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedStringFromString([self.field description]), AFPercentEscapedStringFromString([self.value description])]; } } @@ -110,13 +142,13 @@ - (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding #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 * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding stringEncoding) { +static NSString * AFQueryStringFromParameters(NSDictionary *parameters) { NSMutableArray *mutablePairs = [NSMutableArray array]; for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) { - [mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]]; + [mutablePairs addObject:[pair URLEncodedStringValue]]; } return [mutablePairs componentsJoinedByString:@"&"]; @@ -135,7 +167,7 @@ - (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding NSDictionary *dictionary = value; // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { - id nestedValue = [dictionary objectForKey:nestedKey]; + id nestedValue = dictionary[nestedKey]; if (nestedValue) { [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]; } @@ -215,11 +247,14 @@ - (instancetype)init { NSString *userAgent = nil; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 - userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; + userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; +#elif TARGET_OS_WATCH + // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 + userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]]; #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) - userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; + userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; #endif #pragma clang diagnostic pop if (userAgent) { @@ -486,8 +521,8 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request } }]; + NSString *query = nil; if (parameters) { - NSString *query = nil; if (self.queryStringSerialization) { NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); @@ -502,19 +537,25 @@ - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request } else { switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: - query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding); + query = AFQueryStringFromParameters(parameters); 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; @@ -729,7 +770,7 @@ - (BOOL)appendPartWithFileURL:(NSURL *)fileURL bodyPart.headers = mutableHeaders; bodyPart.boundary = self.boundary; bodyPart.body = fileURL; - bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue]; + bodyPart.bodyContentLength = [fileAttributes[NSFileSize] unsignedLongLongValue]; [self.bodyStream appendHTTPBodyPart:bodyPart]; return YES; @@ -872,7 +913,7 @@ - (void)setInitialAndFinalBoundaries { bodyPart.hasFinalBoundary = NO; } - [[self.HTTPBodyParts objectAtIndex:0] setHasInitialBoundary:YES]; + [[self.HTTPBodyParts firstObject] setHasInitialBoundary:YES]; [[self.HTTPBodyParts lastObject] setHasFinalBoundary:YES]; } } diff --git a/AFNetworking/AFNetworking/AFURLResponseSerialization.h b/AFNetworking/AFNetworking/AFURLResponseSerialization.h index 9cd4ad2..1396cfb 100644 --- a/AFNetworking/AFNetworking/AFURLResponseSerialization.h +++ b/AFNetworking/AFNetworking/AFURLResponseSerialization.h @@ -22,6 +22,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data. @@ -38,9 +40,9 @@ @return The object decoded from the specified response data. */ -- (id)responseObjectForResponse:(NSURLResponse *)response - data:(NSData *)data - error:(NSError *__autoreleasing *)error; +- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response + data:(nullable NSData *)data + error:(NSError * __nullable __autoreleasing *)error; @end @@ -53,7 +55,7 @@ */ @interface AFHTTPResponseSerializer : NSObject -- (instancetype) init; +- (instancetype)init; /** The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default. @@ -74,12 +76,12 @@ See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */ -@property (nonatomic, copy) NSIndexSet *acceptableStatusCodes; +@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes; /** The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation. */ -@property (nonatomic, copy) NSSet *acceptableContentTypes; +@property (nonatomic, copy, nullable) NSSet *acceptableContentTypes; /** Validates the specified response and data. @@ -92,9 +94,9 @@ @return `YES` if the response is valid, otherwise `NO`. */ -- (BOOL)validateResponse:(NSHTTPURLResponse *)response - data:(NSData *)data - error:(NSError *__autoreleasing *)error; +- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response + data:(nullable NSData *)data + error:(NSError * __nullable __autoreleasing *)error; @end @@ -112,7 +114,7 @@ */ @interface AFJSONResponseSerializer : AFHTTPResponseSerializer -- (instancetype) init; +- (instancetype)init; /** Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. @@ -161,7 +163,7 @@ */ @interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer -- (instancetype) init; +- (instancetype)init; /** Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. @@ -190,7 +192,7 @@ */ @interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer -- (instancetype) init; +- (instancetype)init; /** The property list format. Possible values are described in "NSPropertyListFormat". @@ -284,7 +286,7 @@ `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 @@ -302,8 +304,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; - -extern NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; +NS_ASSUME_NONNULL_END diff --git a/AFNetworking/AFNetworking/AFURLResponseSerialization.m b/AFNetworking/AFNetworking/AFURLResponseSerialization.m index a672d20..f95834f 100644 --- a/AFNetworking/AFNetworking/AFURLResponseSerialization.m +++ b/AFNetworking/AFNetworking/AFURLResponseSerialization.m @@ -21,8 +21,10 @@ #import "AFURLResponseSerialization.h" -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS #import +#elif TARGET_OS_WATCH +#import #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #import #endif @@ -67,11 +69,11 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO } else if ([JSONObject isKindOfClass:[NSDictionary class]]) { NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject]; for (id key in [(NSDictionary *)JSONObject allKeys]) { - id value = [(NSDictionary *)JSONObject objectForKey:key]; + id value = (NSDictionary *)JSONObject[key]; if (!value || [value isEqual:[NSNull null]]) { [mutableDictionary removeObjectForKey:key]; } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) { - [mutableDictionary setObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions) forKey:key]; + mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions); } } @@ -529,12 +531,35 @@ - (id)copyWithZone:(NSZone *)zone { #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) #import +@interface UIImage (AFNetworkingSafeImageLoading) ++ (UIImage *)af_safeImageWithData:(NSData *)data; +@end + +static NSLock* imageLock = nil; + +@implementation UIImage (AFNetworkingSafeImageLoading) + ++ (UIImage *)af_safeImageWithData:(NSData *)data { + UIImage* image = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + imageLock = [[NSLock alloc] init]; + }); + + [imageLock lock]; + image = [UIImage imageWithData:data]; + [imageLock unlock]; + return image; +} + +@end + static UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) { - UIImage *image = [[UIImage alloc] initWithData:data]; + UIImage *image = [UIImage af_safeImageWithData:data]; if (image.images) { return image; } - + return [[UIImage alloc] initWithCGImage:[image CGImage] scale:scale orientation:image.imageOrientation]; } @@ -642,9 +667,12 @@ - (instancetype)init { self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil]; -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS self.imageScale = [[UIScreen mainScreen] scale]; self.automaticallyInflatesResponseImage = YES; +#elif TARGET_OS_WATCH + self.imageScale = [[WKInterfaceDevice currentDevice] screenScale]; + self.automaticallyInflatesResponseImage = YES; #endif return self; diff --git a/AFNetworking/AFNetworking/AFURLSessionManager.h b/AFNetworking/AFNetworking/AFURLSessionManager.h index 21d9d64..70e4ec9 100644 --- a/AFNetworking/AFNetworking/AFURLSessionManager.h +++ b/AFNetworking/AFNetworking/AFURLSessionManager.h @@ -24,7 +24,9 @@ #import "AFURLResponseSerialization.h" #import "AFURLRequestSerialization.h" #import "AFSecurityPolicy.h" +#if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" +#endif #ifndef NS_DESIGNATED_INITIALIZER #if __has_attribute(objc_designated_initializer) @@ -89,7 +91,9 @@ @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. */ -#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) +NS_ASSUME_NONNULL_BEGIN + +#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) || TARGET_OS_WATCH @interface AFURLSessionManager : NSObject @@ -119,6 +123,7 @@ */ @property (nonatomic, strong) AFSecurityPolicy *securityPolicy; +#if !TARGET_OS_WATCH ///-------------------------------------- /// @name Monitoring Network Reachability ///-------------------------------------- @@ -127,6 +132,7 @@ The network reachability manager. `AFURLSessionManager` uses the `sharedManager` by default. */ @property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager; +#endif ///---------------------------- /// @name Getting Session Tasks @@ -160,18 +166,18 @@ The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. */ #if OS_OBJECT_HAVE_OBJC_SUPPORT -@property (nonatomic, strong) dispatch_queue_t completionQueue; +@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; #else -@property (nonatomic, assign) dispatch_queue_t completionQueue; +@property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; #endif /** The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. */ #if OS_OBJECT_HAVE_OBJC_SUPPORT -@property (nonatomic, strong) dispatch_group_t completionGroup; +@property (nonatomic, strong, nullable) dispatch_group_t completionGroup; #else -@property (nonatomic, assign) dispatch_group_t completionGroup; +@property (nonatomic, assign, nullable) dispatch_group_t completionGroup; #endif ///--------------------------------- @@ -198,7 +204,7 @@ @return A manager for a newly-created session. */ -- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; /** Invalidates the managed session, optionally canceling pending tasks. @@ -218,7 +224,7 @@ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; ///--------------------------- /// @name Running Upload Tasks @@ -236,8 +242,8 @@ */ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL - progress:(NSProgress * __autoreleasing *)progress - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; /** Creates an `NSURLSessionUploadTask` with the specified request for an HTTP body. @@ -248,9 +254,9 @@ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request - fromData:(NSData *)bodyData - progress:(NSProgress * __autoreleasing *)progress - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + fromData:(nullable NSData *)bodyData + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; /** Creates an `NSURLSessionUploadTask` with the specified streaming request. @@ -260,8 +266,8 @@ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request - progress:(NSProgress * __autoreleasing *)progress - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; ///----------------------------- /// @name Running Download Tasks @@ -278,9 +284,9 @@ @warning If using a background `NSURLSessionConfiguration` on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use `-setDownloadTaskDidFinishDownloadingBlock:` to specify the URL for saving the downloaded file, rather than the destination block of this method. */ - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request - progress:(NSProgress * __autoreleasing *)progress - destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination - completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * __nullable filePath, NSError * __nullable error))completionHandler; /** Creates an `NSURLSessionDownloadTask` with the specified resume data. @@ -291,9 +297,9 @@ @param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any. */ - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData - progress:(NSProgress * __autoreleasing *)progress - destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination - completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * __nullable filePath, NSError * __nullable error))completionHandler; ///--------------------------------- /// @name Getting Progress for Tasks @@ -306,7 +312,7 @@ @return An `NSProgress` object reporting the upload progress of a task, or `nil` if the progress is unavailable. */ -- (NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask; +- (nullable NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask; /** Returns the download progress of the specified task. @@ -315,7 +321,7 @@ @return An `NSProgress` object reporting the download progress of a task, or `nil` if the progress is unavailable. */ -- (NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask; +- (nullable NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask; ///----------------------------------------- /// @name Setting Session Delegate Callbacks @@ -326,14 +332,14 @@ @param block A block object to be executed when the managed session becomes invalid. The block has no return value, and takes two arguments: the session, and the error related to the cause of invalidation. */ -- (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block; +- (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block; /** Sets a block to be executed when a connection level authentication challenge has occurred, as handled by the `NSURLSessionDelegate` method `URLSession:didReceiveChallenge:completionHandler:`. @param block A block object to be executed when a connection level authentication challenge has occurred. The block returns the disposition of the authentication challenge, and takes three arguments: the session, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge. */ -- (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block; +- (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __nullable __autoreleasing * __nullable credential))block; ///-------------------------------------- /// @name Setting Task Delegate Callbacks @@ -344,35 +350,35 @@ @param block A block object to be executed when a task requires a new request body stream. */ -- (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block; +- (void)setTaskNeedNewBodyStreamBlock:(nullable NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block; /** Sets a block to be executed when an HTTP request is attempting to perform a redirection to a different URL, as handled by the `NSURLSessionTaskDelegate` method `URLSession:willPerformHTTPRedirection:newRequest:completionHandler:`. @param block A block object to be executed when an HTTP request is attempting to perform a redirection to a different URL. The block returns the request to be made for the redirection, and takes four arguments: the session, the task, the redirection response, and the request corresponding to the redirection response. */ -- (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; +- (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; /** Sets a block to be executed when a session task has received a request specific authentication challenge, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didReceiveChallenge:completionHandler:`. @param block A block object to be executed when a session task has received a request specific authentication challenge. The block returns the disposition of the authentication challenge, and takes four arguments: the session, the task, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge. */ -- (void)setTaskDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block; +- (void)setTaskDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __nullable __autoreleasing * __nullable credential))block; /** Sets a block to be executed periodically to track upload progress, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:`. @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes five arguments: the session, the task, the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread. */ -- (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block; +- (void)setTaskDidSendBodyDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block; /** Sets a block to be executed as the last message related to a specific task, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didCompleteWithError:`. @param block A block object to be executed when a session task is completed. The block has no return value, and takes three arguments: the session, the task, and any error that occurred in the process of executing the task. */ -- (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block; +- (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * __nullable error))block; ///------------------------------------------- /// @name Setting Data Task Delegate Callbacks @@ -383,35 +389,35 @@ @param block A block object to be executed when a data task has received a response. The block returns the disposition of the session response, and takes three arguments: the session, the data task, and the received response. */ -- (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block; +- (void)setDataTaskDidReceiveResponseBlock:(nullable NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block; /** Sets a block to be executed when a data task has become a download task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didBecomeDownloadTask:`. @param block A block object to be executed when a data task has become a download task. The block has no return value, and takes three arguments: the session, the data task, and the download task it has become. */ -- (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block; +- (void)setDataTaskDidBecomeDownloadTaskBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block; /** Sets a block to be executed when a data task receives data, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveData:`. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the session, the data task, and the data received. This block may be called multiple times, and will execute on the session manager operation queue. */ -- (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block; +- (void)setDataTaskDidReceiveDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block; /** Sets a block to be executed to determine the caching behavior of a data task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:willCacheResponse:completionHandler:`. @param block A block object to be executed to determine the caching behavior of a data task. The block returns the response to cache, and takes three arguments: the session, the data task, and the proposed cached URL response. */ -- (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block; +- (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block; /** Sets a block to be executed once all messages enqueued for a session have been delivered, as handled by the `NSURLSessionDataDelegate` method `URLSessionDidFinishEventsForBackgroundURLSession:`. @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session. */ -- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block; +- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block; ///----------------------------------------------- /// @name Setting Download Task Delegate Callbacks @@ -422,21 +428,21 @@ @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:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; +- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * (^)(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:`. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes five arguments: the session, the download task, the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the session manager operation queue. */ -- (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block; +- (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block; /** Sets a block to be executed when a download task has been resumed, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:`. @param block A block object to be executed when a download task has been resumed. The block has no return value and takes four arguments: the session, the download task, the file offset of the resumed download, and the total number of bytes expected to be downloaded. */ -- (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block; +- (void)setDownloadTaskDidResumeBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block; @end @@ -451,96 +457,98 @@ @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/AFNetworking/AFURLSessionManager.m b/AFNetworking/AFNetworking/AFURLSessionManager.m index 99eadfb..eb28959 100644 --- a/AFNetworking/AFNetworking/AFURLSessionManager.m +++ b/AFNetworking/AFNetworking/AFURLSessionManager.m @@ -154,10 +154,18 @@ - (void)URLSession:(__unused NSURLSession *)session __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer; + //Performance Improvement from #2672 + NSData *data = nil; + if (self.mutableData) { + data = [self.mutableData copy]; + //We no longer need the reference, so nil it out to gain back some memory. + self.mutableData = nil; + } + if (self.downloadFileURL) { userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL; - } else if (self.mutableData) { - userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = [NSData dataWithData:self.mutableData]; + } else if (data) { + userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data; } if (error) { @@ -175,7 +183,7 @@ - (void)URLSession:(__unused NSURLSession *)session } else { dispatch_async(url_session_manager_processing_queue(), ^{ NSError *serializationError = nil; - responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:[NSData dataWithData:self.mutableData] error:&serializationError]; + responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError]; if (self.downloadFileURL) { responseObject = self.downloadFileURL; @@ -316,8 +324,11 @@ + (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 */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" NSURLSessionDataTask *localDataTask = [[NSURLSession sessionWithConfiguration:nil] dataTaskWithURL:nil]; - IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([_AFURLSessionTaskSwizzling class], @selector(af_resume))); +#pragma clang diagnostic pop + IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume))); Class currentClass = [localDataTask class]; while (class_getInstanceMethod(currentClass, @selector(resume))) { @@ -338,12 +349,14 @@ + (void)load { + (void)swizzleResumeAndSuspendMethodForClass:(Class)class { 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(class, @selector(af_resume), afResumeMethod)) { + af_swizzleSelector(class, @selector(resume), @selector(af_resume)); + } + + if (af_addMethod(class, @selector(af_suspend), afSuspendMethod)) { + af_swizzleSelector(class, @selector(suspend), @selector(af_suspend)); + } } - (NSURLSessionTaskState)state { @@ -425,7 +438,9 @@ - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)config self.securityPolicy = [AFSecurityPolicy defaultPolicy]; +#if !TARGET_OS_WATCH self.reachabilityManager = [AFNetworkReachabilityManager sharedManager]; +#endif self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; diff --git a/AFNetworking/README.md b/AFNetworking/README.md index 916a242..f25efe0 100644 --- a/AFNetworking/README.md +++ b/AFNetworking/README.md @@ -256,7 +256,14 @@ NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]}; `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. -**Network reachability is a diagnostic tool that can be used to understand why a request might have failed. It should not be used to determine whether or not to make a request.** +* Do not use Reachability to determine if the original request should be sent. + * You should try to send it. +* You can use Reachability to determine when a request should be automatically retried. + * Although it may still fail, a Reachability notification that the connectivity is available is a good time to retry something. +* 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). #### Shared Network Reachability @@ -264,6 +271,8 @@ NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]}; [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status)); }]; + +[[AFNetworkReachabilityManager sharedManager] startMonitoring]; ``` #### HTTP Manager Reachability diff --git a/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h b/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h index 8242035..3c7649b 100644 --- a/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h +++ b/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** `AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a network request operation has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero. @@ -39,6 +41,7 @@ See the Apple Human Interface Guidelines section about the Network Activity Indicator for more information: http://developer.apple.com/library/iOS/#documentation/UserExperience/Conceptual/MobileHIG/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW44 */ +NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.") @interface AFNetworkActivityIndicatorManager : NSObject /** @@ -72,4 +75,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m b/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m index 82c6cc3..cf13180 100644 --- a/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m +++ b/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m @@ -113,9 +113,7 @@ - (BOOL)isNetworkActivityIndicatorVisible { } - (void)updateNetworkActivityIndicatorVisibility { -#if !defined(AF_APP_EXTENSIONS) [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:[self isNetworkActivityIndicatorVisible]]; -#endif } - (void)setActivityCount:(NSInteger)activityCount { diff --git a/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h index 06e89c4..0c8f9b5 100644 --- a/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h @@ -44,7 +44,7 @@ @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 -- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; +- (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task; #endif ///--------------------------------------- @@ -56,7 +56,7 @@ @param operation The operation. If `nil`, automatic updating from any previously specified operation will be disabled. */ -- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation; +- (void)setAnimatingWithStateOfOperation:(nullable AFURLConnectionOperation *)operation; @end diff --git a/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m b/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m index 1a36091..dd362b0 100644 --- a/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m +++ b/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m @@ -20,6 +20,7 @@ // THE SOFTWARE. #import "UIActivityIndicatorView+AFNetworking.h" +#import #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) @@ -29,8 +30,51 @@ #import "AFURLSessionManager.h" #endif +@interface AFActivityIndicatorViewNotificationObserver : NSObject +@property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView; +- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; +#endif +- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation; + +@end + @implementation UIActivityIndicatorView (AFNetworking) +- (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver { + AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); + if (notificationObserver == nil) { + notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self]; + objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return notificationObserver; +} + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { + [[self af_notificationObserver] setAnimatingWithStateOfTask:task]; +} +#endif + +- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation { + [[self af_notificationObserver] setAnimatingWithStateOfOperation:operation]; +} + +@end + +@implementation AFActivityIndicatorViewNotificationObserver + +- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView +{ + self = [super init]; + if (self) { + _activityIndicatorView = activityIndicatorView; + } + return self; +} + #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; @@ -38,14 +82,19 @@ - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; - + if (task) { if (task.state != NSURLSessionTaskStateCompleted) { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (task.state == NSURLSessionTaskStateRunning) { - [self startAnimating]; + [self.activityIndicatorView startAnimating]; } else { - [self stopAnimating]; + [self.activityIndicatorView stopAnimating]; } +#pragma clang diagnostic pop [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task]; @@ -65,11 +114,16 @@ - (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation { if (operation) { if (![operation isFinished]) { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if ([operation isExecuting]) { - [self startAnimating]; + [self.activityIndicatorView startAnimating]; } else { - [self stopAnimating]; + [self.activityIndicatorView stopAnimating]; } +#pragma clang diagnostic pop [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingOperationDidStartNotification object:operation]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingOperationDidFinishNotification object:operation]; @@ -81,16 +135,37 @@ - (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation { - (void)af_startAnimating { dispatch_async(dispatch_get_main_queue(), ^{ - [self startAnimating]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.activityIndicatorView startAnimating]; +#pragma clang diagnostic pop }); } - (void)af_stopAnimating { dispatch_async(dispatch_get_main_queue(), ^{ - [self stopAnimating]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.activityIndicatorView stopAnimating]; +#pragma clang diagnostic pop }); } +#pragma mark - + +- (void)dealloc { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; +#endif + + [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; +} + @end #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h index 80eddc1..97f5622 100644 --- a/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h @@ -23,10 +23,12 @@ #import -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) #import +NS_ASSUME_NONNULL_BEGIN + @class AFURLConnectionOperation; /** @@ -46,7 +48,7 @@ */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task - delegate:(id)delegate; + delegate:(nullable id)delegate NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); #endif /** @@ -59,9 +61,9 @@ */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task - delegate:(id)delegate - cancelButtonTitle:(NSString *)cancelButtonTitle - otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; + delegate:(nullable id)delegate + cancelButtonTitle:(nullable NSString *)cancelButtonTitle + otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); #endif ///------------------------------------------ @@ -75,7 +77,7 @@ @param delegate The alert view delegate. */ + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation - delegate:(id)delegate; + delegate:(nullable id)delegate NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); /** Shows an alert view with the error of the specified request operation, if any, with a custom cancel button title and other button titles. @@ -86,10 +88,12 @@ @param otherButtonTitles The title of another button. Using this argument is equivalent to invoking addButtonWithTitle: with this title to add more buttons. Too many buttons can cause the alert view to scroll. For guidelines on the best ways to use an alert in an app, see "Temporary Views". Titles of additional buttons to add to the receiver, terminated with `nil`. */ + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation - delegate:(id)delegate - cancelButtonTitle:(NSString *)cancelButtonTitle - otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; + delegate:(nullable id)delegate + cancelButtonTitle:(nullable NSString *)cancelButtonTitle + otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m b/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m index a128544..0d1e9e7 100644 --- a/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m +++ b/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m @@ -21,7 +21,7 @@ #import "UIAlertView+AFNetworking.h" -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) #import "AFURLConnectionOperation.h" diff --git a/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h index 6c09b7a..7289bdb 100644 --- a/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol AFURLResponseSerialization, AFImageCache; /** @@ -41,7 +43,7 @@ ///---------------------------- /** - The image cache used to improve image loadiing performance on scroll views. By default, `UIButton` will use the `sharedImageCache` of `UIImageView`. + The image cache used to improve image loading performance on scroll views. By default, `UIButton` will use the `sharedImageCache` of `UIImageView`. */ + (id )sharedImageCache; @@ -50,7 +52,7 @@ @param imageCache The image cache. */ -+ (void)setSharedImageCache:(id )imageCache; ++ (void)setSharedImageCache:(__nullable id )imageCache; ///------------------------------------ /// @name Accessing Response Serializer @@ -89,7 +91,7 @@ */ - (void)setImageForState:(UIControlState)state withURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage; + placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. @@ -101,14 +103,14 @@ @param state The control state. @param urlRequest The URL request used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. - @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the request and response parameters will be `nil`. + @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes a single argument: the error that occurred. */ - (void)setImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSError *error))failure; + placeholderImage:(nullable UIImage *)placeholderImage + success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(nullable void (^)(NSError *error))failure; ///------------------------------- @@ -137,7 +139,7 @@ */ - (void)setBackgroundImageForState:(UIControlState)state withURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage; + placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. @@ -149,12 +151,14 @@ @param state The control state. @param urlRequest The URL request used for the image request. @param placeholderImage The background image to be set initially, until the background image request finishes. If `nil`, the button will not change its background image until the background image request finishes. + @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the response parameter will be `nil`. + @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes a single argument: the error that occurred. */ - (void)setBackgroundImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSError *error))failure; + placeholderImage:(nullable UIImage *)placeholderImage + success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(nullable void (^)(NSError *error))failure; ///------------------------------ @@ -177,4 +181,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m b/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m index f34631e..e5c36a5 100644 --- a/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m +++ b/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m @@ -121,7 +121,7 @@ @implementation UIButton (AFNetworking) #pragma clang diagnostic pop } -+ (void)setSharedImageCache:(id )imageCache { ++ (void)setSharedImageCache:(__nullable id )imageCache { objc_setAssociatedObject(self, @selector(sharedImageCache), imageCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @@ -165,7 +165,7 @@ - (void)setImageForState:(UIControlState)state - (void)setImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success failure:(void (^)(NSError *error))failure { [self cancelImageRequestOperationForState:state]; @@ -173,7 +173,7 @@ - (void)setImageForState:(UIControlState)state UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { if (success) { - success(nil, nil, cachedImage); + success(urlRequest, nil, cachedImage); } else { [self setImage:cachedImage forState:state]; } @@ -231,7 +231,7 @@ - (void)setBackgroundImageForState:(UIControlState)state - (void)setBackgroundImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success failure:(void (^)(NSError *error))failure { [self cancelBackgroundImageRequestOperationForState:state]; @@ -239,7 +239,7 @@ - (void)setBackgroundImageForState:(UIControlState)state UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { if (success) { - success(nil, nil, cachedImage); + success(urlRequest, nil, cachedImage); } else { [self setBackgroundImage:cachedImage forState:state]; } diff --git a/AFNetworking/UIKit+AFNetworking/UIImage+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIImage+AFNetworking.h new file mode 100644 index 0000000..3292920 --- /dev/null +++ b/AFNetworking/UIKit+AFNetworking/UIImage+AFNetworking.h @@ -0,0 +1,35 @@ +// +// UIImage+AFNetworking.h +// +// +// Created by Paulo Ferreira on 08/07/15. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + +#import + +@interface UIImage (AFNetworking) + ++ (UIImage*) safeImageWithData:(NSData*)data; + +@end + +#endif diff --git a/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h index 2fdff9f..bf61915 100644 --- a/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol AFURLResponseSerialization, AFImageCache; /** @@ -48,7 +50,7 @@ @param imageCache The image cache. */ -+ (void)setSharedImageCache:(id )imageCache; ++ (void)setSharedImageCache:(__nullable id )imageCache; ///------------------------------------ /// @name Accessing Response Serializer @@ -87,7 +89,7 @@ @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. */ - (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage; + placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. @@ -98,13 +100,13 @@ @param urlRequest The URL request used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. - @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the request and response parameters will be `nil`. + @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. */ - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + placeholderImage:(nullable UIImage *)placeholderImage + success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, NSError *error))failure; /** Cancels any executing image operation for the receiver, if one exists. @@ -121,13 +123,13 @@ @protocol AFImageCache /** - Returns a cached image for the specififed request, if available. + Returns a cached image for the specified request, if available. @param request The image request. @return The cached image. */ -- (UIImage *)cachedImageForRequest:(NSURLRequest *)request; +- (nullable UIImage *)cachedImageForRequest:(NSURLRequest *)request; /** Caches a particular image for the specified request. @@ -139,4 +141,6 @@ forRequest:(NSURLRequest *)request; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m b/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m index 1400b4a..2efc160 100644 --- a/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m +++ b/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m @@ -81,7 +81,7 @@ @implementation UIImageView (AFNetworking) #pragma clang diagnostic pop } -+ (void)setSharedImageCache:(id )imageCache { ++ (void)setSharedImageCache:(__nullable id )imageCache { objc_setAssociatedObject(self, @selector(sharedImageCache), imageCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @@ -121,15 +121,15 @@ - (void)setImageWithURL:(NSURL *)url - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, NSError *error))failure { [self cancelImageRequestOperation]; UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { if (success) { - success(nil, nil, cachedImage); + success(urlRequest, nil, cachedImage); } else { self.image = cachedImage; } diff --git a/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h index 94082f6..49850ed 100644 --- a/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if TARGET_OS_IOS #import #ifndef _UIKIT_AFNETWORKING_ @@ -31,8 +32,8 @@ #import "UIAlertView+AFNetworking.h" #import "UIButton+AFNetworking.h" #import "UIImageView+AFNetworking.h" - #import "UIKit+AFNetworking.h" #import "UIProgressView+AFNetworking.h" #import "UIRefreshControl+AFNetworking.h" #import "UIWebView+AFNetworking.h" #endif /* _UIKIT_AFNETWORKING_ */ +#endif diff --git a/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h index 6a4e16f..5c00d6d 100644 --- a/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFURLConnectionOperation; /** @@ -84,4 +86,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h index 18c12ea..a65e390 100644 --- a/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h @@ -28,10 +28,12 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFURLConnectionOperation; /** - This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically begining and ending refreshing depending on the loading state of a request operation or session task. + This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically beginning and ending refreshing depending on the loading state of a request operation or session task. */ @interface UIRefreshControl (AFNetworking) @@ -61,4 +63,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m b/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m index e266451..4c19245 100644 --- a/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m +++ b/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m @@ -21,6 +21,7 @@ // THE SOFTWARE. #import "UIRefreshControl+AFNetworking.h" +#import #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) @@ -30,8 +31,51 @@ #import "AFURLSessionManager.h" #endif +@interface AFRefreshControlNotificationObserver : NSObject +@property (readonly, nonatomic, weak) UIRefreshControl *refreshControl; +- (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; +#endif +- (void)setRefreshingWithStateOfOperation:(AFURLConnectionOperation *)operation; + +@end + @implementation UIRefreshControl (AFNetworking) +- (AFRefreshControlNotificationObserver *)af_notificationObserver { + AFRefreshControlNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); + if (notificationObserver == nil) { + notificationObserver = [[AFRefreshControlNotificationObserver alloc] initWithActivityRefreshControl:self]; + objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return notificationObserver; +} + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { + [[self af_notificationObserver] setRefreshingWithStateOfTask:task]; +} +#endif + +- (void)setRefreshingWithStateOfOperation:(AFURLConnectionOperation *)operation { + [[self af_notificationObserver] setRefreshingWithStateOfOperation:operation]; +} + +@end + +@implementation AFRefreshControlNotificationObserver + +- (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl +{ + self = [super init]; + if (self) { + _refreshControl = refreshControl; + } + return self; +} + #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; @@ -41,15 +85,19 @@ - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; if (task) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (task.state == NSURLSessionTaskStateRunning) { - [self beginRefreshing]; + [self.refreshControl beginRefreshing]; [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidCompleteNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidSuspendNotification object:task]; } else { - [self endRefreshing]; + [self.refreshControl endRefreshing]; } +#pragma clang diagnostic pop } } #endif @@ -61,16 +109,20 @@ - (void)setRefreshingWithStateOfOperation:(AFURLConnectionOperation *)operation [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; if (operation) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (![operation isFinished]) { if ([operation isExecuting]) { - [self beginRefreshing]; + [self.refreshControl beginRefreshing]; } else { - [self endRefreshing]; + [self.refreshControl endRefreshing]; } [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingOperationDidStartNotification object:operation]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingOperationDidFinishNotification object:operation]; } +#pragma clang diagnostic pop } } @@ -78,16 +130,37 @@ - (void)setRefreshingWithStateOfOperation:(AFURLConnectionOperation *)operation - (void)af_beginRefreshing { dispatch_async(dispatch_get_main_queue(), ^{ - [self beginRefreshing]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.refreshControl beginRefreshing]; +#pragma clang diagnostic pop }); } - (void)af_endRefreshing { dispatch_async(dispatch_get_main_queue(), ^{ - [self endRefreshing]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.refreshControl endRefreshing]; +#pragma clang diagnostic pop }); } +#pragma mark - + +- (void)dealloc { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; +#endif + + [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; +} + @end #endif diff --git a/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h b/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h index 56e5832..5d61d6a 100644 --- a/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h +++ b/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h @@ -27,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFHTTPRequestSerializer, AFHTTPResponseSerializer; @protocol AFURLRequestSerialization, AFURLResponseSerialization; @@ -56,9 +58,9 @@ @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. */ - (void)loadRequest:(NSURLRequest *)request - progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress - success:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success - failure:(void (^)(NSError *error))failure; + progress:(nullable void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress + success:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success + failure:(nullable void (^)(NSError *error))failure; /** Asynchronously loads the data associated with a particular request with a specified MIME type and text encoding. @@ -71,12 +73,14 @@ @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. */ - (void)loadRequest:(NSURLRequest *)request - MIMEType:(NSString *)MIMEType - textEncodingName:(NSString *)textEncodingName - progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress - success:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))success - failure:(void (^)(NSError *error))failure; + MIMEType:(nullable NSString *)MIMEType + textEncodingName:(nullable NSString *)textEncodingName + progress:(nullable void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress + success:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))success + failure:(nullable void (^)(NSError *error))failure; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/CocoaLumberjack/Classes/CocoaLumberjack.modulemap b/CocoaLumberjack/Classes/CocoaLumberjack.modulemap deleted file mode 100644 index 8b95381..0000000 --- a/CocoaLumberjack/Classes/CocoaLumberjack.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -framework module CocoaLumberjack { - header "CocoaLumberjack.h" - export * -} diff --git a/CocoaLumberjack/Classes/CocoaLumberjack.swift b/CocoaLumberjack/Classes/CocoaLumberjack.swift index 3562a93..5f022ce 100644 --- a/CocoaLumberjack/Classes/CocoaLumberjack.swift +++ b/CocoaLumberjack/Classes/CocoaLumberjack.swift @@ -14,28 +14,32 @@ // prior written permission of Deusty, LLC. import Foundation -import CocoaLumberjack extension DDLogFlag { public static func fromLogLevel(logLevel: DDLogLevel) -> DDLogFlag { - return DDLogFlag(logLevel.rawValue) + return DDLogFlag(rawValue: logLevel.rawValue) } + + public init(_ logLevel: DDLogLevel) { + self = DDLogFlag(rawValue: logLevel.rawValue) + } ///returns the log level, or the lowest equivalant. public func toLogLevel() -> DDLogLevel { if let ourValid = DDLogLevel(rawValue: self.rawValue) { return ourValid } else { - let logFlag = self - if logFlag & .Verbose == .Verbose { + let logFlag:DDLogFlag = self + + if logFlag.contains(.Verbose) { return .Verbose - } else if logFlag & .Debug == .Debug { + } else if logFlag.contains(.Debug) { return .Debug - } else if logFlag & .Info == .Info { + } else if logFlag.contains(.Info) { return .Info - } else if logFlag & .Warning == .Warning { + } else if logFlag.contains(.Warning) { return .Warning - } else if logFlag & .Error == .Error { + } else if logFlag.contains(.Error) { return .Error } else { return .Off @@ -44,48 +48,44 @@ extension DDLogFlag { } } -extension DDMultiFormatter { - public var formatterArray: [DDLogFormatter] { - return self.formatters as! [DDLogFormatter] - } -} - public var defaultDebugLevel = DDLogLevel.Verbose public func resetDefaultDebugLevel() { defaultDebugLevel = DDLogLevel.Verbose } -public func SwiftLogMacro(isAsynchronous: Bool, level: DDLogLevel, flag flg: DDLogFlag, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, @autoclosure #string: () -> String) { +public func SwiftLogMacro(isAsynchronous: Bool, level: DDLogLevel, flag flg: DDLogFlag, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, @autoclosure string: () -> String) { if level.rawValue & flg.rawValue != 0 { - // Tell the DDLogMessage constructor to copy the C strings that get passed to it. Using string interpolation to prevent integer overflow warning when using StaticString.stringValue - let logMessage = DDLogMessage(message: string(), level: level, flag: flg, context: context, file: "\(file)", function: "\(function)", line: line, tag: tag, options: .CopyFile | .CopyFunction, timestamp: nil) + // Tell the DDLogMessage constructor to copy the C strings that get passed to it. + // Using string interpolation to prevent integer overflow warning when using StaticString.stringValue + let logMessage = DDLogMessage(message: string(), level: level, flag: flg, context: context, file: "\(file)", function: "\(function)", line: line, tag: tag, options: [.CopyFile, .CopyFunction], timestamp: nil) DDLog.log(isAsynchronous, message: logMessage) } } -public func DDLogDebug(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UWord = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { - SwiftLogMacro(async, level, flag: .Debug, context: context, file: file, function: function, line: line, tag: tag, string: logText) +public func DDLogDebug(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { + SwiftLogMacro(async, level: level, flag: .Debug, context: context, file: file, function: function, line: line, tag: tag, string: logText) } -public func DDLogInfo(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UWord = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { - SwiftLogMacro(async, level, flag: .Info, context: context, file: file, function: function, line: line, tag: tag, string: logText) +public func DDLogInfo(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { + SwiftLogMacro(async, level: level, flag: .Info, context: context, file: file, function: function, line: line, tag: tag, string: logText) } -public func DDLogWarn(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UWord = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { - SwiftLogMacro(async, level, flag: .Warning, context: context, file: file, function: function, line: line, tag: tag, string: logText) +public func DDLogWarn(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { + SwiftLogMacro(async, level: level, flag: .Warning, context: context, file: file, function: function, line: line, tag: tag, string: logText) } -public func DDLogVerbose(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UWord = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { - SwiftLogMacro(async, level, flag: .Verbose, context: context, file: file, function: function, line: line, tag: tag, string: logText) +public func DDLogVerbose(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { + SwiftLogMacro(async, level: level, flag: .Verbose, context: context, file: file, function: function, line: line, tag: tag, string: logText) } -public func DDLogError(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UWord = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = true) { - SwiftLogMacro(async, level, flag: .Error, context: context, file: file, function: function, line: line, tag: tag, string: logText) +public func DDLogError(@autoclosure logText: () -> String, level: DDLogLevel = defaultDebugLevel, context: Int = 0, file: StaticString = __FILE__, function: StaticString = __FUNCTION__, line: UInt = __LINE__, tag: AnyObject? = nil, asynchronous async: Bool = false) { + SwiftLogMacro(async, level: level, flag: .Error, context: context, file: file, function: function, line: line, tag: tag, string: logText) } -/// Analogous to the C preprocessor macro THIS_FILE +/// Analogous to the C preprocessor macro `THIS_FILE`. public func CurrentFileName(fileName: StaticString = __FILE__) -> String { // Using string interpolation to prevent integer overflow warning when using StaticString.stringValue - return "\(fileName)".lastPathComponent.stringByDeletingPathExtension + // This double-casting to NSString is necessary as changes to how Swift handles NSPathUtilities requres the string to be an NSString + return (("\(fileName)" as NSString).lastPathComponent as NSString).stringByDeletingPathExtension } diff --git a/CocoaLumberjack/Classes/DDASLLogCapture.h b/CocoaLumberjack/Classes/DDASLLogCapture.h index c87d0b1..f7fa79f 100644 --- a/CocoaLumberjack/Classes/DDASLLogCapture.h +++ b/CocoaLumberjack/Classes/DDASLLogCapture.h @@ -22,11 +22,27 @@ */ @interface DDASLLogCapture : NSObject +/** + * Start capturing logs + */ + (void)start; + +/** + * Stop capturing logs + */ + (void)stop; -// Default log level: DDLogLevelVerbose (i.e. capture all ASL messages). +/** + * Returns the current capture level. + * @note Default log level: DDLogLevelVerbose (i.e. capture all ASL messages). + */ + (DDLogLevel)captureLevel; + +/** + * Set the capture level + * + * @param level new level + */ + (void)setCaptureLevel:(DDLogLevel)level; @end diff --git a/CocoaLumberjack/Classes/DDASLLogCapture.m b/CocoaLumberjack/Classes/DDASLLogCapture.m index bb7f4c8..98d5342 100644 --- a/CocoaLumberjack/Classes/DDASLLogCapture.m +++ b/CocoaLumberjack/Classes/DDASLLogCapture.m @@ -99,7 +99,7 @@ + (void)configureAslQuery:(aslmsg)query { // Don't retrieve logs from our own DDASLLogger asl_set_query(query, kDDASLKeyDDLog, kDDASLDDLogValue, ASL_QUERY_OP_NOT_EQUAL); -#if !TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR +#if !TARGET_OS_IPHONE || TARGET_SIMULATOR int processId = [[NSProcessInfo processInfo] processIdentifier]; char pid[16]; sprintf(pid, "%d", processId); diff --git a/CocoaLumberjack/Classes/DDASLLogger.h b/CocoaLumberjack/Classes/DDASLLogger.h index 57c5f58..24cc1c3 100644 --- a/CocoaLumberjack/Classes/DDASLLogger.h +++ b/CocoaLumberjack/Classes/DDASLLogger.h @@ -32,7 +32,7 @@ extern const char* const kDDASLDDLogValue; * This class provides a logger for the Apple System Log facility. * * As described in the "Getting Started" page, - * the traditional NSLog() function directs it's output to two places: + * the traditional NSLog() function directs its output to two places: * * - Apple System Log * - StdErr (if stderr is a TTY) so log statements show up in Xcode console @@ -41,9 +41,13 @@ extern const char* const kDDASLDDLogValue; * However, if you instead choose to use file logging (for faster performance), * you may choose to use a file logger and a tty logger. **/ - @interface DDASLLogger : DDAbstractLogger +/** + * Singleton method + * + * @return the shared instance + */ + (instancetype)sharedInstance; // Inherited from DDAbstractLogger diff --git a/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h b/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h index 745a91b..aad3666 100644 --- a/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h +++ b/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h @@ -27,7 +27,6 @@ * All that is needed for a concrete database logger is to extend this class * and override the methods in the implementation file that are prefixed with "db_". **/ - @interface DDAbstractDatabaseLogger : DDAbstractLogger { @protected @@ -67,6 +66,10 @@ * The default saveInterval is 60 seconds. **/ @property (assign, readwrite) NSUInteger saveThreshold; + +/** + * See the description for the `saveThreshold` property + */ @property (assign, readwrite) NSTimeInterval saveInterval; /** @@ -96,7 +99,15 @@ * The default deleteOnEverySave is NO. **/ @property (assign, readwrite) NSTimeInterval maxAge; + +/** + * See the description for the `maxAge` property + */ @property (assign, readwrite) NSTimeInterval deleteInterval; + +/** + * See the description for the `maxAge` property + */ @property (assign, readwrite) BOOL deleteOnEverySave; /** diff --git a/CocoaLumberjack/Classes/DDFileLogger.h b/CocoaLumberjack/Classes/DDFileLogger.h index d2f9ebb..f0bfdb6 100644 --- a/CocoaLumberjack/Classes/DDFileLogger.h +++ b/CocoaLumberjack/Classes/DDFileLogger.h @@ -46,28 +46,29 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota; #pragma mark - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// The LogFileManager protocol is designed to allow you to control all aspects of your log files. -// -// The primary purpose of this is to allow you to do something with the log files after they have been rolled. -// Perhaps you want to compress them to save disk space. -// Perhaps you want to upload them to an FTP server. -// Perhaps you want to run some analytics on the file. -// -// A default LogFileManager is, of course, provided. -// The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property. -// -// This protocol provides various methods to fetch the list of log files. -// -// There are two variants: sorted and unsorted. -// If sorting is not necessary, the unsorted variant is obviously faster. -// The sorted variant will return an array sorted by when the log files were created, -// with the most recently created log file at index 0, and the oldest log file at the end of the array. -// -// You can fetch only the log file paths (full path including name), log file names (name only), -// or an array of DDLogFileInfo objects. -// The DDLogFileInfo class is documented below, and provides a handy wrapper that -// gives you easy access to various file attributes such as the creation date or the file size. - +/** + * The LogFileManager protocol is designed to allow you to control all aspects of your log files. + * + * The primary purpose of this is to allow you to do something with the log files after they have been rolled. + * Perhaps you want to compress them to save disk space. + * Perhaps you want to upload them to an FTP server. + * Perhaps you want to run some analytics on the file. + * + * A default LogFileManager is, of course, provided. + * The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property. + * + * This protocol provides various methods to fetch the list of log files. + * + * There are two variants: sorted and unsorted. + * If sorting is not necessary, the unsorted variant is obviously faster. + * The sorted variant will return an array sorted by when the log files were created, + * with the most recently created log file at index 0, and the oldest log file at the end of the array. + * + * You can fetch only the log file paths (full path including name), log file names (name only), + * or an array of `DDLogFileInfo` objects. + * The `DDLogFileInfo` class is documented below, and provides a handy wrapper that + * gives you easy access to various file attributes such as the creation date or the file size. + */ @protocol DDLogFileManager @required @@ -93,25 +94,70 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota; // Public methods +/** + * Returns the logs directory (path) + */ - (NSString *)logsDirectory; +/** + * Returns an array of `NSString` objects, + * each of which is the filePath to an existing log file on disk. + **/ - (NSArray *)unsortedLogFilePaths; + +/** + * Returns an array of `NSString` objects, + * each of which is the fileName of an existing log file on disk. + **/ - (NSArray *)unsortedLogFileNames; + +/** + * Returns an array of `DDLogFileInfo` objects, + * each representing an existing log file on disk, + * and containing important information about the log file such as it's modification date and size. + **/ - (NSArray *)unsortedLogFileInfos; +/** + * Just like the `unsortedLogFilePaths` method, but sorts the array. + * The items in the array are sorted by creation date. + * The first item in the array will be the most recently created log file. + **/ - (NSArray *)sortedLogFilePaths; + +/** + * Just like the `unsortedLogFileNames` method, but sorts the array. + * The items in the array are sorted by creation date. + * The first item in the array will be the most recently created log file. + **/ - (NSArray *)sortedLogFileNames; + +/** + * Just like the `unsortedLogFileInfos` method, but sorts the array. + * The items in the array are sorted by creation date. + * The first item in the array will be the most recently created log file. + **/ - (NSArray *)sortedLogFileInfos; // Private methods (only to be used by DDFileLogger) +/** + * Generates a new unique log file path, and creates the corresponding log file. + **/ - (NSString *)createNewLogFile; @optional // Notifications from DDFileLogger +/** + * Called when a log file was archieved + */ - (void)didArchiveLogFile:(NSString *)logFilePath; + +/** + * Called when the roll action was executed and the log was archieved + */ - (void)didRollAndArchiveLogFile:(NSString *)logFilePath; @end @@ -125,18 +171,26 @@ extern unsigned long long const kDDDefaultLogFilesDiskQuota; * * All log files are placed inside the logsDirectory. * If a specific logsDirectory isn't specified, the default directory is used. - * On Mac, this is in ~/Library/Logs/. - * On iPhone, this is in ~/Library/Caches/Logs. + * On Mac, this is in `~/Library/Logs/`. + * On iPhone, this is in `~/Library/Caches/Logs`. * - * Log files are named "