본문 바로가기
iOS/Swift

[UIKit] CustomView

by Callie_ 2023. 11. 30.

 
 
 
 

새싹에서 후반기 프로젝트를 개발할 당시 CustomView를 많이 사용하게 되어서 정리하게 되었다.
주로 코드베이스로 UI를 그려왔기 때문에 해당 글에선 코드 베이스 + SnapKit 기반으로 customView를 만드는 방법을 다룰 예정이다.
 
 
 
 
 

출처: 내가 한 LSLP 프로젝트 중 회원가입-로그인 UI 캡쳐

 
 
 

커스텀 뷰를 왜 사용할까❓

 
우선 내가 CustomView를 사용했던 가장 큰 이유는 재사용성 때문이었다.
위 캡쳐 이미지처럼, 반복되는 UI 요소가 많은 화면을 그릴 때 매번 UI와 관련된 코드를 작성하면 굉장히 비효율적일 수 밖에 없다.
 
폰트를 바꿔야한다면?
포인트 컬러를 바꿔야한다면?
버튼의 코너 레디어스를 변경해야한다면?
 
동일한 구성의 코드를 일일이 찾아서 수정한다면, 반복되는 뷰의 수가 많을 수록 수정의 굴레에 빠질 수 밖에 없으니까.
 
또한, 부분적으로 다른 뷰에서도 같은 UI를 그려야할 때도 있기 때문에 이럴 때 해당 UI 코드를 재사용하려면 CustomView 사용이 적절했다.
 
 
 
 
 
 
 

✔︎ 커스텀 뷰를 활용하기

 
1. 버튼 재사용
 

import UIKit

class NextButton: UIButton {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setting()
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setting() {
        setTitleColor(.white, for: .normal)
        backgroundColor = ConstantColor.inActiveBrand
        layer.cornerRadius = 8
        titleLabel?.font = ConstantTypo.title2
        
    }
    
    
}

 
회원가입을 할 때, 다음 버튼을 만들 때 UI가 동일 했기 때문에 커스텀뷰로 관리했다.
 
init(frame: CGRect) 코드를 작성하면 자동으로 required init?(coder: NSCoder) 코드를 작성하도록 컴파일 시점에 안내가 뜬다.
 
두 가지를 간단히 정리하자면, 
 
init(frame:)은 코드로 뷰를 생성할 때의 생성자이고,
init(coder:)는 스토리보드 기반으로 뷰가 생성 될 때의 생성자이다.
 
나는 코드로 뷰를 그리고 있기 때문에, init(frame:)에만 내가 재사용하고 싶은 고정 UI 메서드를 호출했다.
 

let nextButton: UIButton = {
   let btn = NextButton()
   btn.setTitle("워크스페이스 생성", for: .normal)
   return btn
}()

 
커스텀으로 만든 버튼은 위 코드처럼 다른 클래스로 불러와 적용하면 된다.
 
 
 
2. 뷰 재사용
 
뷰 자체가 반복되는 UI가 많았던 SLP 뷰를 그리며 CustomView 사용을 확장해볼 수 있었다.
나는 UI 요소 하나하나를 CustomView로 만들어 관리를 해왔었는데, 이 프로젝트 이후 반복되는 view 자체를 custom으로 관리할 수 있게 되었다.
 
 

import UIKit
import SnapKit

final class ListView: UIView {
    
    let customButton = {
        let btn = UIButton()
        return btn
    }()
    
    let iconImageView = {
        let view = UIImageView()
        view.image = ConstantIcon.hashThin
        return view
    }()
    
    let titleLabel = {
        let label = UILabel()
        label.font = ConstantTypo.body
        label.textColor = UIColor.textSecondary
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        configureViews()
        setConstraints()

    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configureViews() {
        addSubview(iconImageView)
        addSubview(titleLabel)
        addSubview(customButton)

    }
    
    func setConstraints() {
        
        iconImageView.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(14)
            make.size.equalTo(18)
            make.centerY.equalToSuperview()
        }
        
        titleLabel.snp.makeConstraints { make in
            make.leading.equalTo(iconImageView.snp.trailing).offset(16)
            make.height.equalTo(28)
            make.width.equalTo(290)
            make.centerY.equalTo(iconImageView)
        }
        
        customButton.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        
    }
}

 
 
customView 내에서 기본 레이아웃을 잡아둘 수 있다.
찾아보니 frame을 사용해서 재사용하는 경우도 있는데, 일단 나는 snapKit 사용이 익숙해서 내가 하던 방식대로 작성했다.
 
 

let guideView = {
      let view = ListView()
      view.iconImageView.image = ConstantIcon.helpCustom
      view.titleLabel.text = "도움말"
      return view
}()

 

커스텀으로 만든 ListView도 위처럼 상속해서 필요에 따라 내부 UI를 수정해서 사용하면 된다.
 
 
 

✔︎ 마무리: 커스텀 뷰 사용의 장점

 
이렇게 반복되는 UI 코드를 클래스로 커스텀뷰를 만들어 사용하면 view에서의 코드가 확실히 줄어있는 걸 볼 수 있다.
 
 

'iOS > Swift' 카테고리의 다른 글

[SwiftUI] @State  (0) 2024.05.22
[SwiftUI] NavigationView, NavigationStack, navigationTitle  (2) 2024.04.15
[SwiftUI] Info.plist  (0) 2023.11.20
[SwiftUI] VStack vs LazyVStack  (5) 2023.11.06
[UIKit] Font 설정하기  (0) 2023.11.02