SnapKit
- iOS 앱 개발에 사용되는 Auto Layout 라이브러리 중 하나로 Auto Layout을 코드로 쉽게 작성할 수 있도록 도와주는 도구
- 간결하고 직관적인 API를 제공하여 레이아웃 코드를 더 읽기 쉽고 유지보수하기 쉽게 만듦
- 인터페이스 빌더를 사용하지 않고도 레이아웃을 코드로 처리할 수 있으며, 코드로 작성된 레이아웃은 버전 관리에 용이하고 협업에 용이
SnapKit 설치 (CocoaPod 이용)
1. Podfile에 pod 'SnapKit' 입력
2. Pod Install
3. import SnapKit
import UIKit
import SnapKit
UI 미리 보기 기능 (PreView)
#if DEBUG
import SwiftUI
struct ViewControllerRepresentable: UIViewControllerRepresentable {
func updateUIViewController(_ uiView: UIViewController,context: Context) {
// leave this empty
}
@available(iOS 13.0.0, *)
func makeUIViewController(context: Context) -> UIViewController{
SnapKitViewController()
}
}
@available(iOS 13.0, *)
struct ViewControllerRepresentable_PreviewProvider: PreviewProvider {
static var previews: some View {
Group {
ViewControllerRepresentable()
.ignoresSafeArea()
.previewDisplayName("Preview")
.previewDevice(PreviewDevice(rawValue: "iPhone 11"))
}
}
} #endif
- SwiftUI로 작성된 코드로 iOS 앱에서 viewController를 Preview하는 방법
- 'opt' + 'cmd' + 'Enter' 입력하면 미리보기 기능
SnapKit 사용 전 코드
1. View 생성
// 빨간색 뷰
lazy var redView: UIView = { () -> UIView in
let view = UIView()
view.backgroundColor = .red
return view
}() // '()' 추가하여 viewDidLoad()에서 addSubview(redView()) 추가 시 () 사용 안 해도 됨
// 파란색 뷰
lazy var blueView: UIView = { () -> UIView in
let view = UIView()
view.backgroundColor = .blue
return view
}()
- 클로저를 사용하여 뷰를 초기화하고 반환
- 'lazy var' 를 사용하여 해당 프로퍼티가 접근되기 전까지 초기화하지 않고 처음 접근 시 한 번만 초기화
2. View 추가
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(redView)
self.view.addSubview(blueView)
}
- viewController의 View에 subView 추가
- 해당 뷰가 접근되므로 초기화 됨
3. autoLayout 지정 (위치, 크기)
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(redView)
self.view.addSubview(blueView)
// 오토레이아웃 지정할 때 false 설정 필수
redView.translatesAutoresizingMaskIntoConstraints = false
blueView.translatesAutoresizingMaskIntoConstraints = false
// redView의 크기 지정
redView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.7).isActive = true
redView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.7).isActive = true
// redView의 위치 지정
redView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
redView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
}
- ' translatesAutoresizingMaskIntoConstraints' 를 'false'로 설정하여 기본 Autoresizing Mask 기능을 비활성화해야 오토 레이아웃 지정 가능
- 'redView' 의 크기와 넓이를 self.view의 크기의 70%로 설정
- 'isActive = true' 로 설정해야만 설정됨
4. autoLayout 지정
redView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 40).isActive = true
redView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -40).isActive = true
redView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 40).isActive = true
redView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -40).isActive = true
- leadingAnchor, trailingAnchor, topAnchor, bottomAnchor를 사용하여 autoLayout 지정
- trailingAnchor, bottomAnchor는 constant를 마이너스 '-' 로 지정해야 함
5. NSLayoutConstraint.active()
NSLayoutConstraint.activate([
blueView.widthAnchor.constraint(equalToConstant: 100),
blueView.heightAnchor.constraint(equalToConstant: 100),
blueView.topAnchor.constraint(equalTo: self.redView.topAnchor, constant: 40),
blueView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
])
- NSLayoutConstraint.active()를 사용하여 배열에 포함된 오토레이아웃을 한 번에 활성화
- isActive = true를 사용하지 않아도 됨
6. 버튼 추가
// 버튼 추가
lazy var myButton = { (color : UIColor) -> UIButton in
let btn = UIButton(type: .system)
btn.backgroundColor = color
btn.setTitle("내 버튼 ", for: .normal)
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 40)
btn.layer.cornerRadius = 15
return btn
}
- UIColor 타입의 파라미터를 입력으로 받고 해당 색상으로 버튼의 배경색 지정
- "내 버튼" 이라는 타이틀 추가, 버튼 텍스트의 크기를 40으로 설정
- 버튼 모서리를 둥글게 처리하기 위해 cornerRadius를 15로 설정
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(redView)
self.view.addSubview(blueView)
let myGreenButton = myButton(.green)
self.view.addSubview(myGreenButton)
myGreenButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myGreenButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
myGreenButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
])
7. button Action 추가 (버튼 클릭 시 blueView의 constant 40씩 증가)
7-1) 변수 추가
// NSLayoutConstraint 타입은 Auto Layout의 제약 조건을 나타내는 클래스로 blueView - Top Anchor의 constant를 변경하기 위해 사용
var blueViewTopLayoutConstraint : NSLayoutConstraint? = nil
- 해당 변수는 제약 조건을 저장하는데 사용되며, 처음에는 값이 할당되지 않은 상태로 선언
7-2) @objc 함수 추가
var offset = 0
@objc fileprivate func moveBlueViewDown(){
offset += 40
print("ViewController : moveBlueViewDown(), offset : \(offset)")
blueViewTopLayoutConstraint?.constant = CGFloat(offset)
}
- 버튼을 누를 때마다 'offset' 값을 40씩 증가
- blueViewTopLayoutConstraint의 constant 값을 offset으로 설정하여 constant 값이 증가하도록 설정
- '@objc' : Objective-C에서 해당 메서드를 사용할 수 있도록 허용하기 위한 어노테이션
- 버튼의 액션으로 사용하기 위해 해당 메서드를 Objective-C에서 호출 가능한 형태로 만들기 위해 @objc 추가
7-3) blueView의 AutoLayout 구조 변경
blueViewTopLayoutConstraint = blueView.topAnchor.constraint(equalTo: self.redView.topAnchor, constant: 40)
// blueView - AutoLayout
NSLayoutConstraint.activate([
blueView.widthAnchor.constraint(equalToConstant: 100),
blueView.heightAnchor.constraint(equalToConstant: 100),
blueView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
])
blueViewTopLayoutConstraint?.isActive = true
- 'blueViewTopLayoutConstraint' 변수를 blueView의 topAnchor와 redView의 bottomAnchor 사이의 제약조건을 저장
- 이후 'isActive = true'로 활성화
7-4) 버튼에 타깃과 액션 추가
myGreenButton.addTarget(self, action: #selector(moveBlueViewDown), for: .touchUpInside)
- 'self' : myGreenButton의 타겟으로 'self' 지정, 사용될 객체를 의미
- 'action : #selector(moveBlueViewDown)' : 버튼이 터치(touchUpInside) 되었을 때 호출할 액션 지정
- 'for : .touchUpInside' : 버튼의 이벤트 지정
SnapKit 사용 후 코드
기존 코드
// 오토레이아웃 지정할 때 false 설정 필수
redView.translatesAutoresizingMaskIntoConstraints = false
redView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 40).isActive = true
redView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -40).isActive = true
redView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 40).isActive = true
redView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -40).isActive = true
SnapKit 코드
redView.snp.makeConstraints { make in
// make.edges.equalTo(self.view).inset(UIEdgeInsets(top: 40, left: 40, bottom: 40, right: 40))
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 40, left: 40, bottom: 40, right: 40))
}
- 'redView.snp.makeConstraints { make in ' : 클로저 내 제약 조건 정의
- 'make.edges.equalTo(self.view)' : redView의 네 변(edge)를 self.View와 동일하게 설정 -> redView가 뷰 컨트롤러에 꽉 차짐
- '.inset(UIEdgeInsets(top : , left : , bottom : , right : )' : redView와 뷰 컨트롤러의 뷰 사이의 간격을 인셋으로 지정 -> 패딩 설정
- 'equalToSuperview()' : SuperView와 동일하게 설정 == 'equalTo(self.view)'
기존 코드
// blueView - AutoLayout
NSLayoutConstraint.activate([
blueView.widthAnchor.constraint(equalToConstant: 100),
blueView.heightAnchor.constraint(equalToConstant: 100),
blueView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
blueView.topAnchor.constraint(equalTo: self.redView.topAnchor, constant: 40)
])
SnapKit 코드
blueView.snp.makeConstraints { make in
// 높이 넓이 : 100으로 지정
make.height.width.equalTo(100)
make.centerX.equalTo(self.view)
// blueView의 top을 redView의 top에 맞추면 offset을 40으로 두어 패딩 설정
make.top.equalTo(self.redView.snp.top).offset(40)
// blueView의 top을 viewController의 safeAreaLayoutGuide의 top에 맞춤
// make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top)
// blueView를 superView의 center에 맞춰서 정가운데에 놓음
// make.center.equalToSuperview()
// blueView의 넓이를 redView의 넓이와 맞춤
// make.width.equalTo(self.redView.snp.width)
// blueView의 넓이를 redView의 넓이의 1.1배로 맞춤
// make.width.equalTo(self.redView.snp.width).multipliedBy(1.1)
// blueView의 넓이를 redView의 넓이의 1/5배로 맞춤
// make.width.equalTo(self.redView.snp.width).dividedBy(5)
}
기존 코드
myGreenButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myGreenButton.widthAnchor.constraint(equalToConstant: 200),
myGreenButton.heightAnchor.constraint(equalToConstant: 100),
myGreenButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
myGreenButton.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor)
])
SnapKit 코드
myGreenButton.snp.makeConstraints { make in
make.width.equalTo(200)
make.height.equalTo(100)
make.centerX.equalToSuperview()
make.bottom.equalTo(self.view.safeAreaLayoutGuide.snp.bottom)
}
기존 코드
// NSLayoutConstraint 타입은 Auto Layout의 제약 조건을 나타내는 클래스로 blueView - Top Anchor의 constant를 변경하기 위해 사용
var blueViewTopLayoutConstraint : NSLayoutConstraint? = nil
blueViewTopLayoutConstraint = blueView.topAnchor.constraint(equalTo: self.redView.topAnchor, constant: 40)
// blueView - AutoLayout
NSLayoutConstraint.activate([
blueView.widthAnchor.constraint(equalToConstant: 100),
blueView.heightAnchor.constraint(equalToConstant: 100),
blueView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
])
blueViewTopLayoutConstraint?.isActive = true
var offset = 0
@objc fileprivate func moveBlueViewDown(){
offset += 40
print("ViewController : moveBlueViewDown(), offset : \(offset)")
blueViewTopLayoutConstraint?.constant = CGFloat(offset)
}
}
SnapKit 코드
// Top Anchor의 제약 조건을 나타내는 Constraint 타입의 옵셔널 변수
var blueViewTopConstraint : Constraint? = nil
blueView.snp.makeConstraints { make in
// 높이 넓이 : 100으로 지정
make.height.width.equalTo(100)
make.centerX.equalTo(self.view)
// blueView의 top을 redView의 top에 맞추면 offset을 40으로 두어 패딩 설정
// make.top.equalTo(self.redView.snp.top).offset(40)
// blueView의 TopAnchor 제약 조건을 설정하고 이를 blueViewTopConstraint 변수에 할당
self.blueViewTopConstraint = make.top.equalTo(self.redView.snp.top).offset(40).constraint
}
var offset = 0
@objc fileprivate func moveBlueViewDown(){
offset += 40
print("ViewController : moveBlueViewDown(), offset : \(offset)")
// blueView의 TopAnchor 제약 조건을 업데이터
self.blueViewTopConstraint?.update(offset: offset)
}
}
참고)
https://velog.io/@hyowon612/iOS-SnapKit-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0
https://www.youtube.com/watch?v=2Gp01Zqy2oA
'Swift' 카테고리의 다른 글
Swift - 프로토콜 (Protocol) (0) | 2023.08.06 |
---|---|
Swift 사진 설정하기 (UIImagePickerController 사용) (0) | 2023.08.05 |
Swift - PickerView (0) | 2023.07.19 |
Swift - 비동기 처리 (Completion Handler) (0) | 2023.07.15 |
Swift - 비동기처리(async / await) (0) | 2023.07.14 |