CATiledLayer shows previous tiles

Originator:tom
Number:rdar://28648050 Date Originated:2016-10-06
Status:Open Resolved:
Product:iOS SDK Product Version:iOS 9, iOS 10
Classification:Serious Reproducible:Always
 
Summary:
When invalidating a view backed by a CATiledLayer, a previous tile remains "stuck" and isn't correctly invalidated.

This seems to happen when the view is invalidated (on the main thread), while at the same time, the tile render threads are still working on a previous version of the tile. Instead of caching the new version of the tile, the previous version is cached.

The view backed by CATiledLayer is a subview of a UIScrollView and is zoomable. The rendering of a tile can be expensive and can use the render thread for 10ms.

Steps to Reproduce:
The attached example app demonstrates this problem.

1. In a CATiledLayer, start rendering all red tiles (this would take about 3 seconds to complete)
2. Each render step takes about 10ms
3. During rendering (after 800ms), invalidate the complete view (setNeedsDisplay)
4. Start rendering all gray tiles (this again takes about 3 seconds)

Expected Results:
All tiles should become gray

Actual Results:
Two tiles (randomly?) remain red

Version:
iOS 9, iOS 10

Notes:
Code is also available here: https://github.com/Q42/CATiledLayerBug

Configuration:
iPhone 6, iPhone 7 Plus, iPad Pro 12"

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!