Swift

Swift - UIKit, SnapKit 비교

iosos 2023. 7. 23. 15:50

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' : 버튼의 이벤트 지정 

 

 

화면 기록 2023-07-22 오후 6.50.53.mov
1.37MB

 

 

 


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 

 

[iOS] SnapKit 시작하기 

SnapKit 이란? Code base로 iOS 개발을 할 때 오토레이아웃을 쉽고 간결한 코드로 작성할 수 있도록 하는 라이브러리다.

velog.io

 

https://www.youtube.com/watch?v=2Gp01Zqy2oA