In order to avoid blocking on the main thread, PINRemoteImage creates
a UUID but does not immediately start a task instead putting it on an
operation queue. This means that a client can request cancelation for
a UUID before its task is created.
Previously, we attempted to handle this by maintaining a set of canceled
UUIDs. This was being done incorrectly however. The logic was to check if,
before creating a task, a UUID was in canceledTasks. If it was, don't
create the task. If it wasn't clear out the canceledTasks list. This
example illustrates why that was erroneous:
1. Request starting a task with UUID #1
2. Request starting a task with UUID #2
3. Request canceling UUID #2
4. Task creation starts for UUID #1
5. UUID one is not in canceledTasks so it is cleared
6. Task creation starts for UUID #2, it is not in canceledTasks
so the task is created and is not canceled.
This patch changes canceledTasks to a weak hash table and removes
the line which cleared out canceledTasks. As long as there are blocks
(for task creation) referencing the UUID, they will not be removed
from canceledTasks. When no one is referencing the UUIDs any longer,
they will be cleared out.
* Have PINProgressiveImage pass back the quality of the current progressive image
* fix
* Check for nil for imageProgress pointer
* Rename some variables
* Rename a bunch of things
* Update comment
* Modify estimatedRemainingTimeThreshhold behavior to match documentation
* Update documentation on maxProgressiveRenderSize property
* Update the behavior, not the docs
While all methods on tasks are called within the manager's lock,
dispatching to another queue obviously means the manager may not
be locked anymore.
I also moved calling progress download callbacks to the download
task so it's similar to progress image.
Hopefully these issues have been fixed, but it leads me to believe
a better architecture would be to make the tasks immutable by the
manager and have the tasks manage a lock on themselves. I'll need
to think about that more.
Mapping generic classes like PINImage, PINImageView and PINButton to the equivalent UIKit or AppKit classes. Throughout the framework use these mappings instead of the concrete UIKit / AppKit names. Furthermore we provide a category on NSImage that is adding methods that are not available on NSImage but on UIImage.