[iOS] AutoLayout 기본개념(6)

Youngwoo Lee·2021년 9월 3일
0

iOS

목록 보기
28/46
post-thumbnail

이번 시간에는 Safe Area와 Layout Margin에 대해서 알아보고,
연장선으로 Scroll View, Cell에서 AutoLayout 설정, Constraint 변경 까지 정리해보자!

Safe Area

iOS에서는 Navigation Bar, Tool Bar 혹은 기기의 노치 부분에 있어서 가려지지 가능성이 없는 View가 잘 표시되는 부분을 Safe Area로 지정해준다

지난 시간에 Anchor이나 NSLayoutConstraint를 활용할 때, 자주 사용했던 것이기도 한 safeAreaLayoutGuide이 Safe Area 부분을 의미하는 객체이기도 하다.

또한, safeAreaInsets 프로퍼티 같은 경우는 bottom, left, right, top의 CGFloat 타입의 프로퍼티를 가지고 있어서 safeArea의 위치 값을 읽을 수 있다

그리고 additionalSafeAreaInsets 객체를 통해서 SafeArea 영역을 변경해 줄 수도 있는데, 가급적이면 SafeArea를 그대로 사용하자!!

바꾸는 것은 아무래도 복잡해보인다...ㅎ

override func viewDidAppear(_ animated: Bool) {
   var newSafeArea = UIEdgeInsets()
   // Adjust the safe area to accommodate 
   //  the width of the side view.
   if let sideViewWidth = sideView?.bounds.size.width {
      newSafeArea.right += sideViewWidth
   }
   // Adjust the safe area to accommodate 
   //  the height of the bottom view.
   if let bottomViewHeight = bottomView?.bounds.size.height {
      newSafeArea.bottom += bottomViewHeight
   }
   // Adjust the safe area insets of the 
   //  embedded child view controller.
   let child = self.childViewControllers[0]
   child.additionalSafeAreaInsets = newSafeArea
}



Layout Margin

참고자료) https://yagom.net/forums/topic/야곰닷넷-질문모음-8/

Layout Margin 같은 경우는 StoryBoard에서 자주 봤는데,
일종의 View의 Padding(충전제) 라고 할 수 있다

View의 Layout과 Content 사이에 비어있는 공간이라고 생각하면 좋다

  • 기본적으로 UIView는 top, bottom, right, left 네 가장자리에 8 포인트의 여백을 가진다. 인터페이스 빌더의 Editor > Canvas > Layout Rectangels 를 활성화해주면 뷰들에 기본 margin이 설정되어 있는 것을 볼 수 있다.
  • But, UIView를 상속받는 모든 뷰들은 각기 다른 기본 여백을 가지고 있다. 이 여백은 오토레이아웃 제약조건을 설정할 때 Constraint to margins 옵션을 체크해주거나, margin에 직접 제약조건을 설정할 때에만 배치에 영향을 준다




AutoLayout with ScrollViews

참고자료) Apple Developer's Document - AutoLayout with ScrollViews
Yagom.net - 오토레이아웃 정복하기

Scroll View를 처음에 사용하면 굉장히 AutoLayoout 설정하기 어지럽다...


우선 Scroll View를 사용하기 위해서는 Scroll View의 frame을 superView에서 위치와 크기를 정의하고, Scroll View의 content 지역의 크기를 정의해 주어야 한다!!

  1. Scene에 Scroll View를 얹기
  2. Scroll View를 super View에 맞게 AutoLayout 적용해보기(크기와 위치 정의)
  3. Content View 라고 이름을 지은 UIView 하나를 ScrollView 위에 추가한다
  4. Content View top, bottom, leading, trailing 을 ScrollView의 Content Layout Guide 에 Constant 0으로 맞춰준다
  5. (Optional) 만약 수직으로 scroll할 경우에는 Content View의 width를 Scroll View의 Frame Layout Guide와 동일하게 한다
  6. (Optional) 수평으로 scroll할 경우에는 Content View의 height를 Scroll View의 Frame Layout Guide와 동일하게 한다
  7. 이후 Content View 내부에 화면에 보여주고 싶은 View들을 넣고 수직방향에 대한 AutoLayout을 설정해주면! ScrollView의 높이가 잡히면서 모든 Constraint 에러가 사라질 것이다!


Content Layout Guide : ScrollView 내부의 Content 영역
Frame Layout Guide : ScrollView 외부의 틀 (Layout 영역)




Dynamic Type

Accessibility(접근성)을 위해서 Font사이즈를 늘리고 줄이고 하는 작업을 유저가 설정을 통해서 할 수 있게 해준다

하지만 Dynamic Type만 지정해준다고 Font Size가 동적으로 변경되는 것은 아니다

위 사진의 아래 Automatically Adjust Font 설정을 해주거나

코드로 위와 같이 adjustsFontForContentSizeCategory property 값을 true 로 설정해줘야 합니다!!

UILabel 과 다르게 UIButton 의 경우는 titleLabel 내에 있는 속성을 이용해서 설정해줘야 한다는 것을 주의하자!




AutoLayout with Cells

참고자료) Apple Developer's Document - Working with Self-Sizing Table View Cells

위 자료에서는 Cell위 높이를 Dynamic하게 정해주기 위해서는 AutomaticDimensionestimatedRowHeight 를 설정해주라고 되어 있다. 지금은 default 값으로 설정되어 있다고 하는데, 그래도 무슨 의미인지는 알고 가자!!



AutomaticDimension

각각 다른 Cell마다 다른 높이를 적용하는 것이라면 tableView 메서드 중 HeightForRowAtIndexPath를 사용하여 임의로 해당 Cell의 높이를 지정해줄 수도 있다. 하지만 우리가 찾는 것은 같은 Cell을 사용하는 Row마다 각각 다른 높이를 지정해주는 것이다. 이 문제를 해결하려면 viewDidLoad에 아래처럼 AutomaticDimension을 통해 테이블 Row의 높이가 유동적이라고 선언해야 한다. 이는 위에서 지정한 Row Height를 무시하고, 각 Row안의 내용에 따라 Row 높이가 유동적으로 결정되게 된다

myTableView.rowHeight = UITableViewAutomaticDimension

estimatedRowHeight

estimatedRowHeight는 말 그대로 개발자가 예상되는 RowHeight 값이다. 이는 테이블뷰의 데이터가 Reload될 때 각 Row마다 대략적인 높이를 계산하는데 도움을 주는 역할을 한다. 아래처럼 테이블뷰의 프로퍼티 값에 직접 접근하여 예상치를 대입할 수도 있고, 테이블뷰 Delegate의 메서드를 사용해도 된다.

myTableView.estimatedRowHeight = 85

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
  return 85
}

estimatedRowHeight 의 경우 잘 지정해줘야 한다. 실제 cell의 높이에 영향을 끼치지는 않지만 테이블을 Reload할 때 해당 예상치에 따라 스크롤 position 값이 지정되기 때문이다. 해당 값이 너무 낮으면 reloadData()를 수행했을 때 엉뚱한 곳에 스크롤되는 경우가 있다.



다시 돌아와서, 일단 위 문서에서 나오는 중요사항을 보자!

해당 내용은 UITableViewCell 에서 기본적으로 제공되는 textLabel, detailTextLabel, imageView 에 대한 주의사항을 알려준다

이미 constraint 값들이 지정되어 있어서, 변경할 수 없다고 하고 있다. 같은 모양이더라도 constraint를 다르게 주고 싶다면 어쩔 수 없이 커스텀화 해야할 것 같다!

위 사진은 기본으로 제공되는 textLabel, detailTextLabel를 사용한 AutoLayout 이 적용된 cell이다




Constraints 변경하기

기존에 지정되어 있는 Constraint를 바꾸는 방법에 대해서 배워보자!

참고 문서) Apple Developer's Document-Changing Constraints

일단 위 문서를 보면 한개 이상의 constraint를 바꿀 수 있는 방법 목록을 보여준다

  1. constraint 활성화 혹은 비활성화
  2. constraint의 constant 값 변경
  3. constraint의 우선순위 변경
  4. view로부터 constraint를 완전히 삭제

해당 글을 보면 Layout 업데이트가 constraint 변경과 동시에 이루어지는 것이 아니라 잠시 미뤄진다고 하고 있다.

iPhone 의 경우 현재 나온 iPhone12 부터는 1초에 120프레임을 화면에 띄우지만 이전에는 화면에 1초에 60프레임을 띄웠다. iOS는 1/120 초에 한번의 주기로 AutoLayout을 조정한다는 것이다.

그렇기 때문에 우리는 다음 주기에 AutoLayout이 업데이트될 수 있도록 setNeedsLayout , setNeedsUpdateConstraints 메서드를 호출해야 된다.




마지막으로 꼭 읽어야 하는 WWDC

WWDC 2015 Mysteries of Auto Layout, Part I/II
WWDC 2018 High Performance Auto Layout



profile
iOS Developer Student

0개의 댓글