Source/TNL_Project.h (139 lines of code) (raw):

// // TNL_Project.h // TwitterNetworkLayer // // Created on 5/24/14. // Copyright © 2020 Twitter, Inc. All rights reserved. // #import "TNL_ProjectCommon.h" #import "TNLError.h" #import "TNLInternalKeys.h" NS_ASSUME_NONNULL_BEGIN /* * NOTE: this header is private to TNL */ #pragma mark - Convenience Macros /** These are convenience macros for speeding up the creation of "setters" of mutable objects that subclass immutable objects in order to expose the existing propert(y/ies) as mutable - (void)setSomeProperty:(id)someProperty PROP_RETAIN_ASSIGN_IMP(someProperty); */ #define PROP_RETAIN_ASSIGN_IMP(var) \ { \ if (_##var != var) { \ _##var = var; \ } \ } #define PROP_COPY_IMP(var) \ { \ if (_##var != var) { \ _##var = [var copy]; \ } \ } #define IS_EQUAL_OBJ_PROP_CHECK(self, other, prop) \ do { \ if (self.prop) { \ if (![self.prop isEqual:other.prop]) { \ return NO; \ } \ } else if (other.prop) { \ return NO; \ } \ } while (0) #pragma mark - Brotli SDK Check #define TARGET_SDK_SUPPORTS_BROTLI 0 #if TARGET_OS_IOS #if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0) #undef TARGET_SDK_SUPPORTS_BROTLI #define TARGET_SDK_SUPPORTS_BROTLI 1 #endif #elif TARGET_OS_TV #if defined(__TVOS_11_0) && (__TV_OS_VERSION_MAX_ALLOWED >= __TVOS_11_0) #undef TARGET_SDK_SUPPORTS_BROTLI #define TARGET_SDK_SUPPORTS_BROTLI 1 #endif #elif TARGET_OS_WATCH #if defined(__WATCHOS_4_0) && (__WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_4_0) #undef TARGET_SDK_SUPPORTS_BROTLI #define TARGET_SDK_SUPPORTS_BROTLI 1 #endif #elif TARGET_OS_OSX #if defined(__MAC_10_13) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_13) #undef TARGET_SDK_SUPPORTS_BROTLI #define TARGET_SDK_SUPPORTS_BROTLI 1 #endif #else // Unexpected target, assume Brotli supported #define TARGET_SDK_SUPPORTS_BROTLI 1 #endif #pragma mark - Version FOUNDATION_EXTERN NSString *TNLVersion(void); #pragma mark - GCD Helpers #define MIN_TIMER_INTERVAL (0.1) #define TIMER_LEEWAY_WITH_FIRE_INTERVAL(x) MIN((x) / 10.0, 4.0) FOUNDATION_EXTERN dispatch_source_t tnl_dispatch_timer_create_and_start(dispatch_queue_t queue, NSTimeInterval interval, NSTimeInterval leeway, BOOL repeats, dispatch_block_t fireBlock); NS_INLINE void tnl_dispatch_timer_invalidate(dispatch_source_t __nullable timerSource) { if (timerSource) { dispatch_source_cancel(timerSource); } } #pragma mark - Threading FOUNDATION_EXTERN NSOperationQueue *TNLNetworkOperationQueue(void); FOUNDATION_EXTERN dispatch_queue_t tnl_network_queue(void); FOUNDATION_EXTERN dispatch_queue_t tnl_coding_queue(void); #define TNLAssertIsNetworkQueue() TNLAssert(dispatch_queue_get_label(tnl_network_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) #define TNLAssertIsCodingQueue() TNLAssert(dispatch_queue_get_label(tnl_coding_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) #pragma mark - Dynamic Linking #if TARGET_OS_IOS || TARGET_OS_TV NS_ASSUME_NONNULL_END #import <UIKit/UIApplication.h> NS_ASSUME_NONNULL_BEGIN FOUNDATION_EXTERN UIApplication * __nullable TNLDynamicUIApplicationSharedApplication(void); FOUNDATION_EXTERN Class __nullable TNLDynamicUIApplicationClass(void); #endif // TARGET_OS_IOS || TARGET_OS_TV #pragma mark - Logging #ifndef ENABLE_LOG_METHODS #define ENABLE_LOG_METHODS 0 #endif #if ENABLE_LOG_METHODS #define METHOD_LOG() TNLLogDebug(NSStringFromClass([self class]), @"%@", NSStringFromSelector(_cmd)) #else #define METHOD_LOG() ((void)0) #endif #define TNLLogVerboseEnabled() ([gTNLLogger respondsToSelector:@selector(tnl_shouldLogVerbosely)] ? [gTNLLogger tnl_shouldLogVerbosely] : NO) #if TARGET_OS_OSX #define TNL_LOG_WAITS_FOR_CONNECTIVITY_WARNING() \ TNLLogWarning(@"#FB7027774: Cannot modify -[TNLRequestConfiguration connectivityOptions] on macOS %li.%li.%li", (long)[NSProcessInfo processInfo].operatingSystemVersion.majorVersion, (long)[NSProcessInfo processInfo].operatingSystemVersion.minorVersion, (long)[NSProcessInfo processInfo].operatingSystemVersion.patchVersion) #elif TARGET_OS_IPHONE && !TARGET_OS_WATCH #define TNL_LOG_WAITS_FOR_CONNECTIVITY_WARNING() \ TNLLogWarning(@"#FB7027774: Cannot modify -[TNLRequestConfiguration connectivityOptions] on %@ %@", [UIDevice currentDevice].systemName, [UIDevice currentDevice].systemVersion) #else #define TNL_LOG_WAITS_FOR_CONNECTIVITY_WARNING() \ TNLLogWarning(@"#FB7027774: Cannot modify -[TNLRequestConfiguration connectivityOptions]") #endif #pragma mark - Introspection #if DEBUG @interface NSObject (Introspection) // existing private methods on NSObject that can be exposed for debugging purposes - (null_unspecified id)_shortMethodDescription; // lists all the instance and class methods of the receiver, - (null_unspecified id)_methodDescription; // does the same, including the superclasses' methods, - (null_unspecified id)_ivarDescription; // lists all the instance variables of the receiver, their type, and their value. @end #endif /** Returns an array of NSValues. Each value encapsulates a SEL. SEL selector = [(NSValue *)selectorsArray[i] pointerValue]; */ FOUNDATION_EXTERN NSArray<NSValue *> * __nullable TNLIntrospection_SelectorsForProtocol(Protocol *p, BOOL requiredMethods, BOOL instanceMethods); /** Returns YES iff the object implements at least one method from the given protocol. Sometimes, respondsToSelector: can be overridden - provide YES for avoidRespondsToSelector to bypass inspecting the object with that method and use direct introspection instead. */ FOUNDATION_EXTERN BOOL TNLIntrospection_ObjectImplementsAnyProtocolInstanceMethod(id object, Protocol *p, BOOL avoidRespondsToSelector); /** Returns YES iff the protocol contains the given selector as an instance method */ FOUNDATION_EXTERN BOOL TNLIntrospection_ProtocolContainsIntanceMethodSelector(Protocol *p, SEL selector); /** Returns YES iff the object implements all the protocol instance methods of the provided protocol. Sometimes, respondsToSelector: can be overridden - provide YES for avoidRespondsToSelector to bypass inspecting the object with that method and use direct introspection instead. */ FOUNDATION_EXTERN BOOL TNLIntrospection_ObjectImplementsAllProtocolInstanceMethods(id object, Protocol *p, BOOL avoidRespondsToSelector); #pragma mark - Debugging Tools #if DEBUG // Add this to inits of objects to track FOUNDATION_EXTERN void TNLIncrementObjectCount(Class class); // Add this to deallocs of objects to track FOUNDATION_EXTERN void TNLDecrementObjectCount(Class class); #else #define TNLIncrementObjectCount(class) ((void)0) #define TNLDecrementObjectCount(class) ((void)0) #endif #pragma mark - Error Helpers FOUNDATION_EXTERN NSError *TNLErrorCreateWithCode(TNLErrorCode code); FOUNDATION_EXTERN NSError *TNLErrorCreateWithCodeAndUnderlyingError(TNLErrorCode code, NSError * __nullable underlyingError); FOUNDATION_EXTERN NSError *TNLErrorCreateWithCodeAndUserInfo(TNLErrorCode code, NSDictionary * __nullable userInfo); #if TARGET_OS_WATCH #define kCFErrorDomainCFNetwork @"kCFErrorDomainCFNetwork" #endif NS_ASSUME_NONNULL_END