카테고리 없음

swift snapkit edges 헷갈리는 inset offset 용어 알아보자.

kingarthur 2024. 7. 4. 10:06

 

snapkit 사용을 안해보고 바꿔 볼려고 하다가 

        contentLabel.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

처음보는... edge 

이게 먼가 해서 찾아봤다. 

공식 문서답.

https://developer.apple.com/documentation/swiftui/edge

 

Edge | Apple Developer Documentation

An enumeration to indicate one edge of a rectangle.

developer.apple.com

 

 

SnapKit은 Swift에서 Auto Layout 제약 조건을 더 간결하게 선언할 수 있게 도와주는 라이브러리입니다. SnapKit을 사용하면 복잡한 NSLayoutConstraint 코드를 훨씬 단순하게 만들 수 있습니다.

아래에 SnapKit의 기본 사용 방법에 대해 설명하겠습니다:

  1. 기본 구조:
    SnapKit은 make, remake, update라는 세 가지 주요 함수로 구성됩니다.

makeConstraints: 새로운 제약 조건을 생성합니다.
updateConstraints: 기존 제약 조건을 수정합니다.
remakeConstraints: 기존 제약 조건을 제거하고 새로운 제약 조건을 생성합니다.

  1. 기본 제약 조건 설정:
    뷰에 제약 조건을 추가하려면 makeConstraints 메서드를 사용하십시오.
view.snp.makeConstraints { (make) in
    make.width.equalTo(100)
    make.height.equalTo(50)
}
  1. 상대적인 제약 조건:
    다른 뷰나 상위 뷰에 대한 상대적인 제약 조건을 쉽게 설정할 수 있습니다.
view.snp.makeConstraints { (make) in
    make.top.equalTo(superview.snp.top).offset(20)
    make.left.equalTo(superview.snp.left).offset(15)
}
  1. 연산자 사용:
    SnapKit은 연산자를 활용하여 제약 조건을 더욱 명확하게 만들 수 있습니다.
view.snp.makeConstraints { (make) in
    make.width.equalToSuperview().multipliedBy(0.5).offset(-10)
    make.height.lessThanOrEqualTo(200)
    make.height.greaterThanOrEqualTo(100)
}
  1. 중심, 크기 및 가장자리:
    SnapKit을 사용하여 뷰의 중심, 크기, 가장자리에 대한 제약 조건을 쉽게 설정할 수 있습니다.
view.snp.makeConstraints { (make) in
    make.center.equalTo(superview)
    make.size.equalTo(CGSize(width: 100, height: 50))
    make.edges.equalTo(superview).inset(20)
}
  1. 배열 및 마진 제약 조건:
    배열을 사용하여 여러 뷰에 대한 제약 조건을 쉽게 설정하거나 마진을 사용하여 제약 조건을 설정할 수 있습니다.
let views = [view1, view2, view3]

views.snp.makeConstraints { (make) in
    make.height.equalTo(50)
}

view1.snp.makeConstraints { (make) in
    make.leadingMargin.equalTo(15)
    make.trailingMargin.equalTo(-15)
}
  1. 우선 순위:
    제약 조건에 우선 순위를 부여할 수 있습니다. 우선 순위는 priority 메서드를 사용하여 설정됩니다.
view.snp.makeConstraints { (make) in
    make.left.equalTo(superview).priority(.high)
    make.right.equalTo(superview).offset(-20).priority(.low)
}

 

 

스냅킷 쓰다가 평소에 헷갈렸던 것 기록해두기-!! ✏️

 

 

[1] translatesAutoresizingMaskIntoConstraints = false 안해도 되는지 

 

스냅킷을 안쓰면 코드로 constraints를 잡을때,

translatesAutoresizingMaskIntoConstraints = false를 명시적으로 해줘야하잖아요..!! 

 

https://www.raywenderlich.com/3225401-snapkit-for-ios-constraints-in-a-snap

 

스냅킷은 translatesAutoresizingMaskIntoConstraints = false 를 내부에서 알아서 해줍니다. 

스냅킷의 LayoutConstraintItem 파일에 가보시면 있습니다.

 

 

그래서 스냅킷 쓸때는 translatesAutoresizingMaskIntoConstraints = false 안해줘도 됩니다. 

 

[2] offset과 inset의 차이

 

파란색뷰를 superview(흰색뷰)에서 top, left, right, bottom 50씩 spacing 주려면 각각 어떻게 해야할까요?

 

 

1) offset을 썼을때 

 

 box.snp.makeConstraints { maker -> Void in
      maker.top.equalToSuperview().offset(50)
      maker.left.equalToSuperview().offset(50)
      maker.right.equalToSuperview().offset(-50)
      maker.bottom.equalToSuperview().offset(-50)
  }

 

 

"현재 뷰 constraint = 슈퍼뷰 constraint + offset 값"

 

offset은 위의 공식이라고 생각하면 됩니다. 

 

위의 수치들도 아래 공식으로 적용되어졌다고 볼 수 있어요

 

top = 슈퍼뷰의 top + 50

left = 슈퍼뷰의 left + 50

right = 슈퍼뷰의 right - 50

bottom = 슈퍼뷰의 bottom - 50

 

 

 

2) inset을 썼을때 

 

box.snp.remakeConstraints { maker -> Void in
    maker.top.left.bottom.right.equalToSuperview().inset(50)
}

 

insets은 UIEdgeInsets을 해줬다고 생각하면 됩니다. 

저 코드는 실제 아래 코드와 똑같거든요..!

box.snp.makeConstraints { maker -> Void in
    maker.top.left.bottom.right.equalToSuperview().inset(UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50))
}

 

하지만 저 코드는 별로 안좋은 코드에요

왜냐면 이런식으로 make와 UIEdgeInsets의 top, left,right, bottom의 순서를 다르게 쓰면 헷갈릴 수 있으니까..?!

(그래도 UIEdgeInsets의 top, left, bottom, right 순서로 먹여집니다.)

  box.snp.makeConstraints { maker -> Void in
      maker.top.right.bottom.left.equalToSuperview().inset(UIEdgeInsets(top: 10, left: 10, bottom: 50, right: 50))
  }

 

 

그래서 저렇게 쓰고 싶으면 이렇게 사용하는 게 안헷갈리겠죠?!

  box.snp.makeConstraints { maker -> Void in
      maker.edges.equalTo(UIEdgeInsets(top: 10, left: 10, bottom: 50, right: 50))
  }

 

우리의 스펙처럼 똑같은 50의 spacing값이라면 이렇게 해주는게 제일 깔끔하겠네요

  box.snp.makeConstraints { (make) -> Void in
      make.edges.equalToSuperview().inset(50)
  }

 

 

[3] snp.left와 snp.leading의 차이 / snp.right와 snp.trailing의 차이

 

우선 아래 표처럼 스냅킷의 ViewAttribute는 NSLayoutAttribute와 매칭됩니다.

 

http://snapkit.io/docs/

그럼 NSLayoutAttribute의 left와 leading, right와 trailing이 왜 각각 존재하는지 알아봐야겠죠?!

 

leading, trailing으로 설정하면 right-to-left 순서로 읽는 지역에서 화면이 거꾸로(flip되어서) 표시된다고 합니다. 

하지만 left, right로 설정하면 안그럽니다.

 

https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html

 

 

(왼쪽, 오른쪽은 모든 지역에서 항상 똑같은 위치이지만(??) leading, trailing은 각 지역마다 다르게 받아들인다!!

그래서 leading, trailing으로 하면 오른쪽으로 왼쪽으로 읽는 지역에서 flip된 UI가 나온다!! 라고 생각하면 될 것 같아요)

 

 

 

[4] Constraint를 reference로 들고 있을 수 있는가

 

스냅킷을 안쓰면 이런식으로 reference 들고 있을 수 있잖아요

그리고 topSpace.constant = 100 해서 constant를 업데이트 해주고!

 

 

스냅킷도 가능하다고 합니다.

 

makeConstraints할때 프로퍼티에 assign해주면 됩니다. 

그리고 updateOffset을 사용하면 됩니다. 

 

http://snapkit.io/docs/

 

 

근데 updateConstraints 하는게 더 스냅킷스럽고 좋아보여요-!

  box.snp.makeConstraints { maker in
      maker.top.bottom.left.right.equalToSuperview()
  }

  box.snp.updateConstraints { maker in
      maker.top.equalToSuperview().offset(100)
  }