0

I have a view controller which I have created using code (no interface builder or storyboard). I am trying to programatically add few views (buttons and image views) and I am using Masonry for AutoLayout.

I have the following code

- (instancetype)init {
    self = [super init];

    if (self) {
        self.view.backgroundColor = UIColor.whiteColor;
        self.progress = 0.f;
        self.shouldRecord = YES;
        [self createMainUI];
        [self addActions];
    }
    return self;
}

- (void)createMainUI {
    self.backButton = [self.view createAndAddSubView:UIButton.class];
    [self.backButton setImage:[TeamieUIGlobals defaultPicForPurpose:@"close" withSize:25.f] forState:UIControlStateNormal];
    [self.backButton addTarget:self action:@selector(dismissViewController) forControlEvents:UIControlEventTouchUpInside];

    self.micNormalImageView = [self.view createAndAddSubView:UIImageView.class];

    self.dynamicProgress = [self.view createAndAddSubView:TMEProgressImageView.class];
    self.dynamicProgress.image = IMAGE_MIC_WAVE;
    self.dynamicProgress.progress = 0;
    self.dynamicProgress.hasGrayscaleBackground = NO;
    self.dynamicProgress.verticalProgress = YES;

    self.recordButton = [self.view createAndAddSubView:UIButton.class];
    self.recordButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.recordButton.backgroundColor = UIColor.redColor;
    self.recordButton.layer.cornerRadius = 50.f;
    self.recordButton.titleLabel.font = [TeamieGlobals appFontFor:@"regularFontWithSize13"];
    [self.recordButton setTitle:@"Record" forState:UIControlStateNormal];
    [self.recordButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];

    [self.backButton mas_makeConstraints:^(MASConstraintMaker *make){
        make.width.height.equalTo(@25);
        make.left.top.equalTo(@10);
    }];
    [self.micNormalImageView mas_makeConstraints:^(MASConstraintMaker *make){
        make.width.equalTo(@204);
        make.height.equalTo(@295);
        make.center.equalTo(self.view);
    }];
    [self.dynamicProgress mas_makeConstraints:^(MASConstraintMaker *make){
        make.width.equalTo(@204);
        make.height.equalTo(@295);
        make.center.equalTo(self.view);
    }];
    [self.recordButton mas_makeConstraints:^(MASConstraintMaker *make){
        make.width.height.equalTo(@100);
        make.centerX.equalTo(self.view);
        make.bottom.equalTo(self.view.mas_bottom).with.offset(15.f);
    }];
}

This is what createAndAddSubView does

- (id)createAndAddSubView:(Class)modelClass {
    id temporaryView = [modelClass new];
    [self insertSubview:(UIView *)temporaryView atIndex:0];
    return temporaryView;
}

The only view which appears on the view in the simulator is the backButton and no other view appears.

Also, the last 2 constraints added to the recordButton crashes the app and the error is "couldn't find a common superview for <UIButton: 0x7ff2eb15f110; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x7ff2eb118c60>> and <UIView: 0x7ff2e8f4bf20; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff2e8fdf220>>" but when I pin the button, there is no error but still it is not visible on the view. Any idea why the views aren't appearing, something wrong with the code?

0

3 Answers 3

1
- (id)createAndAddSubView:(Class)modelClass {
    id temporaryView = [modelClass new];
    [self insertSubview:(UIView *)temporaryView atIndex:self.subviews.count];
    return temporaryView;
}

Problem is with the atIndex:0 it should be self.subviews.count

Sign up to request clarification or add additional context in comments.

1 Comment

Hi Nitish, The issue with UIButton or any UIControl subclass is that it has a class method to initialize itself. [UIButton buttonWithType:] in the case of UIButton. Creating a view using createAndAddSubView will create a UIView whereas creating using [UIButton buttonWithType:] will create a UIControl which is a button. self.recordButton = [self.view createAndAddSubView:UIButton.class]; self.recordButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; These two will create two separate views so the second statement will override the first one
0

I think the problem could be the index at which you are inserting the subviews on parent view. Substitute [[self subviews] count] in place of index '0' as-

- (id)createAndAddSubView:(Class)modelClass {
    id temporaryView = [modelClass new];
    [self insertSubview:(UIView *)temporaryView atIndex:[[self subviews] count]];
    return temporaryView;
}

Comments

0

There are several concerns about the code presented above: 1. Apologise if missed this, however I dont see a code to set the frames of each sub view. 2. This is incorrect.

self.recordButton = [self.view createAndAddSubView:UIButton.class];
self.recordButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];

3. You are adding each sub view on top of previously added subviews.

Please check all these aspects and I think your code should work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.