Xcode 7.1 Interface Builder generates bogus constraints for designable views at build time

Originator:argentumko
Number:rdar://23234553 Date Originated:24-Oct-2015
Status:Open (Resolved) Resolved:Yes
Product:Developer Tools Product Version:Xcode 7.1 (7B91b), OS X 10.11.1 (15B42)
Classification:Other Bug Reproducible:Always
 
Summary:
Using a custom designable view (UIView subclass with IB_DESIGNABLE/@IBDesignable attribute) with overridden intrinsicContentSize method in Interface Builder of Xcode 7.1 results in extra unnecessary constraints created for this view at build time by Interface Builder, even though layout of that view is fully defined by constraints in canvas and customized intrinsic content size. At design time, Interface Builder does not show any layout warnings and lays out the view correctly in canvas without any ambiguities. At runtime, that view's superview contains extra constraints with identifiers of "IB auto generated at build time for view with ambiguity". This issue goes away if deployment target is set to iOS 9.1.

Steps to Reproduce:
1. Create a new iOS project in Xcode 7.1, regardless of language. Set its deployment target to anything below iOS 9.1, e.g.: iOS 8.0.
2. Create a subclass of UIView, let's call it CustomView. Mark it as IB_DESIGNABLE/@IBDesignable. Implement intrinsicContentSize method in it. E.g.:
- (CGSize)intrinsicContentSize
{
    return CGSizeMake(50.0f, 50.0f);
}
3. Open the project's storyboard, add a view in the scene and set its class to CustomView.
4. Constrain this view to its superview's top margin and center it horizontally in superview.
5. Make sure Interface Builder has refreshed designable views (click Editor → Refresh All Views if necessary).
6. The view should have a size of 50, 50 as per its intrinsic content size.
7. Build and run the app.
8. The view should be laid correctly. Now inspect the constraints connected to that view (in debugger, View Debugger or, for example, Reveal).

Expected Results:
The view should be connected to its superview by two constraints and should contain two NSContentSizeLayoutConstraint constraints.

Actual Results:
Besides the expected constraints, the view is also connected to 4 extra constraints of class NSIBPrototypingLayoutConstraint and identifier "IB auto generated at build time for view with ambiguity", even though they are extraneous in that configuration.

Version:
Xcode 7.1 (7B91b), OS X 10.11.1 (15B42)

Notes:
It seems like at build time Interface Builder compiler doesn't take into account the defined intrinsic content size method of the designable view, while Interface Builder agent at design time does.
The current workaround is either to define placeholder intrinsic content size for the custom view, or compile in Xcode 7.0.
Since this issue results in extra constraints required to resolve in runtime, it affects performance and may also potentially affect layout correctness.
Attachment contains a sample project with a custom view inside a storyboard, with deployment target set to iOS 9.0, and it can be used to demonstrate the issue and confirm that it doesn't occur in Xcode 7.0.

Configuration:
This issue occurs:
* Only in Xcode 7.1 (doesn't occur in Xcode 7.0, occurred in later betas of Xcode 7.1 as well).
* Only if deployment target is set to *lower* than iOS 9.1.
* Regardless of Objective C/Swift.
* Regardless of custom view class location (main app target or library).
* Only if the custom view is @IBDesignable / IB_DESIGNABLE.
* Only if it defines intrinsic content size.
* Regardless of whether it's used in a XIB file or a Storyboard.
* Only if placeholder intrinsic size is ​*not* set on the view.

Attachments:
'InterfaceBuilderTest.zip' was successfully uploaded.

Comments

Vlas Voloshin

As of Xcode 8.0 beta 1 (8S128d), this issue is now fixed. Thank you! This issue has been verified as resolved and can be closed.

By argentumko at June 20, 2016, 6:14 a.m. (reply...)

Apple Developer Relations

Engineering has provided the following feedback regarding this issue:

Interface Builder is currently not detecting the intrinsic content size override in the custom view. For now, there is a workaround: Select the custom view in the canvas, go to the size inspector, and switch the Intrinsic Size to “Placeholder”. This setting will tell Interface Builder to treat the custom view with an intrinsic content size based on the width and height in the inspector for canvas and compilation.

We are continuing to work on this issue, and will follow up with you again.

By argentumko at Oct. 31, 2015, 2:27 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!