ios10: viewDidLoad frame width/height not initialized correctly

拈花ヽ惹草 提交于 2019-11-28 04:06:48

The most common issues you describe are appearing in iOS 10 only and can be solved by adding this line (if necessary):

self.view.layoutIfNeeded()

just above the code, that is responsible for changing constraint, layer.cornerRadius etc.

OR

place your code related to frames / layers into viewDidLayoutSubviews() method:

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    view.layer.cornerRadius = self.myView.frame.size.width/2
    view.clipsToBounds = true

    ... etc
}

We created a radar (28342777 (marked as duplicate for 28221021 but Open)) for the similar problem and the reply that we got was as below:

"Thank you for reporting the issue. Could we get more information about the profile image view? In Xcode 8, a fully constraint, non-misplaced view no longer saves out a frame to minimize diffs and support automatically update frames in IB. At runtime, these views get decoded with a placeholder size of 1000x1000, but are resolved after first layout. Could the image be assigned before initial layout, and would assigning the image to the image view after first layout address this case? Please send a sample to help us further analyze. thanks!"

At present we have provided them the sample project. My observations:

  • The problem that we had used to happen for XIBs that are converted from Xcode 7.x to Xcode 8.x
  • If we intentionally break the constraint in XIB then viewDidLoad will get expected height and width and not 1000x1000.
  • For us it was a UIImageView on which we were apply some layering for making it circular and using masksToBounds. If we set masksToBounds = NO then we everything was working fine.

Though Apple claims that it is going to be a standard from Xcode 8 that views will be set to 1000x1000, the behavior doesn't seem to be consistent.

Hope this helps.

I encountered the same issue and try to solve it without luck by referring above suggestions.

Seems it should be a bug for Apple to solve. I finally find a solution by changing to save my XIB document back to Xcode 7.x format and my UI back to normal.

Until Apple releasing a fix, I don't want to spend my time on hacking it.

What about doing this:

- (NSLayoutConstraint*)widthConstraint{
    return [self constraintForAttribute:NSLayoutAttributeWidth];
}

- (NSLayoutConstraint*)heightConstraint {
    return [self constraintForAttribute:NSLayoutAttributeHeight];
}

- (NSLayoutConstraint*)constraintForAttribute:(NSLayoutAttribute)attribute {
    NSLayoutConstraint *targetConstraint = nil;
    for (NSLayoutConstraint *constraint in self.constraints) {
        //NSLog(@"constraint: %@", constraint);
        if (![constraint isKindOfClass:NSClassFromString(@"NSContentSizeLayoutConstraint")]) {
            if (constraint.firstAttribute == attribute) {
                targetConstraint = constraint;
                break;
            }
        }
    }
    return targetConstraint;
}

You should never rely on the timing of when a view is layed out. If that worked for you before, then out of pure luck. There are very little guarantees about this in UIKit. If you rely on something adopting to the size of your view, the right thing to do is override layoutSubviews in that view and adjust your stuff there.

Even after your view is fully rendered on screen, there are still so many conditions that could cause the size of the view to change. For example: Double height status bar, multitasking on iPad, device rotation, just to name a few. So it never is a good idea to do frame related layout changes at a particular point in time.

I was having the exact same problem. I had custom UITableViewCell subclasses and was using clipsToBounds = YES and self.iconView.layer.cornerRadius = self.iconView.frame.size.width/2 to give myself a circular image. Tried calling my cell configuration method from cellForRowAtIndexPath and willDisplayCell and neither worked.

Here is what works:
Move your layering code into the cell's -layoutSubviews method like this:

-(void)layoutSubviews {
    [super layoutSubviews];
    self.iconView.clipsToBounds = YES;
    self.iconView.layer.cornerRadius = self.iconView.frame.size.width/2;
} 

After this the images should load properly and your layering code should also work.

Only Update frame in your autolayout box .

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!