Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Masonry is malfunctioning in iOS 10 while compiling with XCode 8. #382

Closed
aquaibm opened this issue Sep 14, 2016 · 31 comments
Closed

Masonry is malfunctioning in iOS 10 while compiling with XCode 8. #382

aquaibm opened this issue Sep 14, 2016 · 31 comments

Comments

@aquaibm
Copy link

aquaibm commented Sep 14, 2016

It worked well before I updated to iOS 10 and Xcode 8.
For example,in a UITableViewCell subclass:

        UIImageView *imageView = [UIImageView new];
        imageView.contentMode = UIViewContentModeScaleAspectFill;
        [self.contentView addSubview: imageView];
        self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
        [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(0);
            make.right.mas_equalTo(0);
            make.top.mas_equalTo(15);
            make.height.mas_equalTo(imageView.mas_width).with.multipliedBy(9/16.0);
        }];
        self.pImageView = imageView;

        [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(0);
            make.right.mas_equalTo(0);
            make.top.mas_equalTo(0);
            make.bottom.mas_equalTo(imageView.mas_bottom).with.offset(15);
        }];

This used to work like a charm in iOS 9 while compiling with XCode 7.x, but now it is not.
Console shows this:

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<MASLayoutConstraint:0x1740b1dc0 UITableViewCellContentView:0x100546830.bottom == UIImageView:0x1005203b0.bottom + 15>",
    "<MASLayoutConstraint:0x1740b2120 UIImageView:0x1005203b0.left == UITableViewCellContentView:0x100546830.left>",
    "<MASLayoutConstraint:0x1740b2180 UIImageView:0x1005203b0.right == UITableViewCellContentView:0x100546830.right>",
    "<MASLayoutConstraint:0x1740b2240 UIImageView:0x1005203b0.top == UITableViewCellContentView:0x100546830.top + 15>",
    "<MASLayoutConstraint:0x1740b2300 UIImageView:0x1005203b0.height == UIImageView:0x1005203b0.width * 0.5625>",
    "<NSLayoutConstraint:0x174099eb0 UITableViewCellContentView:0x100546830.height == 0>",
    "<NSLayoutConstraint:0x174099e60 UITableViewCellContentView:0x100546830.width == 375>"
)

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x1740b2300 UIImageView:0x1005203b0.height == UIImageView:0x1005203b0.width * 0.5625>

How can I fix this? Thanks a lot.

@robertjpayne
Copy link
Member

@aquaibm are you using interface builder at all?

Looks like iOS 10 has two additional constraints there for width/height unsure why but that's whats causing the error.

@aquaibm
Copy link
Author

aquaibm commented Sep 14, 2016

No, I am not using interface builder, purely code layout,NO xib file for this class.

@robertjpayne
Copy link
Member

@aquaibm what if you do self.translatesAutoresizingMaskIntoConstraints = NO as well? And are you using iOS's prefetching or auto cell sizing?

@robertjpayne
Copy link
Member

@aquaibm basically something in iOS 10 runtime is adding:

"<NSLayoutConstraint:0x174099eb0 UITableViewCellContentView:0x100546830.height == 0>",
"<NSLayoutConstraint:0x174099e60 UITableViewCellContentView:0x100546830.width == 375>"

Masonry was not in the past nor will ever modify non Masonry constraints so somehow you have to track down what new API(s) are necessary to stop those two constraints from being created/added.

@aquaibm
Copy link
Author

aquaibm commented Sep 14, 2016

@robertjpayne self.translatesAutoresizingMaskIntoConstraints = NO I have tried this ,not working, still the same alert.

"<NSLayoutConstraint:0x174099e60 UITableViewCellContentView:0x100546830.width == 375>"
This constraint is expected , right ? My device is iPhone 6s,so it's width should be 375, as specified by this:

        [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(0);
            make.right.mas_equalTo(0);
}];

@aquaibm
Copy link
Author

aquaibm commented Sep 14, 2016

Basically the code I've posted is to make sure the cell's contentView grows as the imageView size changes later, yes ,I am using UITableView dynamic height trick, it works well before iOS 10.

@robertjpayne
Copy link
Member

@aquaibm right so this isn't an issue with Masonry it's something to do with iOS 10, unfortunately I'm not sure what exactly is causing those two extra constraints but I would poke around with some of the API's related to auto sizing and see if that is the cause.

@anthonygeranio
Copy link

Did you figure out what the issue was @aquaibm I seem to be discovering the same thing.

For context, @robertjpayne.. it seems that we now have to set a "placeholder" height with UITableViewCell's that require some sort of dynamic layout based off content. UITableViewAutomaticCellDimension doesn't seem to work properly.

Happy to sync and set up an example project if this helps you debug, @robertjpayne?

@aquaibm
Copy link
Author

aquaibm commented Sep 16, 2016

@anthonygeranio nope.

@kevinh
Copy link

kevinh commented Sep 18, 2016

I have the same problem “It worked well before I updated to iOS 10 and Xcode 8.”


- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.translatesAutoresizingMaskIntoConstraints = NO; // update xcode8 new add
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        [self initSubview];
    }
    return self;
}


- (void)initSubview{
    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.numberOfLines = 0;
    [self.contentView addSubview:self.titleLabel];
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.contentView).offset(25);
        make.left.equalTo(self.contentView).offset(10);
        make.right.equalTo(self.contentView).offset(-10);
    }];

    [self.contentView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.top.left.equalTo(self);
        make.bottom.equalTo(self.titleLabel).offset(25);
        make.width.equalTo(@(SCREEN_WIDTH));
    }];
}

- (void)setTitle:(NSString *)title{
    _title = title;
    self.titleLabel.text = title;
}

tableview layout before is OK but update xcode8 layout will be chaotic, (all data show in first cell, See only a part of the data)

all cell show in first cell

rows height is right,but all cell overlap in first cell. why?

Can anyone help me? thanks



@kevinh
Copy link

kevinh commented Sep 18, 2016

@aquaibm @robertjpayne @anthonygeranio Do you have any Suggestions?

@Panajev
Copy link

Panajev commented Sep 18, 2016

iOS 10 is not setting the initial view constraints so if you are not super thorough, not saying you have not been :), you could easily miss some.

Sent from my iPhone

On 18 Sep 2016, at 17:50, aquaibm notifications@github.com wrote:

iOS 10's autolayout engine must have been modified, it has broken Masonry.
For example, check out the code below:
` NSLog(@"0 %@",self.contentView.constraints);

UIImageView *imageView = [UIImageView new];
imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.contentView addSubview: imageView];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(0);
    make.right.mas_equalTo(0);
    make.top.mas_equalTo(15);
    make.height.mas_equalTo(imageView.mas_width).with.multipliedBy(9/16.0);
}];
self.pImageView = imageView;

NSLog(@"1 %@",self.contentView.constraints);`

And then got this in console:

0 (
)
1 (
"<MASLayoutConstraint:0x1702a6660 UIImageView:0x100500780.left == UITableViewCellContentView:0x100550760.left>",
"<MASLayoutConstraint:0x1702a6720 UIImageView:0x100500780.right == UITableViewCellContentView:0x100550760.right>",
"<MASLayoutConstraint:0x1702a6840 UIImageView:0x100500780.top == UITableViewCellContentView:0x100550760.top + 15>"
)

The height constraint is missing!


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@robertjpayne
Copy link
Member

robertjpayne commented Sep 18, 2016

@aquaibm width/height constraints are installed on the view itself if it is constrained to itself or a constant. So make sure you check imageView for that missing constraint. It will be there.

@aquaibm
Copy link
Author

aquaibm commented Sep 19, 2016

@Panajev @robertjpayne Oh,seems like I've made a mistake,thanks.

@kevinh
Copy link

kevinh commented Sep 20, 2016

I have already solved!
replace
self.translatesAutoresizingMaskIntoConstraints = NO;
to
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self); }];

I also don't know why? do you think this is helpful to you? @aquaibm

@aquaibm
Copy link
Author

aquaibm commented Sep 20, 2016

@kevinh Nope, your solution is not suitable for my case, which needs dynamic cell heights. Besides, are you sure there were no alerts showing in your xcode console when runing the project on your devices after replacement?

@kevinh
Copy link

kevinh commented Sep 20, 2016

@aquaibm yes is dynamic cell heights

old code is

- (CGFloat)cacheTableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath indexKey:indexKey{
    CGFloat height;
    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    [cell setNeedsLayout];
    [cell layoutIfNeeded];
    cell.bounds = CGRectMake(0,0,self.tableView.bounds.size.width, cell.bounds.size.height);
    height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    height +=1.0f;

    [self.heightCacheDic setValue:[NSNumber numberWithFloat:height] forKey:indexKey];
    return height;
}

updated xcode8 alert

(
    "<MASLayoutConstraint:0x175ebfc80 UITableViewCellContentView:0x10c251f60.width == 414>",
    "<NSLayoutConstraint:0x171885550 UITableViewCellContentView:0x10c251f60.width <= 320>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x171885550 UITableViewCellContentView:0x10c251f60.width <= 320>

but layout is ok

after I remove

[cell layoutIfNeeded];

the warning disappear

@cclion
Copy link

cclion commented Sep 21, 2016

The solution:

UIImageView *imageView = [UIImageView new];
imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.contentView addSubview: imageView];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.right.mas_equalTo(0);
make.top.mas_equalTo(15);
make.height.mas_equalTo(imageView.mas_width).with.multipliedBy(9/16.0);
make.bottom.equalTo(self.contentView);
}];
self.pImageView = imageView;

@anthonygeranio
Copy link

Found a solution to this. Thinking about writing a blog post about it. Any interest?

@beloso
Copy link

beloso commented Sep 22, 2016

@anthonygeranio I would be interested in reading it.

@anthonygeranio
Copy link

Sweet gonna put something together tomorrow @beloso

@Panajev
Copy link

Panajev commented Sep 22, 2016

Thanks for this :)!

Sent from my iPhone

On 22 Sep 2016, at 20:43, Anthony Geranio notifications@github.com wrote:

Sweet gonna put something together tomorrow @beloso


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@beloso
Copy link

beloso commented Sep 22, 2016

@anthonygeranio I will be updating an app to iOS 10. I am using masonry and it would be good to know the problems and how to solve them before hand :)

will we need a pull request to "fix" masonry?

@aquaibm
Copy link
Author

aquaibm commented Sep 23, 2016

@anthonygeranio Looking forward for your solution. 💃

@cclion I will try it later, thanks.

@virtualrapha
Copy link

I've had a cell with fixed height and still experienced this problem. The solution that worked for my case was to override intrinsicContentSize in the cell subclass and return the size you want like so:

- (CGSize)intrinsicContentSize {
    CGFloat someFixedHeight = 250.0f;
    return CGSizeMake(CGRectGetWidth(self.bounds), someFixedHeight);
}

@xiao-xi
Copy link

xiao-xi commented Sep 28, 2016

it is good@kevinh

@seventhfish
Copy link

@anthonygeranio Please help, how to fix this issue

@wells1013
Copy link

+1, how to fix it

@zb737472783
Copy link

+1

@jeffleeismyhero
Copy link

I ran across this same issue. It seems that:

make.center.equalTo(myLabel.mas_centerX);

would work prior to iOS 10. After iOS 10, that does not work and I needed:

make.centerX.equalTo(myLabel.mas_centerX);

@aquaibm
Copy link
Author

aquaibm commented Oct 24, 2016

Finally found out the solution for my case, seems like it's not Masonry's fault to blame for this problem.

My solution is: Just don't do this

        [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(0);
            make.right.mas_equalTo(0);
            make.top.mas_equalTo(0);
            make.bottom.mas_equalTo(imageView.mas_bottom).with.offset(15);
        }];

Do NOT call mas_makeConstraints on tableViewCell's contentView, instead be sure that there is a constraint attached to all four sides of the contentView. Like this:

[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(self.contentView.mas_left);
            make.right.mas_equalTo(self.contentView.mas_right);
            make.top.mas_equalTo(self.contentView.mas_top);
            make.height.mas_equalTo(imageView.mas_width).with.multipliedBy(9/16.0);
            make.bottom.mas_equalTo(self.contentView.mas_bottom);
        }];

Hope this will help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests