Program Tip

자동 레이아웃 : UIView-Encapsulated-Layout-Width & Height라는 제약 조건을 만드는 것은 무엇입니까?

programtip 2020. 11. 10. 22:09
반응형

자동 레이아웃 : UIView-Encapsulated-Layout-Width & Height라는 제약 조건을 만드는 것은 무엇입니까?


내 레이아웃 제약 조건은 Interface Builder에서 괜찮지 만 프레임 워크의 일부가 실제로 원하지 않는 고정 높이 및 너비 제약 조건을 적용하여 런타임에 예외가 발생합니다. 왜 거기에 있으며 어떻게 끄나요?

기록 된 목록에 표시된 마지막 두 가지 제약 조건입니다.

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>

많은 관찰을 바탕으로 제약 조건 및 친구에 의해 명명 UIView-Encapsulated-Layout-Width되고 UIView-Encapsulated-Layout-Height생성되었으며 델리게이트 메서드가 UICollectionView반환하는 크기를 적용하기 위해 존재 한다고 믿습니다 (확실히 알 수는 없음) sizeForItemAtIndexPath. UICollectionViewCell설정이 cellForItemAtIndexPath끝날 것이라고 말한 크기가 되도록 보장하기 위해 거기 에 있다고 생각합니다.

여기에 내 초기 질문에 대한 답이 있습니다. 두 번째 질문은 제약 조건이 만족스럽지 않은 이유입니다. 셀의 고유 높이는 UIView-Encapsulated-Layout-Height. 다시 말하지만, 확실하지는 않지만 반올림 오류라고 생각합니다 (즉, 고유 높이가 200.1 픽셀로, UIView-Encapsulated-Layout-Height반올림 되었을 수도 있습니다. UIView-Encapsulated-Layout-Height마지막 단어를 가질 있습니다.


이것은 귀하의 질문에 대한 답변이 아닐 수 있지만 검색을 통해 여기에 온 나와 같은 다른 사람들에게 도움이 될 수 있습니다.

아직 AutoLayout으로 크기가 조정되지 않은 테이블 뷰에를 UIView-Encapsulated-Layout-Width추가했기 때문에 제약 조건 과 함께 이상한 AutoLayout 중단 제약 조건 오류가 발생했습니다 tableHeaderView. 그래서 시스템은 내 헤더 하위 뷰의 제약 조건을 {0,0,0,0}. UITableView는 요소의 너비 제어를 좋아하기 때문에 생성 된 너비 제약 조건 UIView-Encapsulated-Layout-Width은 0으로 설정되어 320 + pt 너비를 예상하는 헤더 요소와 모든 종류의 혼동을 일으켰습니다.

요점 : AutoLayout에 의해 tableview의 크기가 조정 된 후에 보충 / 머리글 / 바닥 글보기를 추가 / 조작하고 있는지 확인하십시오.


나는 똑같은 기이 한 제약에 직면하고 있었고 그 끔찍한 translatesAutoresizingMaskIntoConstraints재산을 기억할 때까지 그 이유를 알지 못했습니다 . 이를 설정 false하여 문제 해결했습니다. 백그라운드에서 일어나는 일은 자동 크기 조정 마스크 (iOS 용 이전 레이아웃 엔진)가 제약 조건으로 변환된다는 것입니다. 종종 당신은 이러한 제약을 원하지 않고 자신의 제약을 원합니다. 이러한 경우이 속성을 false로 설정해야합니다.

view.translatesAutoresizingMaskIntoConstraints = false

이러한 제약 조건에 대한 참조를 포함하는 iOS 11에서 수많은 레이아웃 충돌이 발생했으며 실제로 translatesAutoresizingMaskIntoConstraints플래그 를 통해 추가되었습니다 . iOS 11에서는 뷰가 레이아웃 될 때만 (이전 iOS 버전에서 작동하는 것처럼 보였으므로) 뷰가 계층 구조에 추가 될 때 훨씬 더 많은 AutoLayout 마법이 발생하는 것 같습니다.

다음과 같은 상황이 발생했습니다.

  • 내부 레이아웃이 뷰 크기를 정의하는 데 도움이되는 뷰를 만듭니다 (예 : 뷰에 명시적인 패딩 등을 포함하는 내부 제약이 있음).
  • ***이보기를 계층 구조에 추가하십시오.
  • 나중에 레이아웃이 전달되기 전에 translatesAutoresizingMaskIntoConstraints를 false로 설정하십시오.

두 번째 단계 (***)는 뷰가 계층 구조에 추가 될 때 시스템이 뷰에 0 크기 제약 조건을 추가하므로 충돌이 발생합니다. 우리는 설정되었다 translatesAutoresizingMaskIntoConstraints... 그 말, 당신이 해제 기억할 필요가 아이폰 OS 11 뷰를 제한 할 때 자동으로 올바르게 플래그를 설정하는 PureLayout 프레임 워크를 사용의 결과로 나중에 translatesAutoresizingMaskIntoConstraints보기가 추가되기 전에 건설시, 계층.

나는 Apple 이이 플래그를 YES로 기본 설정하는 것이 고통스러운 것보다 훨씬 더 도움이 될 것이라고 생각했습니다. 불행히도 이것은 사실이 아닙니다.


나는 모든 종류의 상황 에서이 오류가 발생했습니다 ( 여기 에서 정답이 제안한대로 UICollectionView 및 친구들과 반드시 ​​연결되어 있지는 않습니다 ) ..

그래서 그것을 처리하는 방법은 단순히 모든 제약 조건을 지우고 다시 구축하는 것입니다 (이번에는 제약 조건이 사전 생성 된 제약 조건과 충돌하는 것을 두려워하지 않습니다).

그래서 코드에서 :

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

clearConstraintsOfSubviewUIView의 카테고리 메소드는 어디에 있습니까?

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

확실히에이보고 UITableViewtableHeaderView. 를 설정 한 후 너비를 명시 적으로 설정 한 다음 레이아웃 단계가 완료된 후 다시 tableView설정하여 사용자 지정 헤더보기에서이 작업을 수행 할 수있었습니다 tableHeaderView.

다음 UITableView같이 메서드에 전달되고 tableView이를 구성 할 항목 이 있다고 가정하는 iOS 9 용 예제 코드 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

금붕어에 대한 기억이 있기 때문에 다시 찾아 볼 때에 대한 몇 가지 메모입니다.

  • 에서 호출 할 필요가 없습니다 . 설정하는 동안 적절한 너비를 갖는 viewDidLayoutSubviews한이 기술을 사용할 수있었습니다 tableView.
  • 헤더보기가 자동으로 크기가 조정되도록 설정되어 있는지 확인해야합니다. 를 만든 .xib다음 모든 항목이 고정되었는지 확인하여보기의 너비가 변경되면 높이가 업데이트되도록했습니다.
  • If you're trying to do this for viewForHeaderInSection, you're probably better off grabbing something offscreen which you can lay out a la this technique. I haven't had much luck with the self-sizing bits.

In my case, I was inadvertently setting up my programmatic constraints twice. As soon as I removed the duplicate call, the conflicts went away.


I catch this problem when I use AL create tableviewHeader

I init tableview like below

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

then I create tableviewHeader with AutoLayout.

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

symbolic breakpoint appear

After I refer @Yerk 's the answer. I change the frame when I init tableView

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

The problem seems to be solved


I was facing a similar issue and solved it with the following.

  • Environment: Swift 5.0, xcode 10.2.1, Setting views programmatically

  • Warning message: Unable to simultaneously satisfy constraints... 'UIView-Encapsulated-Layout-Width' UIView:0x0000000000.width == 0 (active)>" )

  • Code with warning

    override func loadView() {
    
    view = UIView()
    
    /// Adds the subviews to the view and sets their properties and constraints
    setupViews()
    
    }
    
  • Code that cleared warning

    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()
    }
    
  • Notes on the loadView() method: "If you use Interface Builder to create your views and initialize the view controller, you must not override this method. You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the view property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not call super." - Apple documentation

  • Notes on the root view:

    "If you prefer to create views programmatically ... you do so by overriding your view controller’s loadView method. Your implementation of this method should do the following:

    Create a root view object. The root view contains all other views associated with your view controller. You typically define the frame for this view to match the size of the app window, which itself should fill the screen. However, the frame is adjusted based on how your view controller is displayed. See “View Controller View Resizing.”

    You can use a generic UIView object, a custom view you define, or any other view that can scale to fill the screen.

    Create additional subviews and add them to the root view." - Old apple documentation?


I was having a similar problem found from testing Split View on the iPad Pro, and DesignatedNerd's answer worked but I didn't need so much code. Here is what I used:

[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]];

Note the addition of the Y Constraint, which binds the top of the tableHeaderView to the top of the tableView.


I had the same issue when adding constraints to a Table view header. It seem to occur when adding constraints with set constants when the bounds of the header was (0,0,0,0). I managed to fix this by only adding the constraints in the layout subviews method when the bounds of the header was not (0,0,0,0)

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

constraint UIView-Encapsulated-Layout-Height is created with value you set in tableView.estimatedSectionHeaderHeight


After banging my head for a while i found this link. In my case it was happening on the UITableViewHeaderFooterView when i was using insertRows or deleteRows from my UIVieController. 'estimatedSectionHeaderHeight' and 'estimatedRowHeight' where set, my constraints redone 3 times ... The error shown was:

"<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)>"

As stated on the link:

"When you do insertRows or deleteRows with certain animation types, UIKit will animate the row height from 0 to full height or back. At the 0-end of that animation, the layout equations are impossible to solve if entire vertical axis is set to priority=1000. But lower just one constraint to 999 – say that bottom space to superview margin – and all is fine; the content will just drop-down, outside the cell’s bounds.".

The solution was to set to 999 (or lower to 1000) the leading priority of the UIImageView.

참고URL : https://stackoverflow.com/questions/23308400/auto-layout-what-creates-constraints-named-uiview-encapsulated-layout-width-h

반응형