Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuring imageCache when initializing ASPINRemoteImageDownloader. #1197

Merged
merged 8 commits into from
Nov 4, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## master
* Add your own contributions to the next release on the line below this with your name.
- [ASPINRemoteImageManager] Allow specifying an image cache when configuring ASPINRemoteImageManager. [Kevin Smith](https://github.com/wiseoldduck). [#1197](https://github.com/TextureGroup/Texture/pull/1197)
- [ASDisplayNode.m] Make sure node is loaded before enter visible. [Max Wang](https://github.com/wsdwsd0829). [#886](https://github.com/TextureGroup/Texture/pull/886)
- [ASTextNode2] Add improved support for all line-break modes in experimental text node. [Kevin Smith](https://github.com/wiseoldduck). [#1150](https://github.com/TextureGroup/Texture/pull/1150)
- [ASExperimentalFeatures.m] Fix mismatch name in experimental features. [Max Wang](https://github.com/wsdwsd0829). [#1159](https://github.com/TextureGroup/Texture/pull/1159)
Expand Down
17 changes: 15 additions & 2 deletions Source/Details/ASPINRemoteImageDownloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
NS_ASSUME_NONNULL_BEGIN

@class PINRemoteImageManager;
@protocol PINRemoteImageCaching;

@interface ASPINRemoteImageDownloader : NSObject <ASImageCacheProtocol, ASImageDownloaderProtocol>

Expand All @@ -28,7 +29,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (ASPINRemoteImageDownloader *)sharedDownloader NS_RETURNS_RETAINED;


/**
* Sets the default NSURLSessionConfiguration that will be used by @c ASNetworkImageNodes and @c ASMultiplexImageNodes
* while loading images off the network. This must be specified early in the application lifecycle before
Expand All @@ -39,6 +39,19 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration;

/**
* Sets the default NSURLSessionConfiguration that will be used by @c ASNetworkImageNodes and @c ASMultiplexImageNodes
* while loading images off the network. This must be specified early in the application lifecycle before
* `sharedDownloader` is accessed.
*
* @param configuration The session configuration that will be used by `sharedDownloader`
* @param imageCache The cache to be used by PINRemoteImage - nil will set up a default cache: PINCache
* if it is available, PINRemoteImageBasicCache (NSCache) if not.
*
*/
+ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration
imageCache:(nullable id<PINRemoteImageCaching>)imageCache;

/**
* Sets a custom preconfigured PINRemoteImageManager that will be used by @c ASNetworkImageNodes and @c ASMultiplexImageNodes
* while loading images off the network. This must be specified early in the application lifecycle before
Expand All @@ -47,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @param preconfiguredPINRemoteImageManager The preconfigured remote image manager that will be used by `sharedDownloader`
*/
+ (void)setSharedPreconfiguredRemoteImageManager:(nullable PINRemoteImageManager *)preconfiguredPINRemoteImageManager;
+ (void)setSharedPreconfiguredRemoteImageManager:(PINRemoteImageManager *)preconfiguredPINRemoteImageManager;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we remove the nullable here it does not match with the implementation. Any reason we removed it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should change the implementation if I didn't. It makes no sense to call this with nil, to support it would be to add a check right away along the lines of if (preconfiguredPINRemoteImageManager == nil) return; which is silly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing nullable here is fine. It doesn't make sense to pass in a nil manager here anyway, and it isn't obvious what the framework would do in that case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I did actually also change the implementation so I'm happy with this as is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also update the doc comments. The doc still say passing in a nil as the PINRemoteImageManager, it will create a default one.


/**
* The shared instance of a @c PINRemoteImageManager used by all @c ASPINRemoteImageDownloaders
Expand Down
84 changes: 47 additions & 37 deletions Source/Details/ASPINRemoteImageDownloader.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ @interface ASPINRemoteImageManager : PINRemoteImageManager
@implementation ASPINRemoteImageManager

//Share image cache with sharedImageManager image cache.
- (id <PINRemoteImageCaching>)defaultImageCache
+ (id <PINRemoteImageCaching>)defaultImageCache
{
static dispatch_once_t onceToken;
static id <PINRemoteImageCaching> cache = nil;
Expand Down Expand Up @@ -106,7 +106,6 @@ @implementation ASPINRemoteImageDownloader

+ (ASPINRemoteImageDownloader *)sharedDownloader NS_RETURNS_RETAINED
{

static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedDownloader = [[ASPINRemoteImageDownloader alloc] init];
Expand All @@ -116,56 +115,67 @@ + (ASPINRemoteImageDownloader *)sharedDownloader NS_RETURNS_RETAINED

+ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration
{
NSAssert(sharedDownloader == nil, @"Singleton has been created and session can no longer be configured.");
NSAssert1(sharedPINRemoteImageManager == nil, @"An instance of %@ has been set. Either configuration or preconfigured image manager can be set at a time and only once.", [[sharedPINRemoteImageManager class] description]);
__unused PINRemoteImageManager *sharedManager = [self sharedPINRemoteImageManagerWithConfiguration:configuration preconfiguredPINRemoteImageManager:nil];
PINRemoteImageManager *sharedManager = [self PINRemoteImageManagerWithConfiguration:configuration imageCache:nil];
[self setSharedPreconfiguredRemoteImageManager:sharedManager];
}

+ (void)setSharedPreconfiguredRemoteImageManager:(nullable PINRemoteImageManager *)preconfiguredPINRemoteImageManager
+ (void)setSharedImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration
imageCache:(nullable id<PINRemoteImageCaching>)imageCache
{
PINRemoteImageManager *sharedManager = [self PINRemoteImageManagerWithConfiguration:configuration imageCache:imageCache];
[self setSharedPreconfiguredRemoteImageManager:sharedManager];
}

static dispatch_once_t shared_init_predicate;

+ (void)setSharedPreconfiguredRemoteImageManager:(PINRemoteImageManager *)preconfiguredPINRemoteImageManager
{
NSAssert(sharedDownloader == nil, @"Singleton has been created and session can no longer be configured.");
NSAssert1(sharedPINRemoteImageManager == nil, @"An instance of %@ has been set. Either configuration or preconfigured image manager can be set at a time and only once.", [[sharedPINRemoteImageManager class] description]);
wiseoldduck marked this conversation as resolved.
Show resolved Hide resolved
__unused PINRemoteImageManager *sharedManager = [self sharedPINRemoteImageManagerWithConfiguration:nil preconfiguredPINRemoteImageManager:preconfiguredPINRemoteImageManager];

dispatch_once(&shared_init_predicate, ^{
sharedPINRemoteImageManager = preconfiguredPINRemoteImageManager;
});
}

+ (PINRemoteImageManager *)sharedPINRemoteImageManagerWithConfiguration:(NSURLSessionConfiguration *)configuration preconfiguredPINRemoteImageManager:(PINRemoteImageManager *)preconfiguredPINRemoteImageManager
+ (PINRemoteImageManager *)PINRemoteImageManagerWithConfiguration:(nullable NSURLSessionConfiguration *)configuration imageCache:(nullable id<PINRemoteImageCaching>)imageCache
{
NSAssert(!(configuration != nil && preconfiguredPINRemoteImageManager != nil), @"Either configuration or preconfigured image manager can be set at a time.");
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{

if (preconfiguredPINRemoteImageManager) {
sharedPINRemoteImageManager = preconfiguredPINRemoteImageManager;
} else {
PINRemoteImageManager *manager = nil;
// Check that Carthage users have linked both PINRemoteImage & PINCache by testing for one file each
if (!(NSClassFromString(@"PINRemoteImageManager"))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should put that behind a debug flag.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to put these checks behind the PIN_ANIMATED_AVAILABLE flag, just like the previous implementation.

Copy link
Contributor

@maicki maicki Nov 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered as I looked over it the first time why this was the case? cc @garrettmoon

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I hit the error condition once, and didn't get the exception, and saw that, and thought it would be helpful, and it didn't have anything really to do with PIN_ANIMATED_AVAILABLE specifically, so I moved it out. takes a breath

I can see putting it behind #if DEBUG, although it's just going to crash either way and for a check that is guaranteed to only ever run once it doesn't seem like two NSClassFromStrings is that expensive. But it's of limited use without a debugger attached (you would get a friendlier crash report from Apple if your released app hit here, but then presumably your app is crashing every time so ...... you hopefully have it figured out)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course now that I've done it, it seems like it might as well be an assertion instead if it's only on DEBUG.

I agree that I'm interested in Garret's take here as well.

NSException *e = [NSException
exceptionWithName:@"FrameworkSetupException"
reason:@"Missing the path to the PINRemoteImage framework."
userInfo:nil];
@throw e;
}
if (!(NSClassFromString(@"PINCache"))) {
NSException *e = [NSException
exceptionWithName:@"FrameworkSetupException"
reason:@"Missing the path to the PINCache framework."
userInfo:nil];
@throw e;
}
#if PIN_ANIMATED_AVAILABLE
// Check that Carthage users have linked both PINRemoteImage & PINCache by testing for one file each
if (!(NSClassFromString(@"PINRemoteImageManager"))) {
NSException *e = [NSException
exceptionWithName:@"FrameworkSetupException"
reason:@"Missing the path to the PINRemoteImage framework."
userInfo:nil];
@throw e;
}
if (!(NSClassFromString(@"PINCache"))) {
NSException *e = [NSException
exceptionWithName:@"FrameworkSetupException"
reason:@"Missing the path to the PINCache framework."
userInfo:nil];
@throw e;
}
sharedPINRemoteImageManager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration
alternativeRepresentationProvider:[self sharedDownloader]];
sharedPINRemoteImageManager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration
wiseoldduck marked this conversation as resolved.
Show resolved Hide resolved
alternativeRepresentationProvider:[self sharedDownloader]
imageCache:imageCache];
#else
sharedPINRemoteImageManager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration];
manager = [[ASPINRemoteImageManager alloc] initWithSessionConfiguration:configuration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change to manager instead of sharedPINRemoteImageManager?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it's not shared - I funneled all the set-shared logic into as few places (two, unfortunately couldn't get it to one without changing the API of the getter) as possible to reduce complexity. This method just configures a manager and returns it to you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change to manager instead of sharedPINRemoteImageManager?

This method is no longer a setter but a builder.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool than we should change the other sharedPINRemoteImageManager to the manager variable too :)

alternativeRepresentationProvider:nil
imageCache:imageCache];
#endif
}
});
return sharedPINRemoteImageManager;
return manager;
}

- (PINRemoteImageManager *)sharedPINRemoteImageManager
{
return [ASPINRemoteImageDownloader sharedPINRemoteImageManagerWithConfiguration:nil preconfiguredPINRemoteImageManager:nil];
if (!sharedPINRemoteImageManager) {
Copy link
Contributor

@maicki maicki Nov 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we have to have this check here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give me a minute to try to remember lol!

If I can't, I will write it off as a brain fart...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I took nine, and I got nothing! I am pretty sure I had worked myself into some overcomplicated concurrency scenario that cannot actually exist and wouldn't have been completely helped anyway

dispatch_once(&shared_init_predicate, ^{
sharedPINRemoteImageManager = [ASPINRemoteImageDownloader PINRemoteImageManagerWithConfiguration:nil imageCache:nil];
wiseoldduck marked this conversation as resolved.
Show resolved Hide resolved
});
}
return sharedPINRemoteImageManager;
}

- (BOOL)sharedImageManagerSupportsMemoryRemoval
Expand Down