[편집 : 경고 : 후속 토론 전체가 iOS 8에 의해 낡았거나 적어도 크게 완화되어 뷰 변환이 적용될 때 레이아웃을 트리거하는 실수를 더 이상하지 않을 수 있습니다.]
자동 레이아웃 vs. 뷰 변환
자동 레이아웃은 뷰 변환에서 전혀 잘 재생되지 않습니다. 내가 알 수있는 한 그 이유는 변환 (기본 ID 변환 이외)이있는 뷰의 프레임을 엉망으로 만들지 않아야하기 때문입니다. 그러나 이것이 자동 레이아웃이하는 것입니다. 자동 레이아웃이 작동하는 방식 layoutSubviews은 런타임에서 모든 제약 조건을 따라 파싱하고 모든 뷰의 프레임을 적절하게 설정하는 것입니다.
다시 말해, 제약은 마술이 아닙니다. 그들은 단지 할 일 목록 일뿐입니다.layoutSubviews할 일 목록이 완성되는 곳입니다. 그리고 프레임을 설정하여 수행합니다.
나는 이것을 버그로 도울 수 없다. 이 변환을 뷰에 적용하면 :
v.transform = CGAffineTransformMakeScale(0.5,0.5);
뷰가 중심과 함께 이전 크기와 절반 크기로 나타납니다. 그러나 제약 조건에 따라 내가 전혀 보지 못할 수도 있습니다.
[실제로 두 번째 놀라운 점이 있습니다. 뷰에 변환을 적용하면 레이아웃이 즉시 트리거됩니다. 이것은 나에게 또 다른 버그 인 것 같습니다. 아니면 아마도 첫 번째 버그의 핵심 일 것입니다. 내가 기대할 수있는 것은 레이아웃 시간까지 최소한 프레임 시간으로 프레임 애니메이션으로 도망 갈 수있는 것처럼 레이아웃 시간까지 장치를 회전시킬 때까지 변환으로 벗어날 수 있다는 것입니다. 그러나 실제로 레이아웃 시간은 즉각적이며 이는 잘못된 것 같습니다.]
해결 방법 1 : 제한 없음
현재 해결책 중 하나는 반영구적 변환을 뷰에 적용하고 (일시적으로 흔들리는 것이 아니라) 뷰에 영향을 미치는 모든 제약 조건을 제거하는 것입니다. 불행히도 자동 레이아웃이 여전히 발생하기 때문에 일반적으로 화면에서 뷰가 사라지고 뷰를 배치 할 위치를 알려주는 제약이 없습니다. 따라서 제약 조건을 제거하는 것 외에도보기 translatesAutoresizingMaskIntoConstraints를 YES로 설정했습니다 . 뷰는 이제 자동 레이아웃의 영향을받지 않고 이전 방식으로 작동합니다. (그것은 됩니다 분명, 자동 레이아웃에 영향을하지만, 암시 적 자동 크기 마스크 제약의 동작이 자동 레이아웃 전과 마찬가지로 원인이 될.)
해결 방법 2 : 적절한 제약 조건 만 사용
약간 과감한 것처럼 보이면 다른 솔루션은 의도 한 변환에서 제약 조건이 올바르게 작동하도록 설정하는 것입니다. 예를 들어 뷰의 내부 고정 너비와 높이에 따라 크기가 정해지고 중심에 의해 순수하게 배치되면 스케일 변환이 예상대로 작동합니다. 이 코드에서는 하위 뷰 ( otherView) 의 기존 제약 조건을 제거하고 해당 제약 조건을 네 가지 제약 조건으로 대체하여 너비와 높이를 고정하고 중심을 기준으로 고정합니다. 그 후 스케일 변환이 작동합니다.
NSMutableArray* cons = [NSMutableArray array];
for (NSLayoutConstraint* con in self.view.constraints)
if (con.firstItem == self.otherView || con.secondItem == self.otherView)
[cons addObject:con];
[self.view removeConstraints:cons];
[self.otherView removeConstraints:self.otherView.constraints];
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeCenterX relatedBy:0 toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:self.otherView.center.x]];
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:self.otherView.center.y]];
[self.otherView addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeWidth relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:self.otherView.bounds.size.width]];
[self.otherView addConstraint:
[NSLayoutConstraint constraintWithItem:self.otherView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:self.otherView.bounds.size.height]];
결론은 뷰의 프레임에 영향을 미치는 구속 조건이없는 경우 자동 레이아웃은 뷰의 프레임을 건드리지 않는다는 것입니다.
해결 방법 3 : 하위 뷰 사용
위의 두 가지 해결 방법의 문제점은 제약 조건의 이점을 잃어 시야를 확보 할 수 없다는 것입니다. 이를 해결하는 솔루션이 있습니다. 작업이 호스트 역할만을하는 보이지 않는보기로 시작하고 제약 조건을 사용하여 배치하십시오. 그 안에 실제 뷰를 하위 뷰로 넣습니다. 제약 조건을 사용하여 호스트 뷰 내에 하위 뷰를 배치 할 수 있지만 변환을 적용 할 때 반박하지 않는 제약 조건으로 제한 조건을 제한하십시오.
그림은 다음과 같습니다.

흰색보기는 호스트보기입니다. 투명하고 보이지 않는 것처럼 가장해야합니다. 빨간색 뷰는 중앙을 호스트 뷰의 중앙에 고정하여 배치 된 하위 뷰입니다. 이제 우리는 아무런 문제없이 중앙을 중심으로 빨간색보기를 확장하고 회전시킬 수 있으며 실제로 그림은 우리가 그렇게했음을 보여줍니다.
self.otherView.transform = CGAffineTransformScale(self.otherView.transform, 0.5, 0.5);
self.otherView.transform = CGAffineTransformRotate(self.otherView.transform, M_PI/8.0);
한편 호스트보기의 제약 조건은 장치를 회전 할 때 올바른 위치에 유지됩니다.
해결 방법 4 : 대신 레이어 변환 사용
뷰 변환 대신 레이아웃을 트리거하지 않으므로 구속 조건과 즉시 충돌하지 않는 레이어 변환을 사용하십시오.
예를 들어,이 간단한 "throb"뷰 애니메이션은 자동 레이아웃에서 잘릴 수 있습니다.
[UIView animateWithDuration:0.3 delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
v.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
v.transform = CGAffineTransformIdentity;
}];
결국 뷰의 크기에는 변화가 없었지만 transform레이아웃을 설정 하면 레이아웃이 발생하고 제약 조건으로 인해 뷰가 건너 뛸 수 있습니다. (버그처럼 보입니까?) 그러나 CABasicAnimation을 사용하고 뷰 레이어에 애니메이션을 적용하는 Core Animation과 동일한 작업을 수행하면 레이아웃이 발생하지 않으며 제대로 작동합니다.
CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.autoreverses = YES;
ba.duration = 0.3;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
[v.layer addAnimation:ba forKey:nil];
layerView너비를 어떻게 알 수 있습니까? 오른쪽이 다른 것을 고집하고 있습니까?