TwitterImagePipeline/TIPImageFetchRequest.h (97 lines of code) (raw):

// // TIPImageFetchRequest.h // TwitterImagePipeline // // Created on 1/21/16. // Copyright © 2020 Twitter. All rights reserved. // #import <TwitterImagePipeline/TIPDefinitions.h> #import <TwitterImagePipeline/TIPProgressive.h> @protocol TIPImageFetchOperationUnderlyingContext; @protocol TIPImageFetchTransformer; NS_ASSUME_NONNULL_BEGIN FOUNDATION_EXTERN const NSTimeInterval TIPTimeToLiveDefault; // 30 days //! Block to call with the hydrated `NSURLRequest` when hydration is triggered typedef void(^TIPImageFetchHydrationCompletionBlock)(NSURLRequest * __nullable hydratedRequest, NSError * __nullable error); //! Block to hydrate an `NSURLRequest` for a given _context_ typedef void(^TIPImageFetchHydrationBlock)(NSURLRequest *requestToHydrate, id<TIPImageFetchOperationUnderlyingContext> context, TIPImageFetchHydrationCompletionBlock complete); //! Block to call with the _Authorization_ string when authorizing an `NSURLRequest` is triggered typedef void(^TIPImageFetchAuthorizationCompletionBlock)(NSString * __nullable authorizationString, NSError * __nullable error); //! Block to provide the Authorization for a given `NSURLRequest` (and its _context_) typedef void(^TIPImageFetchAuthorizationBlock)(NSURLRequest *requestToAuthorize, id<TIPImageFetchOperationUnderlyingContext> context, TIPImageFetchAuthorizationCompletionBlock complete); /** Options for a `TIPImageFetchRequest` */ typedef NS_OPTIONS(NSInteger, TIPImageFetchOptions) { /** No options - default behavior */ TIPImageFetchNoOptions = 0, /** Don't reset the expiry when accessed */ TIPImageFetchDoNotResetExpiryOnAccess = 1 << 0, /** When a matching `imageIdentifier` is fetched/stored that doesn't match this fetch's `imageURL`, clear this store request's results from cache. Useful for _"placeholder"_ fetches/stores that might have the same (or larger) dimensions as a non-placeholder fetch/store. */ TIPImageFetchTreatAsPlaceholder = 1 << 1, /** Don't store to rendered cache. Useful for known large views that will not need to be synchronously rendered in the future. Example: a full screen view of an image is something that users opt into and not something passively viewed like in a timeline, those fetches should provide `.SkipStoringToRenderedCache` to avoid bloating the rendered cache with media that doesn't require synchronous access. */ TIPImageFetchSkipStoringToRenderedCache = 1 << 2, }; /** `TIPImageFetchRequest` is a protocol that is to be implemented by an object for encapsulating the relevant information for retrieving an image via a `TIPImagePipeline`. */ @protocol TIPImageFetchRequest <NSObject> @required /** The only required property is the `NSURL` of the image to load from the _Network_. */ @property (nonatomic, readonly) NSURL *imageURL; @optional /** The identifier for an image that is devoid of sizing related information. This will be used for matching against existing cached images. If not provided (or `nil`), `[imageURL absoluteString]` will be used instead. */ @property (nonatomic, readonly, copy, nullable) NSString *imageIdentifier; /** The pixel dimensions (not points) of the target for displaying the image. Must be paired with `targetContentMode` to have any effect. This value (and `targetContentMode`) are used for scaling the source image to the size desired for the target (such as a `UIImageView`) and has no impact on what source image is loaded. If you do not provide target sizing information you risk having your target view scale the resulting `UIImage` on the main thread, which is expensive and will absolutely yield a drop in FPS. Default == `CGSizeZero` indicating the target's dimensions are unknown. */ @property (nonatomic, readonly) CGSize targetDimensions; /** The `UIViewContentMode` of the target for displaying the image. Must be paired with `targetDimensions` to have any effect. This value (and `targetDimensions`) are used for scaling the source image to the size desired for the target (such as a `UIImageView`) and has no impact on what source image is loaded. If you do not provide target sizing information you risk having your target view scale the resulting `UIImage` on the main thread, which is expensive and will absolutely yield a drop in FPS. Default == `UIViewContentModeCenter` indicating the image won't be constrained to any specified dimensions. See `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFit` and/or `UIViewContentModeScaleAspectFill` for constrained content modes. @note only _targetContentMode_ values that have `UIViewContentModeScale*` will be scaled (others are just positional and do not scale) */ @property (nonatomic, readonly) UIViewContentMode targetContentMode; /** The duration that the image will live in the `TIPImagePipeline`'s internal cache(s) if fetched from the _Network_. Default == `TIPTimeToLiveDefault` */ @property (nonatomic, readonly) NSTimeInterval timeToLive; /** The options for the fetch. Default == `TIPImageFetchNoOptions` */ @property (nonatomic, readonly) TIPImageFetchOptions options; /** The `TIPImageFetchProgressiveLoadingPolicy` instances for progressively loading images. The keys should be _TIPImageType_ values (which are `NSString` objects). Any unspecified _TIPImageType_ values will use the fallback policy for that type. Default == `nil`. Fallback is `TIPImageFetchProgressiveLoadingPolicyDefaultPolicies()` See `TIPImageFetchDelegate` and `TIPImageTypes.h` */ @property (nonatomic, readonly, copy, nullable) NSDictionary<NSString *, id<TIPImageFetchProgressiveLoadingPolicy>> *progressiveLoadingPolicies; /** Provide a `TIPImageFetchTransformer` to support transforming the fetched image. @note providing a transformer will scope what synchronous render cached images can be fetched based on the `tip_transformerIdentifier` of the transformer. */ @property (nonatomic, readonly, nullable) id<TIPImageFetchTransformer> transformer; /** Specify where to load from. Default == `TIPImageFetchLoadingSourcesAll` */ @property (nonatomic, readonly) TIPImageFetchLoadingSources loadingSources; /** The `TIPImageFetchHydrationBlock` to use when retrieving the image over the _Network_. Use this to modify the `NSURLRequest` that will be loaded over the _Network_. This can be valuable for providing custom headers like the User-Agent to the _HTTP Request_ that will be sent. The `imageRequestHydrationBlock` MUST NOT change the `URL` nor the _HTTP Method_, otherwise doing so will yield an error. Default == `nil` @note It is best to avoid using this hydration block for _Authorization_ header population and better to use `imageRequestAuthorizationBlock` for authorization. We won't enforce it, but to preserve the flow of network request construction, we recommend keeping authorization separate from hydration. */ @property (nonatomic, readonly, copy, nullable) TIPImageFetchHydrationBlock imageRequestHydrationBlock; /** The `TIPImageFetchAuthorizationBlock` to use for signing the `NSURLRequest` to load the image over the _Network_. Use this to provide an _Authorization_ header value to load the image. Default == `nil` */ @property (nonatomic, readonly, copy, nullable) TIPImageFetchAuthorizationBlock imageRequestAuthorizationBlock; /** An optional decoder config map. Can be useful for custom decoder behavior. */ @property (nonatomic, readonly, copy, nullable) NSDictionary<NSString *, id> *decoderConfigMap; @end /** Extended TIPImageFetchRequest that enforces mutable target sizing properties being available. */ @protocol TIPMutableTargetSizingImageFetchRequest <TIPImageFetchRequest> @required /** The pixel dimensions (not points) of the target for displaying the image. Default should be `CGSizeZero` indicating the target's dimensions are unknown. See `[TIPImageFetchRequest targetDimensions]` */ @property (nonatomic) CGSize targetDimensions; /** The `UIViewContentMode` of the target for displaying the image. Default should be `UIViewContentModeCenter` indicating the image won't be constrained to any specified dimensions. See `[TIPImageFetchRequest targetContentMode]` */ @property (nonatomic) UIViewContentMode targetContentMode; @end ///! Convenience function to get the imageIdentifier from a `TIPImageFetchRequest` NS_INLINE NSString *TIPImageFetchRequestGetImageIdentifier(id<TIPImageFetchRequest> request) { NSString *imageIdentifier = nil; if ([request respondsToSelector:@selector(imageIdentifier)]) { imageIdentifier = request.imageIdentifier; } if (!imageIdentifier) { imageIdentifier = request.imageURL.absoluteString; } return imageIdentifier; } @class TIPMutableGenericImageFetchRequest; /** * Generic fetch request */ @interface TIPGenericImageFetchRequest : NSObject <TIPImageFetchRequest, NSCopying, NSMutableCopying> @property (nonatomic, readonly) NSURL *imageURL; @property (nonatomic, readonly, copy, nullable) NSString *imageIdentifier; @property (nonatomic, readonly) CGSize targetDimensions; @property (nonatomic, readonly) UIViewContentMode targetContentMode; @property (nonatomic, readonly) NSTimeInterval timeToLive; @property (nonatomic, readonly) TIPImageFetchOptions options; @property (nonatomic, readonly, copy, nullable) NSDictionary<NSString *, id<TIPImageFetchProgressiveLoadingPolicy>> *progressiveLoadingPolicies; @property (nonatomic, readonly, nullable) id<TIPImageFetchTransformer> transformer; @property (nonatomic, readonly) TIPImageFetchLoadingSources loadingSources; @property (nonatomic, readonly, copy, nullable) TIPImageFetchHydrationBlock imageRequestHydrationBlock; @property (nonatomic, readonly, copy, nullable) TIPImageFetchAuthorizationBlock imageRequestAuthorizationBlock; @property (nonatomic, readonly, copy, nullable) NSDictionary<NSString *, id> *decoderConfigMap; - (instancetype)initWithImageURL:(NSURL *)imageURL identifier:(nullable NSString *)imageIdentifier targetDimensions:(CGSize)dims targetContentMode:(UIViewContentMode)mode NS_DESIGNATED_INITIALIZER; - (instancetype)initWithImageURL:(NSURL *)imageURL; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; + (instancetype)genericImageFetchRequestWithRequest:(id<TIPImageFetchRequest>)request; - (TIPGenericImageFetchRequest *)copy; - (TIPGenericImageFetchRequest *)copyWithZone:(nullable NSZone *)zone; - (TIPMutableGenericImageFetchRequest *)mutableCopy; - (TIPMutableGenericImageFetchRequest *)mutableCopyWithZone:(nullable NSZone *)zone; @end /** * Generic fetch request (mutable) */ @interface TIPMutableGenericImageFetchRequest : TIPGenericImageFetchRequest <TIPMutableTargetSizingImageFetchRequest> @property (nonatomic) NSURL *imageURL; @property (nonatomic, copy, nullable) NSString *imageIdentifier; @property (nonatomic) CGSize targetDimensions; @property (nonatomic) UIViewContentMode targetContentMode; @property (nonatomic) NSTimeInterval timeToLive; @property (nonatomic) TIPImageFetchOptions options; @property (nonatomic, copy, nullable) NSDictionary<NSString *, id<TIPImageFetchProgressiveLoadingPolicy>> *progressiveLoadingPolicies; @property (nonatomic, nullable) id<TIPImageFetchTransformer> transformer; @property (nonatomic) TIPImageFetchLoadingSources loadingSources; @property (nonatomic, copy, nullable) TIPImageFetchHydrationBlock imageRequestHydrationBlock; @property (nonatomic, copy, nullable) TIPImageFetchAuthorizationBlock imageRequestAuthorizationBlock; @property (nonatomic, copy, nullable) NSDictionary<NSString *, id> *decoderConfigMap; @end NS_ASSUME_NONNULL_END