[iOS] 초심자의 SnapKit 사용기

Youngwoo Lee·2022년 3월 14일
2

iOS

목록 보기
44/46
post-thumbnail

SnapKit

지난 1달 반 정도 프로젝트를 진행하면서, 처음으로 SnapKit 을 사용하게 되었다. 사용하면서도 "이게 줄어들면 얼마나 줄어든다고... 왜 쓰지?" 라는 생각을 했었는데, 우연히 옛날 레포를 살펴보다가, NSLayoutConstraint 를 통해서 AutoLayout 설정을 한 코드를 보고 그제서야 깨달았다.

정말 정말 읽기 불편한 이 코드를 무슨 생각으로 썼는지 모르겠다.

오늘은 이러한 생각을 한 김에 한달 반 동안 써본 SnapKit 을 쓰면서 탐구했던 내용들을 블로그에 정리하는 시간을 가져보려고 한다!


시작하기

자, 무엇이든 개발을 할 때 처음 경험한다면 반드시 읽어야 하는 것이 있다. 바로 공식문서! 왜냐? 만든 놈이 제일 잘 설명하고, 제일 잘 알테니깐!

제일 시작은 일단, 어느 라이브러리와 다를 것 없이 Dependency 추가 방법에 대해서 나오고 있다. 재미 없으니 넘어가겠다.


사용법(Usage)

사용법에서는 일단 사용하기 엄청 쉽다고 자랑하고 있다. 예시로 나와 있는 것이 있는데, UIViewbox 를 superView로부터 20의 padding 을 주는 코드를 보여주고 있다.

let box = UIView()
superView.addSubView(box)

box.snp.makeConstraints {
  $0.edges.equalToSuperView().inset(20)
}

이전에, NSLayoutConstraint 를 통해서 AutoLayout 을 설정하는 것에 비해서 코드가 대폭 줄어든 것을 느낄 수 있을 것이다.

아 그리고 또 한 가지!! 매번 코드 베이스로 UI 를 구현할 때, 정말 정말 귀찮았고 빠지면 에러를 불러일으키는 translatesAutoresizingMaskIntoConstraints = false ... 이것도 대신 해줘서 너무 편리하다.


Equal 로 처리하는 것만 있는 것은 아니다 (Not all things are created equal)

  • .equalTo 의 경우는 NSLayoutConstraint.Relation.equal 와 동일
  • .lessThanOrEqualTo 의 경우는 NSLayoutConstraint.Relation.lessThanOrEqual 와 동일
  • .greaterThanOrEqualTo 의 경우는 NSLayoutConstraint.Relation.greaterThanOrEqual 와 동일

위와 같이 "동일", "작거나 동일", "크거나 동일" 세 가지의 식을 만들어줄 수 있다.


View 속성 (ViewAttribute)

위에서 소개 해준 등호, 부등호를 사용하기 위해서는 Element 들이 필요할 텐데, 아래와 같다. NSLayoutConstraint 를 사용해봤다면 익히 알던 것들이다.


UiView/NSView

위에서 소개한 것들을 종합해서 view.leftlabel.left 보다 크거나 같을 경우에는 아래와 같이 코드를 작성하면 된다.


Strict Checks

다른 뷰들과의 비교 말고도 상수로도 설정할 수 있는데, 아래와 같이 너비와 높이 값을 상수를 통해서 설정할 수 있다.

// width >= 200 && width <= 400
make.width.greatherThanOrEqualTo(200)
make.width.lessThanOrEqualTo(400)

하지만, Auto Layout 의 경우 left, right, center Y 등등과 같은 alignment 설정에서는 constant Value를 사용하지 못한다는 점! 만약에 주게 된다면?! superView에 대한 설정으로 인식된다고 한다.

// creates view.left <= view.superview.left + 10
make.left.lessThanOrEqualTo(10)
make.top.equalTo(42)
make.height.equalTo(20)
make.size.equalTo(CGSize(width: 50, height: 100))
make.edges.equalTo(UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0))
make.left.equalTo(view).offset(UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0))

우선순위에 대해서 알아보자 (Learn to prioritize)

.priority 는 특정 설정에 대한 우선순위를 지정해줄 수 있다.

다들 SnapKit 이 아니더라도 AutoLayout 설정을 할 때 huggingPriority 나 compressionResistencePriority를 설정한 경험이 있을 것이다.

Priority 는 constraint chain 뒤쪽에서 설정해줄 수 있다

make.top.equalTo(label.snp.top).priority(600)

상수를 사용할 수도 있지만, low, medium, high, required 로 열거형으로 지정되어 있는 값들을 사용할 수도 있다.


Composition, Composition, Composition

그리고 위에서 알려준 메서드들로 하나씩 설정할 수도 있지만 한꺼번에 설정해줄 수도 있다.

edges

// make top, left, bottom, right equal view2
make.edges.equalTo(view2)

make.edges.equalTo(superView).inset(UIEdgeInsets(top: 5, left: 10, bottom: 15, right: 15))

size

// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

// make width = superview.width + 100, height = superview.height + 100
make.size.equalTo(superview).offset(100)

center

// make centerX and centerY = button1
make.center.equalTo(button1)

// make centerX = superview.centerX + 5, centerY = superview.centerY + 5
make.center.equalTo(superview).offset(5)

Hold on for dear life

View를 애니메이션화 시키거나 제거하거나 바꾸기 위해서는 기존 Constraint를 수정해야 하는 경우가 있다. SnapKit에서는 제약 조건을 업데이트 하기 위한 몇 가지 다른 접근 방식이 있다.

1. 참고 타입(References)

Constraint 설정 결과를 로컬 변수 또는 클래스 속성에 할당하여 특정 제약 조건의 참조를 유지할 수 있다. 여러 구속조건을 배열에 저장하여 참조할 수도 있다.

var topConstraint: Constraint? = nil

...
// when making constraints
view1.snp.makeConstraints { (make) -> Void in
  self.topConstraint = make.top.equalTo(superview).offset(padding.top).constraint
  make.left.equalTo(superview).offset(padding.left)
}

...
// then later you can call
self.topConstraint.deactivate()

// or if you want to update the constraint
self.topConstraint.updateOffset(5)

2. snp.updateConstraints

constraint를 변경해줄 때는 snp.makeConstraints 대신해서 snp.updateConstraints 를 사용하면 됩니다.

// this is Apple's recommended place for adding/updating constraints
// this method can get called multiple times in response to setNeedsUpdateConstraints
// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints

// updateConstraints 메서드는 constraints들을 adding 혹은 updating할 때 최적의 장소입니다.
// 이 메서드는 setNeedsUpdateConstraints 혹은 여러 trigger에 의해서 여러 번 호출될 수 있습니다.
override func updateConstraints() {
    self.growingButton.snp.updateConstraints { (make) -> Void in
        make.center.equalTo(self);
        make.width.equalTo(self.buttonSize.width).priority(250)
        make.height.equalTo(self.buttonSize.height).priority(250)
        make.width.lessThanOrEqualTo(self)
        make.height.lessThanOrEqualTo(self)
    }
    
   // according to Apple super should be called at end of method
   super.updateConstraints()
}

3. snp.remakeConstraints

snp.remakeConstraintssnp.makeConstraints 와 비슷합니다. 그러나 remake를 할 경우에는 SnapKit 에 의해서 이제껏 설정해 둔 모든 Constraint가 없어지니 조심해서 사용해야 됩니다.

func changeButtonPosition() {
  self.button.snp.remakeConstraints { (make) -> Void in 
    make.size.equalTo(self.buttonSize)

    if topLeft {
      make.top.left.equalTo(10)
    } else {
      make.bottom.equalTo(self.view).offset(-10)
      make.right.equalTo(self.view).offset(-10)
    }
  }
}


마치며

이상으로, SnapKit 공식문서를 바탕으로 SnapKit 사용 방법에 대해서 알아봤다.

다음 시간에는 마지막으로, SnapKit에서 offset 과 inset의 차이점에 대해서 알아보도록 하자!

profile
iOS Developer Student

0개의 댓글