UIStackView/AutoLayout performance with many subviews

I'm trying to use a UIStackView to layout lots of subviews (hundreds or even thousands). Unfortunately it seems that AutoLayout cannot handle views with this many subviews.


For comparison, I created a sample app and compared manually computing frames vs. using a UIStackView.


Computing Frames

static const NSInteger numViews = 5000;
static const CGFloat viewHeight = 75.0f;
static const CGFloat viewWidth = 250.0f;
static const CGFloat viewPadding = 8.0f;
static const CGFloat initialViewOffset = 25.0f;

- (void)viewDidLoad {
    [super viewDidLoad];

    CGFloat viewOffset = initialViewOffset;
    for (int i = 0; i < numViews; i++) {
        UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, viewOffset, viewWidth, viewHeight)];
        v.backgroundColor = [UIColor grayColor];
        [self.view addSubview:v];
     
        viewOffset += viewHeight + viewPadding;
    }
}

Memory Usage: 24 MB

Time between viewDidLoad and viewDidLoadSubviews: 0.05s


Alternate Implementation using UIStackView

- (void)viewDidLoad {
    [super viewDidLoad];
   
    self.stackView = [UIStackView new];
    [self.view addSubview:self.stackView];
    self.stackView.translatesAutoresizingMaskIntoConstraints = NO;
    self.stackView.axis = UILayoutConstraintAxisVertical;
    self.stackView.spacing = viewPadding;
    [self.stackView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:initialViewOffset].active = YES;
   
    for (int i = 0; i < numViews; i++) {
        UIView *v = [UIView new];
        [self.stackView addArrangedSubview:v];
        v.translatesAutoresizingMaskIntoConstraints = NO;
        [v.heightAnchor constraintEqualToConstant:viewHeight].active = YES;
        [v.widthAnchor constraintEqualToConstant:viewWidth].active = YES;
        v.backgroundColor = [UIColor grayColor];
    }
}

Memory Usage: 900+ MB

Time between viewDidLoad and viewDidLoadSubviews: 6.34s

Memory usage and time seem to increase in a polynomial fashion with respect to the number of subviews.


In a more complex application but with less subviews (say 500) where the subviews themselves contain subviews laid out using AutoLayout, the peformance is as bad or worse.


I'm surprised by how big of a difference there is between the two methods. Manually computing the view frames is relatively efficient, but AutoLayout is unusable. Is my observation true that AutoLayout can't be used in this way (a view containing thousands of subviews) or could I be using AutoLayout more efficiently?


Thanks

Replies

I think you demonstrated a limitation of using stack views with a large number of subviews.


This kind of issue is why UITableViews and UICollectionViews use a model where only the necessary information is loaded based on the visible content.


Maybe one of those is better suited for this situation.

Autolayout engine has cache, I think it's reason for bad memory usage, but reusable cells in UITableView/UICollectionView allows autolayout engine clear extra cache