Constraints with Code #1

19904 단어 iOSiOS

Constraints with Code #0 에서 작성했던

NSLayoutConstraint NSLayoutAnchor를 이용해 직접 화면을 구성해보자.

우선, 화면을 절반으로 나누고 아래의 View를 위의 View와 동일하게 출력되게끔 코드로 직접 제약을 생성해보자.

우선, NSLayoutConstraint NSLayoutAnchor 를 테스트해볼거니까 extension해서 따로따로 함수를 만들자.

  • layoutWithInitializer() -> NSLayoutConstraint
  • layoutWithAnchor() -> NSLayoutAnchor

NSLayoutConstraint 를 이용한 방법

extension FillParentViewController {
   func layoutWithInitializer() {
    blueView.translatesAutoresizingMaskIntoConstraints = false // #1
    
    let leading = NSLayoutConstraint(item: blueView, attribute: .leading, relatedBy: .equal, toItem: bottomContainer, attribute: .leading, multiplier: 1.0, constant: 0)
    let top = NSLayoutConstraint(item: blueView, attribute: .top, relatedBy: .equal, toItem: bottomContainer, attribute: .top, multiplier: 1.0, constant: 0)
    let trailing = NSLayoutConstraint(item: blueView, attribute: .trailing, relatedBy: .equal, toItem: bottomContainer, attribute: .trailing, multiplier: 1.0, constant: 0)
    let bottom = NSLayoutConstraint(item: blueView, attribute: .bottom, relatedBy: .equal, toItem: bottomContainer, attribute: .bottom, multiplier: 1.0, constant: 0)
    
    NSLayoutConstraint.activate([leading,top,trailing,bottom])
   }
}
  • NSLayoutConstraint를 이용해 원하는 제약을 생성하고, activate 메소드를 통해 제약을 활성화 하는 방식으로 사용한다.

  • 이 activate 메소드는 활성화 할 제약을 배열로 전달받아 올바른 위치에 자동으로 추가해준다.

!! 여기서 주의할 점
#1 의 코드를 작성하지 않게되면 내가 원하지 않는 결과가 출력된다.

why??

  • viewController안에 blueView는 코드로 제약을 생성하기전까지 아무런 제약없이 놓여있기 때문이다.

  • 이런 경우, 인터페이스 빌더가 알아서 NSAutoresizingMaskLayoutConstraint 을 기반으로 제약을 자동으로 추가한다.

  • 그렇기 때문에 내가 생성해서 적용한 제약과 NSAutoresizingMaskLayoutConstraint을 을 기반으로 자동으로 추가된 제약이 충돌을 일으키기 때문이다.

해결을 위해선 #1 의 코드처럼 translatesAutoresizingMaskIntoConstraints을 사용하지 않는다고 선언해주면 된다.

blueView.translatesAutoresizingMaskIntoConstraints = false // #1

NSLayoutAnchor 를 이용한 방법

extension FillParentViewController {
   func layoutWithAnchor() {
    blueView.translatesAutoresizingMaskIntoConstraints = false
    
    blueView.leadingAnchor.constraint(equalTo: bottomContainer.leadingAnchor).isActive = true// #1
    blueView.trailingAnchor.constraint(equalTo: bottomContainer.trailingAnchor).isActive = true
    blueView.topAnchor.constraint(equalTo: bottomContainer.topAnchor).isActive = true
    blueView.bottomAnchor.constraint(equalTo: bottomContainer.bottomAnchor).isActive = true
   }
}

NSLayoutConstraint 을 이용한 방식보다 훨씬 간단하다!

  • 각각의 제약은 View가 가지고 있는 Anchor 속성으로 지정할 수 있다.

  • 각각의 Anchor 속성은 다양한 메소드를 제공한다.

  • #1 과 같이 constraint 메소드에 SuperView의 원하는 Anchor속성을 전달하며느 그 앵커를 기준으로 relation 이 equal이고 constant 가 0인 제약이 추가된다.

NSLayoutConstraint 방식과 마찬가지로 NSLayoutAnchor 도 꼭 translatesAutoresizingMaskIntoConstraints을 사용하지 않는다고 선언해줘야 한다.

blueView.translatesAutoresizingMaskIntoConstraints = false

결과 화면

두 방식을 비교해보자 ㅎㅋㅎㅋ

같은 제약을 생성해 같은 화면을 구성했지만 두 방식의 코드 구현을 살펴보면

NSLayoutConstraint

extension FillParentViewController {
   func layoutWithInitializer() {
    blueView.translatesAutoresizingMaskIntoConstraints = false // #1
    
    let leading = NSLayoutConstraint(item: blueView,
                                      attribute: .leading, 
                                      relatedBy: .equal,
                                      toItem: bottomContainer, 
                                      attribute: .leading,
                                      multiplier: 1.0, 
                                      constant: 0)
    let top = NSLayoutConstraint(item: blueView, 
                                  attribute: .top, 
                                  relatedBy: .equal,
                                  toItem: bottomContainer,
                                  attribute: .top, 
                                  multiplier: 1.0, 
                                  constant: 0)
    let trailing = NSLayoutConstraint(item: blueView, 
                                        attribute: .trailing, 
                                        relatedBy: .equal,
                                        toItem: bottomContainer,
                                        attribute: .trailing,
                                        multiplier: 1.0,
                                        constant: 0)
    let bottom = NSLayoutConstraint(item: blueView, 
                                      attribute: .bottom, 
                                      relatedBy: .equal,
                                      toItem: bottomContainer,
                                      attribute: .bottom,
                                      multiplier: 1.0, 
                                      constant: 0)

    NSLayoutConstraint.activate([leading,top,trailing,bottom])
   }
}

NSLayoutAnchor

extension FillParentViewController {
   func layoutWithAnchor() {
    blueView.translatesAutoresizingMaskIntoConstraints = false
    
    blueView
    .leadingAnchor
    .constraint(equalTo: bottomContainer.leadingAnchor)
    .isActive = true// #1
    blueView
    .trailingAnchor
    .constraint(equalTo: bottomContainer.trailingAnchor)
    .isActive = true
    blueView
    .topAnchor
    .constraint(equalTo: bottomContainer.topAnchor)
    .isActive = true
    blueView
    .bottomAnchor
    .constraint(equalTo: bottomContainer.bottomAnchor)
    .isActive = true
   }
}

훠어얼씬 가독성도 좋고 간단하게 구현할 수 있다는걸 알 수 있다 !

좋은 웹페이지 즐겨찾기