Creating view rects in loop
We should be using auto-layout.  Not being as comfortable with auto-layout is not an excuse to not use it.  Manually setting rects is not very good at all.  Manually set rects don't play well with rotation.  Manually set rects mean we probably need a special set of code for iPad versus iPhone.  Manually set rects mean we probably need a special set of code for iPhone 4 vs iPhone 5 vs iPhone 6 vs iPhone 6+.

I'm not really going to touch the createSubviews method, which has some issues that should be address, but I do want to point out the problems with createViewRects: and how we can more easily write this code with auto-layout and using the Visual Format Language quite simply.

The method sets up the position for four views.  The spacing follows two rules:


Each view has an X of 16 pixels from the left edge.
Each view has a Y that leaves a gap of 8 pixels between the other views (plus 8 pixels between the top of the super view and the top of the top view and 8 pixels between the bottom of the super view and the bottom of the bottom view).


For this, I'm going to assume that bgView is a scroll view.  Scroll view's content doesn't really work particularly well with multiple top-level subviews.  Instead, we give the bgView a single subview and add all of the subviews to that subview.  This will allow auto-layout to work well.

Let's define a couple dictionaries to use with VFL.

For starters, so we can put them in a dictionary, let's use NSNumber objects rather than CGFloat for our metrics:

NSNumber *padding = @16.0;
NSNumber *rowPadding = @8.0;


We don't need a total height.  Auto-layout will resolve this for us.  Anyway, creating a dictionary is as simple as this:

NSDictionary *metrics = NSDictionaryOfVariableBindings(padding, rowPadding);


Now, using a mutable string, a mutable dictionary, let's set up these constraints:

int viewIndex = 0;
NSMutableString *vertConstraintsStr = [@"V:|-[rowPadding]-" mutableCopy];
NSMutableDictionary *views = [NSMutableDictionary dictionary];

UIView *backgroundView = [[UIView alloc] init];

for (UIView *view in views) {
    NSString *viewKey = [NSString stringWithFormat:@"view%i", viewIndex];
    ++viewIndex;

    [backgroundView addSubview:view];

    views[viewKey] = view;

    view.translatesAutoresizingMaskIntoConstraints = NO;

    [vertConstraintsStr addFormat:@"[%@]-[rowPadding]-", viewKey];

    NSString *horizConstraintStr = 
        [NSString stringWithFormat:@"H:|-[padding]-[%@]", viewKey];

    NSArray *horizontalConstraints = 
        [NSLayoutConstraint constraintsWithVisualFormat:horizConstraintStr
                                                options:0
                                                metrics:metrics
                                                  views:views];

    [backgroundView addConstraints:horizontalConstraints];
}

[vertConstraintsStr addString:@"[rowPadding]-|"];

NSArray *verticalConstraints = 
    [NSLayoutConstraint constraintsWithVisualFormat:vertConstraintStr
                                            options:0
                                            metrics:metrics
                                              views:views];

[backgroundView addConstraints:verticalConstraints];

[self.bgView addSubview:backgroundView];


Ultimately, this is more lines of code, but this is much more flexible.

Consider what happens if we were to change the size of one of our subviews.  With your code, we must be sure to call createViewsRect: each time any view changes sizes in order to ensure everything still looks right.  With auto layout, the view will automatically adjust to the new size of one of the subviews.  Plus, now you've got some experience working with auto layout so you'll be less intimidated and more comfortable with it in the future, particularly when you want to start doing more complicated layouts.