web-dev-qa-db-ja.com

自動レイアウト:何がUIView-Encapsulated-Layout-Width&Heightという名前の制約を作成しますか?

Interface Builderではレイアウトの制約は問題ありませんが、フレームワークの一部が固定の高さと幅の制​​約を適用するため、実行時に例外が発生します。なぜそこにあり、それらをオフにする方法ですか?

これらは、ログリストに表示される最後の2つの制約です。

2014-04-26 09:02:58.687 BBCNews[32058:60b] 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. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>",
    "<NSLayoutConstraint:0xbf47190 UIView:0xbf4a3c0.leading == BNMyNewsCell_landscape:0xbf48b10.leading>",
    "<NSLayoutConstraint:0xbf47160 UIView:0xbf4a3c0.trailing == BNMyNewsCell_landscape:0xbf48b10.trailing>",
    "<NSLayoutConstraint:0xbf47130 BNMyNewsCell_landscape:0xbf48b10.bottom == UIView:0xbf4a3c0.bottom>",
    "<NSLayoutConstraint:0xbf47100 UIView:0xbf4a3c0.top == BNMyNewsCell_landscape:0xbf48b10.top>",
    "<NSLayoutConstraint:0xd4c3c40 'UIView-Encapsulated-Layout-Width' H:[BNMyNewsCell_landscape:0xbf48b10(304)]>",
    "<NSLayoutConstraint:0xd4c38a0 'UIView-Encapsulated-Layout-Height' V:[BNMyNewsCell_landscape:0xbf48b10(290)]>"
}
Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>
67
Reuben Scratton

UIView-Encapsulated-Layout-WidthおよびUIView-Encapsulated-Layout-Heightという名前の制約はUICollectionViewとその友人によって作成され、返されるサイズを強制するために存在していると私は信じています(しかし確かではありません)。 sizeForItemAtIndexPathデリゲートメソッド。 UICollectionViewCellによってセットアップされたcellForItemAtIndexPathが最終的なサイズになることを保証するためにあると思います。

ここで私の最初の質問に答えます。 2番目の質問は、なぜ制約が満たされないのかということです。セルの固有の高さは、UIView-Encapsulated-Layout-Heightと同じでなければなりません。繰り返しますが、確かなことはわかりませんが、丸め誤差(つまり、固有の高さが200.1ピクセルになり、UIView-Encapsulated-Layout-Heightが200に丸められる可能性があります。私が思いついた修正は、優先度を下げることでした。 UIView-Encapsulated-Layout-Heightが最後のワードを持つことを許可する関連セル制約の。

88
Reuben Scratton

これはあなたの質問に答えないかもしれませんが、検索からここに来た私のような他の人を助けることができます。

まだAutoLayoutでサイズ変更されていないテーブルビューにtableHeaderViewを追加していたため、UIView-Encapsulated-Layout-Width制約を伴う奇妙なAutoLayoutの壊れた制約エラーが発生していました。そのため、システムは{0,0,0,0}のフレームを使用して、tableview内にヘッダーサブビューの制約を適用しようとしました。 UITableViewは要素の幅を制御するのが好きなので、生成された幅制約UIView-Encapsulated-Layout-Widthはゼロに設定され、320 + ptの幅を期待していたヘッダー要素とのあらゆる種類の混乱を引き起こしました。

テイクアウト:テーブルビューがAutoLayoutによってサイズ変更された後に、補助/ヘッダー/フッタービューを追加/操作していることを確認してください。

42
Yerk

私は同じ奇妙な制約に直面していました、そして、なぜかわからなかった、私はdarned translatesAutoresizingMaskIntoConstraintsプロパティを思い出した。これをfalseに設定すると、問題が解決しました。バックグラウンドで行われるのは、自動サイズ変更マスク(iOSの古いレイアウトエンジン)が制約に変換されることです。非常に多くの場合、これらの制約は必要なく、独自の制約が必要です。そのような場合、このプロパティをfalseに設定する必要があります。

view.translatesAutoresizingMaskIntoConstraints = false
6
Zoltán

UITableViewtableHeaderViewで間違いなくこれを見ています。 tableViewを設定した後、tableHeaderViewの幅と明示的に等しい幅を設定することにより、カスタムヘッダービューでこれを動作させることができ、レイアウトパスが完了した後にリセットします。

IOS 9のサンプルコードでは、UITableViewとしてメソッドに渡されるtableViewと、itemとして設定するアイテムがあると想定しています。

//Create the header view
self.contentDetailHeaderView = MyCustomHeaderView()

//Turn on autolayout
self.contentDetailHeaderView.translatesAutoresizingMaskIntoConstraints = false

//Add the header to the table view
tableView.tableHeaderView = self.contentDetailHeaderView

//Pin the width  
let widthConstraint = NSLayoutConstraint(item: self.contentDetailHeaderView,
    attribute: .Width,
    relatedBy: .Equal,
    toItem: tableView,
    attribute: .Width,
    multiplier: 1,
    constant: 0)

tableView.addConstraint(widthConstraint)

//Do whatever configuration you need to - this is just a convenience method I wrote on my header view.
self.contentDetailHeaderView.setupForItem(item)

//Lay out the configured view
self.contentDetailHeaderView.layoutIfNeeded()

//Reset the table header view, because ¯\_(ツ)_/¯
tableView.tableHeaderView = self.contentDetailHeaderView

いくつかのメモ、主に金魚の記憶があるのでこれをもう一度調べるときのために:

  • あなたはnotviewDidLayoutSubviewsからこれを呼び出す必要があります-私はtableViewセットアップ中に適切な幅があります。
  • ヘッダービューが自動的にサイズ変更されるように設定する必要があります。これを行うには、.xibそして、すべてのアイテムが固定されていることを確認して、ビューの幅が変わると高さが更新されるようにします。
  • viewForHeaderInSectionでこれを行おうとしているなら、おそらく このテクニック をレイアウトできるオフスクリーンのものをつかむほうがいいでしょう。私は自己サイズ調整ビットであまり運がありませんでした。
3
DesignatedNerd

あらゆる種類の状況でこのエラーが発生しました(ここで correct answerで示唆されているように、必ずしもUICollectionViewや友人に結び付けられているわけではありません)。

したがって、私の対処方法は、すべての制約をクリアしてから再度構築することでした(今回だけは、これらの事前に作成された制約と競合する恐れがありません)。

コードで:

UIView *parentView = [viewInQuestion superview];
[parentView clearConstraintsOfSubview:viewInQuestion];

ここで、clearConstraintsOfSubviewはUIViewのカテゴリメソッドです。

- (void)clearConstraintsOfSubview:(UIView *)subview
{
    for (NSLayoutConstraint *constraint in [self constraints]) {
        if ([[constraint firstItem] isEqual:subview] || [[constraint secondItem] isEqual:subview]) {
            [self removeConstraint:constraint];
        }
    }
}
3
abbood

私の場合、意図せずにプログラム制約を2回設定していました。重複した呼び出しを削除するとすぐに、競合はなくなりました。

1
tcarey

AL create tableviewHeaderを使用すると、この問題をキャッチします

私は以下のようにテーブルビューを初期化します

_let table = UITableView.init(frame: .zero, style: .grouped)
// set table constraint ...
_

次に、AutoLayoutを使用してtableviewHeaderを作成します。

"<NSLayoutConstraint:0x600003d7d130 'UIView-Encapsulated-Layout-Width' UIView:0x7fe92bc55260.width == 0 (active)>"

シンボリックブレークポイントが表示されます

@Yerkの答えを参照した後。 tableViewを初期化するときにフレームを変更します

_let rect = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 0)
let table = UITableView.init(frame:rect , style: .grouped)
_

問題は解決されたようです

1
柯力乘

私は同様の問題に直面しており、次のようにして解決しました。

  • 環境: Swift 5.0、xcode 10.2.1、プログラムによるビューの設定

  • 警告メッセージ:制約を同時に満たすことができません... 'UIView-Encapsulated-Layout-Width' UIView:0x0000000000.width == 0(active)> ")

  • 警告付きコード

    override func loadView() {
    
    view = UIView()
    
    /// Adds the subviews to the view and sets their properties and constraints
    setupViews()
    
    }
    
  • 警告をクリアしたコード

    override func loadView() {
    
    /// Needed to set the frame of the root view to the window frame.
    let window = UIWindow()
    view = UIView(frame: window.frame)
    
    /// Adds the subviews to the view and sets their properties and constraints
    setupViews()
    }
    
  • loadView()メソッドに関する注意: "Interface Builderを使用してビューを作成し、View Controllerを初期化する場合、このメソッドをオーバーライドしないでください。このメソッドをオーバーライドして、ビューを手動で作成できます。 。そうすることを選択した場合、ビュー階層のルートビューをビュープロパティに割り当てます。作成するビューは一意のインスタンスであり、他のView Controllerオブジェクトと共有しないでください。このメソッドのカスタム実装は呼び出さないでくださいスーパー。" -Appleドキュメント

  • ルートビューに関する注意:

    「プログラムでビューを作成する場合は、View ControllerのloadViewメソッドをオーバーライドすることで作成します。このメソッドの実装は次のことを行う必要があります。

    ルートビューオブジェクトを作成します。ルートビューには、View Controllerに関連付けられている他のすべてのビューが含まれています。通常、このビューのフレームは、アプリウィンドウのサイズに合わせて定義します。アプリウィンドウ自体は画面全体に表示されます。ただし、View Controllerの表示方法に基づいてフレームが調整されます。 「View Controllerビューのサイズ変更」を参照してください。

    汎用UIViewオブジェクト、定義したカスタムビュー、または画面いっぱいに拡大縮小できるその他のビューを使用できます。

    追加のサブビューを作成し、ルートビューに追加します。 "-古いApple documentation?

1
Ben Oveson

Tableビューのヘッダーに制約を追加するときに同じ問題が発生しました。ヘッダーの境界が(0,0,0,0)であるときに、定数を設定した制約を追加するときに発生するようです。ヘッダーの境界が(0,0,0,0)でなかったときにレイアウトサブビューメソッドに制約を追加するだけで、これを修正できました。

    if self.bounds == CGRect.zero {
        return
    }
0
DairySeeker

IPad ProでSplit Viewをテストした結果、同様の問題が見つかりました。DesignatedNerdの答えは機能しましたが、それほど多くのコードは必要ありませんでした。ここに私が使用したものがあります:

[self.tableView.tableHeaderView setTranslatesAutoresizingMaskIntoConstraints:NO];

NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView
                                                                   attribute:NSLayoutAttributeWidth
                                                                   relatedBy:NSLayoutRelationEqual
                                                                      toItem:self.tableView
                                                                   attribute:NSLayoutAttributeWidth
                                                                  multiplier:1
                                                                    constant:0];
NSLayoutConstraint *yConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView
                                                               attribute:NSLayoutAttributeTop
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:self.tableView
                                                               attribute:NSLayoutAttributeTop
                                                              multiplier:1
                                                                constant:0];


[self.tableView addConstraints:@[widthConstraint, yConstraint]];

TableHeaderViewの上部をtableViewの上部にバインドするY制約の追加に注意してください。

0

しばらく頭を叩いた後、私は このリンク を見つけました。私の場合、UIVieControllerからinsertRowsまたはdeleteRowsを使用していたときにUITableViewHeaderFooterViewで発生していました。 'estimatedSectionHeaderHeight'および 'estimatedRowHeight'が設定されている場合、制約が3回再実行されます...表示されるエラーは次のとおりです。

"<NSLayoutConstraint:0x280648140 H:|-(8)-[UIImageView:0x106e94860]   (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>",
"<NSLayoutConstraint:0x280648230 H:[UIImageView:0x106e94860]-(8)-[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...']   (active)>",
"<NSLayoutConstraint:0x280648410 H:[UIButton:0x106ea5a40]-(8)-|   (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>",
"<NSLayoutConstraint:0x280648460 H:[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...']-(8)-[UIButton:0x106ea5a40]   (active)>",
"<NSLayoutConstraint:0x2806493b0 'UIView-Encapsulated-Layout-Width' DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50.width == 0   (active)>"

リンクに記載されているとおり:

"特定のアニメーションタイプでinsertRowsまたはdeleteRowsを実行すると、UIKitは行の高さを0から最大の高さまで、または元に戻します。そのアニメーションの0端では、次の場合にレイアウト方程式を解くことはできません。縦軸全体がpriority = 1000に設定されています。ただし、1つの制約を999に下げます(たとえば、下のスペースからスーパービューマージンまで)。すべてが問題ありません。コンテンツはセルの境界外でドロップダウンします。 " 。

解決策は、UIImageViewの主要な優先順位を999(または1000未満)に設定することでした。

0
Reimond Hill

UIView-Encapsulated-Layout-Heightに設定した値で制約tableView.estimatedSectionHeaderHeightが作成されます

0
Maq