Notes of learning AutoLayout

11170 ワード

XCode 5では、ButtonまたはLabel、または他の標準Viewを追加してconstraintsを設定しないと、IBは自動的にconstraintsを生成しますが、これらのconstraintsはfixedであり、intrinsic content sizeの変化に応じて変化することはできません.これは私たちが望んでいるものではありません.たとえば、私はViewにlabelを追加します.labelのtitleはLabelです.Buttonを追加します.Buttonをクリックしてlabelのtitleを長い文字に変更し、invalidateInstrinsicContentSizeを呼び出します.実行前後にconstraintsをそれぞれ印刷します.コードは以下の通りです.
    NSLog(@"current constraints %@ ", [[self textLabel] constraintsAffectingLayoutForAxis:UILayoutConstraintAxisHorizontal]);
    NSLog(@"current constraints %@ ", [[self textLabel] constraintsAffectingLayoutForAxis:UILayoutConstraintAxisVertical]);
    
    
    [[self textLabel] setText:@"weuituwjaskdtuqwieotuasdjgakleutaiosgajksdgequwtioasdjgkasjdgkajskgd"];
    [[self textLabel] invalidateIntrinsicContentSize];
    NSLog(@"current constraints %@ ", [[self textLabel] constraintsAffectingLayoutForAxis:UILayoutConstraintAxisHorizontal]);
    NSLog(@"current constraints %@ ", [[self textLabel] constraintsAffectingLayoutForAxis:UILayoutConstraintAxisVertical]);

このとき見える出力は
2014-07-04 17:46:28.580 AutoLayoutExample[1110:70b] current constraints (
    "<NSIBPrototypingLayoutConstraint:0x8b95fb0 'IB auto generated at build time for view with fixed frame' H:|-(179)-[UILabel:0x8b93e80](LTR)   (Names: '|':UIView:0x8b95290 )>",
    "<NSIBPrototypingLayoutConstraint:0x8b960e0 'IB auto generated at build time for view with fixed frame' H:[UILabel:0x8b93e80(42)]>"
) 
2014-07-04 17:46:28.582 AutoLayoutExample[1110:70b] current constraints (
    "<NSIBPrototypingLayoutConstraint:0x8b95d60 'IB auto generated at build time for view with fixed frame' V:|-(147)-[UILabel:0x8b93e80]   (Names: '|':UIView:0x8b95290 )>",
    "<NSIBPrototypingLayoutConstraint:0x8b96110 'IB auto generated at build time for view with fixed frame' V:[UILabel:0x8b93e80(21)]>"
) 

2014-07-04 17:46:28.586 AutoLayoutExample[1110:70b] current constraints ( "<NSIBPrototypingLayoutConstraint:0x8b95fb0 'IB auto generated at build time for view with fixed frame' H:|-(179)-[UILabel:0x8b93e80](LTR) (Names: '|':UIView:0x8b95290 )>", "<NSIBPrototypingLayoutConstraint:0x8b960e0 'IB auto generated at build time for view with fixed frame' H:[UILabel:0x8b93e80(42)]>" ) 2014-07-04 17:46:28.587 AutoLayoutExample[1110:70b] current constraints ( "<NSIBPrototypingLayoutConstraint:0x8b95d60 'IB auto generated at build time for view with fixed frame' V:|-(147)-[UILabel:0x8b93e80] (Names: '|':UIView:0x8b95290 )>", "<NSIBPrototypingLayoutConstraint:0x8b96110 'IB auto generated at build time for view with fixed frame' V:[UILabel:0x8b93e80(21)]>" )

IBはIB auto generated at build time for view with fixed frameを生み出し,intrinsic content sizeがどのように変化しても役に立たないことがわかる.したがって、AutoLayoutを使用する場合は、各要素にsizeと位置を完全に特定できるconstraintsがあり、同じように特定できない場合はIBがErrorまたはWarningを提示し、これらのErrorまたはWarningも解決しなければならないことを覚えておいてください.
2種類のPlaceHolderについて
placeholder constraitsとplaceholder instrinsic content size
placeholder constraitsとは、このconstraintはplaceholderにすぎず、build時に削除され、IBが自動的にconstraintsを生成することを阻止することができるということです.placeholder instrinsic content sizeとは、IBで設計時に使用されるsizeのことであり、runtimeではintrinsicContentSizeメソッドを呼び出して決定する必要がある.
次にintrinsicContentSizeとconstraintの関係を説明します:intrinsicContentSizeとconstraintはAuto Layoutの支柱概念で、一つ欠けてはいけません.また、intrinsicContentSizeは、ある態様においてもconstraintである場合がある、通常、unambiguous layout generally requires setting two attributes in each axis(すなわち、1次元に起点と長さの2つの情報を設定する必要がある)である.When a view has an intrinsic content size, that size accounts for one of the two attributes.(viewにintrinsicContentSizeがある場合、設計者はintrinsicContentSizeがその長さの制限作用を果たすことができると考えている)You can,for example,place a text-based control or an image view in the center of its superview,and its layout will not be ambiguous.The intrinsic content size plus the location combine for a fully specified placement. このようなことができる前提は1である.システムの標準ビューを使用します.IBでIntrinsic sizeを指定する場合は、位置情報のみを指定してsizeを指定しない場合、system default intrinsic sizeを使用する場合など、Default(System defined)を使用する必要があります.
2014-07-04 22:25:40.866 AutoLayoutExample[2237:70b] current constraints (
    "<NSLayoutConstraint:0x8a6bde0 H:|-(179)-[UILabel:0x8a6a010]   (Names: '|':UIView:0x8a6b400 )>",
    "<NSContentSizeLayoutConstraint:0x8b847a0 H:[UILabel:0x8a6a010(42)] Hug:251 CompressionResistance:750>"
) 
2014-07-04 22:25:40.868 AutoLayoutExample[2237:70b] current constraints (
    "<NSLayoutConstraint:0x8a6bd30 V:[_UILayoutGuide:0x8a6b4b0]-(127)-[UILabel:0x8a6a010]>",
    "<_UILayoutSupportConstraint:0x8a67660 V:[_UILayoutGuide:0x8a6b4b0(20)]>",
    "<_UILayoutSupportConstraint:0x8a6a300 V:|-(0)-[_UILayoutGuide:0x8a6b4b0]   (Names: '|':UIView:0x8a6b400 )>",
    "<NSContentSizeLayoutConstraint:0x8b847e0 V:[UILabel:0x8a6a010(21)] Hug:251 CompressionResistance:750>"
) 
2014-07-04 22:25:40.869 AutoLayoutExample[2237:70b] current constraints (
    "<NSLayoutConstraint:0x8a6bde0 H:|-(179)-[UILabel:0x8a6a010]   (Names: '|':UIView:0x8a6b400 )>",
    "<NSContentSizeLayoutConstraint:0x8b847a0 H:[UILabel:0x8a6a010(42)] Hug:251 CompressionResistance:750>"
) 
2014-07-04 22:25:40.870 AutoLayoutExample[2237:70b] current constraints (
    "<NSLayoutConstraint:0x8a6bd30 V:[_UILayoutGuide:0x8a6b4b0]-(127)-[UILabel:0x8a6a010]>",
    "<_UILayoutSupportConstraint:0x8a67660 V:[_UILayoutGuide:0x8a6b4b0(20)]>",
    "<_UILayoutSupportConstraint:0x8a6a300 V:|-(0)-[_UILayoutGuide:0x8a6b4b0]   (Names: '|':UIView:0x8a6b400 )>",
    "<NSContentSizeLayoutConstraint:0x8b847e0 V:[UILabel:0x8a6a010(21)] Hug:251 CompressionResistance:750>"
) 

 
位置情報のみを指定し、size情報は指定しないが、intrisic sizeがPlaceHolder、width、heightがNoneの場合に出力されます.
2014-07-04 21:11:56.941 AutoLayoutExample[1790:70b] current constraints (
    "<NSLayoutConstraint:0x8ad9670 H:|-(179)-[UILabel:0x8ad7880]   (Names: '|':UIView:0x8ad8c90 )>",
    "<NSIBPrototypingLayoutConstraint:0x8ad9c10 'IB auto generated at build time for view with ambiguity' H:[UILabel:0x8ad7880(42@251)] priority:251>"
) 
2014-07-04 21:11:56.942 AutoLayoutExample[1790:70b] current constraints (
    "<NSLayoutConstraint:0x8ad95c0 V:[_UILayoutGuide:0x8ad8d40]-(127)-[UILabel:0x8ad7880]>",
    "<_UILayoutSupportConstraint:0x8a6d3f0 V:[_UILayoutGuide:0x8ad8d40(20)]>",
    "<_UILayoutSupportConstraint:0x8aaf250 V:|-(0)-[_UILayoutGuide:0x8ad8d40]   (Names: '|':UIView:0x8ad8c90 )>",
    "<NSIBPrototypingLayoutConstraint:0x8ad9c40 'IB auto generated at build time for view with ambiguity' V:[UILabel:0x8ad7880(21@251)] priority:251>"
) 
2014-07-04 21:11:56.943 AutoLayoutExample[1790:70b] current constraints (
    "<NSLayoutConstraint:0x8ad9670 H:|-(179)-[UILabel:0x8ad7880]   (Names: '|':UIView:0x8ad8c90 )>",
    "<NSIBPrototypingLayoutConstraint:0x8ad9c10 'IB auto generated at build time for view with ambiguity' H:[UILabel:0x8ad7880(42@251)] priority:251>"
) 
2014-07-04 21:11:56.944 AutoLayoutExample[1790:70b] current constraints (
    "<NSLayoutConstraint:0x8ad95c0 V:[_UILayoutGuide:0x8ad8d40]-(127)-[UILabel:0x8ad7880]>",
    "<_UILayoutSupportConstraint:0x8a6d3f0 V:[_UILayoutGuide:0x8ad8d40(20)]>",
    "<_UILayoutSupportConstraint:0x8aaf250 V:|-(0)-[_UILayoutGuide:0x8ad8d40]   (Names: '|':UIView:0x8ad8c90 )>",
    "<NSIBPrototypingLayoutConstraint:0x8ad9c40 'IB auto generated at build time for view with ambiguity' V:[UILabel:0x8ad7880(21@251)] priority:251>"
) 

size情報部分はIBによって自動的に生成されるが、priorityは以前の1000(required)ではなく251にすぎない.
位置のみを指定し、DefaultとPlaceHolderのconstraintsを比較すると、Defaultを使用する場合、IBはNSContentSizeLayoutConstraintを自動的に追加していることがわかります.Placeholderを使用する場合、IBはNSIBPrototypingLayoutConstraintを自動的に生成します.Placeholderを使用し、sizeはすべて0なので、IBはsize情報を知ることができません.ambiguityを避けるために自動的に追加するしかありません.
custom viewを使用する場合、intrinsic sizeをplaceholderと指定する必要がありますが、IBがambiguityのconstraintを自動的に追加する問題をどのように解決すればいいのでしょうか.
実際、私たちのviewがcustom viewであれば、IBはambityのconstraintを自動的に追加しません.IBはNSContentSizeLayoutConstraintを追加し、runtime時にcustom viewのintrinsicContentSizeを呼び出してviewがどれだけ大きいかを知ることができます.
また、intrinsicContentSizeについては、実際には一人で戦っているわけではありません.他のconstraintにはpriorityが1つしかありませんが、intrinsicContentSizeにはContent Hugging PriorityとContent Compression Resistancy Priorityの2つがあります.Content Hugging Priorityは、view frame>intrinsicContentSizeの場合、viewのsizeを縮小するかどうかを制御します.一方、Content Compression Resistancy Priorityは、view frameたとえば、UILabelがある場合は、Titleを「Label」に、Width constraintを42@500、Content Hugging Priorityを1000、Content Compression Resistancy Priorityを1に設定します.もし私がruntimeでTitleを「S」に変更したら、UILabel全体のsizeは5しか収容できないように縮小されます.このときframe sizeはIntrinsicContentSizeより大きく、Content Hugging Priorityは1000で、width constraintより高いので、Content Huggingが役に立つはずです.Titleを「325 ioqukejgakshgkjashdgjka」に変更すると、このUILabelのsizeは42になり、内容は「32...」に切り捨てられ、このときframe sizeはIntrinsicContentSizeよりも小さいため、Content Compression Resistancy Priorityは1のみで、width constraintが機能し、幅を42に設定します.
 
AutoLayoutを使った面白いBug
 
CenterYを削除する前にIBはXとYの位置情報を知っていたため,ContentSizeLayoutConstraintを付加したが,削除後,IBはそのY方向の情報を特定できずPrototypingLayoutConstraintを生成した.しかし、なぜ251のpriorityしかないPrototypingLayoutConstraintはclip labelをしないのでしょうか.では、PrototypingLayoutConstraintについてもっと知る必要があります.
 
//Before
2014-07-05 23:29:40.068 AutoLayoutExample[2035:70b] current constraints (
    "<NSLayoutConstraint:0x8b44c20 H:|-(10)-[UILabel:0x8b450f0]   (Names: '|':UITableViewCellContentView:0x8b453e0 )>",
    "<NSContentSizeLayoutConstraint:0x8b37520 H:[UILabel:0x8b450f0(42)] Hug:251 CompressionResistance:750>"
) 

//After
2014-07-05 23:32:19.251 AutoLayoutExample[2062:70b] current constraints (
    "<NSLayoutConstraint:0x8b66a10 H:|-(10)-[UILabel:0x8b664d0]   (Names: '|':UITableViewCellContentView:0x8b66210 )>",
    "<NSIBPrototypingLayoutConstraint:0x8b521f0 'IB auto generated at build time for view with ambiguity' H:[UILabel:0x8b664d0(42@251)] priority:251>"
)