Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Conversation

@maicki
Copy link
Contributor

@maicki maicki commented Dec 4, 2016

We had some confusion in our Slack channel as well as a P1 bug in Pinterest due to setting an image directly to the image property of an ASNetworkImageNode that get's blown away if the node get's into the didExitPreloadState. This PR addresses this issue for ASNetworkImageNode in there we make the following behavior changes:

  • Setting an image directly will set a flag: _imageWasSetExternally and the node will act like a plain ASImageNode
  • In didExitPreloadState we check if the _imageWasSetExternally == true and just return and don't blow away the image anymore. Same as the ASImageNode
  • Setting an URL aftewards will transform the node to be an image node that manages the image property internally based on the defaultImage and the image that was fetched based on the URL property.

I tried to reduce the changes within the core classes as much as possible ... but unfortunately we still have to add some clutter ...

Resolves: #2699

{
[self __setImage:image];
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a comment: "This is exposed to library subclasses, i.e. ASNetworkImageNode, ASMultiplexImageNode and ASVideoNode"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added comment


- (void)setImage:(UIImage *)image
{
ASDisplayNodeAssert(NO, @"Setting the image directly to an ASMultiplexImageNode is not allowed.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the assert explain why?

"Setting the image directly on an ASMultiplexImageNode is unsafe. It will be cleared in didExitPreloadRange and will have no way to restore in didEnterPreloadRange"

@Adlai-Holler
Copy link
Contributor

As we discussed, let's remove the assert and do one of the following:

  • Implement setImage: by calling setDefaultImage: and implement -image by returning super.image ?: self.defaultImage. Possibly deprecate .defaultImage externally.
  • Add a flag like imageWasSetExternally and check that flag before clearing the image when exiting the preload range.

I advocate for the first one, but I don't feel strongly about it. I think it's reasonable to say that if a URL and an image are set, the node should prefer the remote image.

@Adlai-Holler
Copy link
Contributor

Actually on second thought, I advocate for the second option. If someone sets an image on the node externally, we should prefer that and perhaps not even both loading the image from URL.

This way the developer has finer control over how the node appears. If I set an image on it, that image will get shown full stop.

@maicki
Copy link
Contributor Author

maicki commented Dec 5, 2016

Ok let's roll with option two for now.


- (void)setURL:(NSURL *)URL
{
[self setURL:URL resetToDefault:YES];
Copy link
Contributor

Choose a reason for hiding this comment

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

Should setURL clear out _imageWasSetExternally?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will clear it out now yes

@maicki maicki changed the title [ASImageNode] Add assertion against externally setting .image in specific ASImageNode subclasses [ASImageNode] Add handling of setting .image in specific ASImageNode subclasses Dec 6, 2016
Copy link
Contributor

@garrettmoon garrettmoon left a comment

Choose a reason for hiding this comment

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

What are the video node changes hoping to achieve overall?

* ASNetworkImageNode to set the image.
*
* This is exposed to library subclasses, i.e. ASNetworkImageNode, ASMultiplexImageNode and ASVideoNode for setting
* the image directly without going throug the setter of the superclass
Copy link
Contributor

Choose a reason for hiding this comment

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

total nit: through


{
ASDN::MutexLocker l(__instanceLock__);
_asset = asset;
Copy link
Contributor

Choose a reason for hiding this comment

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

Ha, nice, fix some threading issues while you're here :)

@maicki
Copy link
Contributor Author

maicki commented Dec 6, 2016

@garrettmoon @appleguy Ready for another round. As already mentioned not really beautiful and unfortunately adds some clutter to the core classes :(


#ifdef DEBUG
if (_URL != nil) {
NSLog(@"Setting the image directly on an %@ and setting and setting an URL is not supported. If you want to use a placeholder image please use defaultImage .", NSStringFromClass([self class]));
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this necessary? If not, I think we should support this condition. Think for example of using a network image node in a transition, and so you might want to override its image with some other one temporarily, to achieve a visual effect.

}
__instanceLock__.unlock();

[self _setImage:image];
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we may need to hold this lock while calling _setImage:, because we need to be sure that _imageWasSetExternally lines up with super.image.

Think if thread A calls this (image != nil), then B calls it just after (image == nil). A finishes the critical section having set _imageWasSetExternally = YES. Then A goes to sleep. Then B finishes the critical sections having set _imageWasSetExternally = NO, then B calls _setImage:nil, then A wakes up and calls _setImage:(nonnil). Now our flag doesn't match our image.

@maicki
Copy link
Contributor Author

maicki commented Dec 6, 2016

@garrettmoon @Adlai-Holler @appleguy Ready for review.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants