UITintColorVisitor causes exponentially worsening performance when adding subviews

Originator:xenadu
Number:rdar://25934331 Date Originated:26-Apr-2016 10:37 AM
Status:Open Resolved:
Product:iOS SDK Product Version:9.0
Classification: Reproducible:Yes
 
Summary:
When adding subviews to a view that obtains its tint color from the window or a parent view performance gets exponentially worse the more subviews you add. When adding 6000 subviews execution takes over 10 minutes in the following method chain:

In _postMovedFromSuperview, _UIViewVisitorRecursivelyEntertainDescendingVisitors, _UITintColorVisitor.visitView, checking NSArray.containsObject.

It appears UIKit is visiting all sibling views to set their tintColor when only a single sibling is added.

Here is a really simple sample project demonstrating the problem. If you tap the Custom Tint Color button it will take several minutes to run. If you tap the No Tint Color button the subviews are added so quickly you might miss it. The identical code is running in both cases, the only difference is whether the application UIWindow has a tintColor set.

Steps to Reproduce:
Set window tintColor to a non-default color
Create a subview class
Add 6000 subviews to the parent view
Observe exponentially decreasing performance as UITintColorVisitor continuously re-scans the growing array.

Expected Results:
Performance should not get exponentially worse with more subviews

Actual Results:
Performance gets exponentially worse

Version:
iOS 9.3, Xcode 7.3

Notes:
A temporary workaround is to explicitly set the tintColor on all subviews but that defeats the purpose of tintColor's inheritance system.

Comments

The performance is improved on iOS 10.

It takes about 5-6 seconds to add 6000 subviews with a custom tint color set compared to less than 1 second with no custom tint color.

I would still consider this an undesirable behavior on the part of UIKit especially for a bunch of views that don't have children and don't care about the tint color. I would expect the tint color to be lazily resolved when needed, not pushed every time subviews are added.

For that reason I still consider this an open bug.


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!