본문 바로가기

이상/iOS

[iOS] Easy to Auto Layout = SnapKit (ft.유의점)

반응형

 

iOS 화면을 개발할 때 SnapKit을 사용하면 정말 편하다

(혼자 공부하거나 토이 프로젝트를 할 때 무조건 사용하는 편이다)

 

SnapKit GitHub에도 첫 줄에서 이렇게 설명한다

SnapKit is a DSL to make Auto Layout easy on both iOS and OS X.

 

DSL은 Domain-Specific Language, 도메인 특화 언어라는 뜻이고

 

AutoLayout?

그럼 그냥 SnapKit 써~

이거 좋아, 아~주 좋아~

 

대충 이런 말이다

 

내가 느낀 SnapKit이 쓰이게 되는 레퍼토리는 이렇다

 

Storyboard로 화면 개발

> 프로젝트가 비대해지면서 화면 수도 많아지고 복잡해짐

> Storyboard도 무거워지면서 Storyboard 파일을 열기조차 싫어짐

> 하... Storyboard를 꼭 써야할까?

> Storyboard 없이 constraint를 소스로 추가해보자

> 하다보니 constraint 추가하는 소스도 너무 긴 것 같은데?

> SnapKit 사용

> AutoLayout 신세계 입성

 

실제 경험담은 아니고(일부는 맞고) 단순 뇌피셜이다

 

 

설치 방법은 GitHub - Installation에 나와있고

CocoaPods, Carthege, SPM으로 설치 가능하다

 

 

사용 방법

(Storyboard를 사용하지 않고) 정사각형의 UIView가 있고

safeAreaLayoutGuide 영역의 정가운데에 배치하려고 한다

SnapKit 미사용

view.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
containerView.heightAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
containerView.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor).isActive = true

 

SnapKit 사용

view.addSubview(containerView)
containerView.snp.makeConstraints { target in
    target.leading.trailing.equalToSuperview()
    target.height.equalTo(view.frame.width)
    target.centerY.equalTo(view.safeAreaLayoutGuide.snp.centerY)
}

 

또는

view.addSubview(containerView)
containerView.snp.makeConstraints {
    $0.leading.trailing.equalToSuperview()
    $0.height.equalTo(self.view.frame.width)
    $0.centerY.equalTo(self.view.safeAreaLayoutGuide.snp.centerY)
}

 

 

SnapKit을 사용하지 않을 경우엔

translatesAutoresizingMaskIntoConstraints = false를 해줘야하며

원하는 Anchor마다 각각 따로 관계를 지어줘야하고

isActive = true를 해줘야한다

 

반대로 말해 SnapKit을 사용하면

translatesAutoresizingMaskIntoConstraints = false를 해줄 필요가 없으며

원하는 Anchor를 묶음으로 한 번에 관계를 지어줄 수 있고

isActive = true를 해 줄 필요가 없다

개인적인 느낌일 수도 있지만 눈에 더 잘 들어온다

 

translatesAutoresizingMaskIntoConstraints의 경우 SnapKit 내부에서 지정해준다

 

 

필요에 따라 더 간단하게 사용할 수 있다

view.addSubview(containerView)
containerView.snp.makeConstraints {
    $0.top.equalTo(view.safeAreaLayoutGuide.snp.top)
    $0.leading.equalTo(view.safeAreaLayoutGuide.snp.leading)
    $0.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)
    $0.trailing.equalTo(view.safeAreaLayoutGuide.snp.trailing)
                줄이면
    $0.top.leading.bottom.trailing.equalTo(view.safeAreaLayoutGuide)
                한 번 더 줄이면
    $0.edges.equalTo(view.safeAreaLayoutGuide)
}

 

 

 

 

하지만 무조건적으로 사용하면 안 된다

(SnapKit에 대해 포스팅을 하게 된 이유!)

유의점

SnapKit 사용에 대한 유의점이라기보다는

AutoLayout에 대한 유의점일 수도 있는데

무지성으로 SnapKit을 사용하다보면

frame으로 지정해줘야할 때 constraint를 추가해서

내가 생각한대로 작동하지 않을 경우가 있다

 

UIPanGesture를 이용해서 UITextView를 움직이거나 텍스트를 수정할 수 있는 기능을 예시로 구현한다

(UIPanGesture 추가하는 부분은 생략)

view.addSubview(containerView)
containerView.snp.makeConstraints {
    $0.leading.trailing.equalToSuperview()
    $0.height.equalTo(view.frame.width)
    $0.centerY.equalTo(view.safeAreaLayoutGuide.snp.centerY)
}

let textView = UITextView()
    textView.deleagte 또는 textView.rx를 이용하여 PanGesture 구현
containerView.addSubview(textView)
textView.sizeToFit()
textView.snp.makeConstraints {
    $0.centerX.centerY.equalToSuperview()
}

 

위 예시처럼 화면에 추가한 textView의 center를 부모뷰의 center에 맞추는 constraint를 추가할 경우

textView의 텍스트를 수정하면서 textView의 frame에 변화가 생기고

추가했던 constraint에 의해 다시 화면 가운데로 이동하게 된다

 

 

 

 

때문에 이러한 경우 SnapKit을 사용하지 않고 (AutoLayout을 사용하지 않고)

직접 center를 맞춰준다

view.addSubview(containerView)
containerView.snp.makeConstraints {
    $0.leading.trailing.equalToSuperview()
    $0.height.equalTo(view.frame.width)
    $0.centerY.equalTo(view.safeAreaLayoutGuide.snp.centerY)
}

let textView = UITextView()
    textView.deleagte 또는 textView.rx를 이용하여 PanGesture 구현
containerView.addSubview(textView)
textView.sizeToFit()
textView.center = CGPoint(x: containerView.frame.size.width  / 2,
                          y: containerView.frame.size.height / 2)

 

 

 

 

 

요약

(후랑아) 아무리 유용하더라도 생각은 하면서 사용하자

 

반응형