목차
티스토리 뷰
안녕하세요 🐾
개발을 진행하다보면 요구에 의해 다양한 커스텀 뷰를 만들어야 합니다.
코드를 이용해 Custom View를 만드는 방식을 공유합니다 :-)
이와 더불어 커스텀 뷰 생산성에 도움을 줄 [Code Snippet(코드 스니펫), 코드 즐겨찾기]도 참고하시는 것을 추천합니다.
1. 커스텀 뷰 템플릿 생성
템플릿을 만들어두면 커스텀 뷰 생성 후, 템플릿 코드를 붙여 넣은 뒤 일부 코드만 수정 구현하는 것이 편리하여 개인적으로 사용하는 방법입니다. 템플릿은 아래와 같이 작성하였습니다.
import UIKit
class UIViewTemplate: UIView {
// MARK: - Properties
// MARK: - UI Properties
// MARK: - Initialize
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Functions
private func setupUI() {
self.backgroundColor = .white
}
}
템플릿 코드를 보시면 먼저 주석의 코드영역을 표시하는 마킹 기능을 활용하였습니다.
클래스 탭 상단의 마지막 경로 부분을 눌러보면 아래와 같이 마킹한 구역이 나누어 표시되고 선택하면 선택된 영역으로 하이퍼링크가 가능해 집니다.
코드에 보이는 required init 생성자가 보이시나요?
UIView를 상속받아 지정 생성자를 사용할 경우 required init?
을 필수로 작성해야 합니다.
왜 그럴까요? 바로 NSCoding 때문입니다.
UIView를 살펴보면 아래와 같이 NSCoding이란 프로토콜을 채택하고 있는걸 확인 할 수 있습니다.
UI가 코드로만 생성되는 것이 아니라 스토리보드나 xib로 만들어질 때에는 NSCoding에 속한 init(coder: NSCoder)
을 통해 객체가 생성됩니다.
지정 생성자 선언 후 init(coder: NSCoder)
생성자에 대한 코드를 자동 완성하면, fatalError로 코드가 채워지는 것을 확인 할 수 있습니다.
이는 '지정 생성자를 통해 뷰를 만들었으니 스토리보드나 xib로 만드는 것은 안된다' 는 일종의 경고로 보시면 됩니다 :)
2. 커스텀 뷰 생성
하나의 이미지뷰와 라벨을 가진 커스텀 뷰를 생성하도록 하겠습니다.
레이아웃 배치시 오토레이아웃 코드에 대한 생산성을 위해 Snapkit을 같이 사용했습니다.
import UIKit
import SnapKit
class AssumView: UIView {
// MARK: - Properties
// MARK: - UI Properties
let nameLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 16, weight: .semibold)
label.textAlignment = .center
label.textColor = .darkGray
label.text = "Assum"
return label
}()
let iconImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.image = UIImage(named: "icon")
return imageView
}()
// MARK: - Initialize
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Functions
private func setupUI() {
self.backgroundColor = .lightGray.withAlphaComponent(0.3)
// iconImageView
addSubview(iconImageView)
iconImageView.snp.makeConstraints {
$0.top.equalToSuperview()
$0.centerX.equalToSuperview()
$0.width.height.equalTo(48)
}
// nameLabel
addSubview(nameLabel)
nameLabel.snp.makeConstraints {
$0.top.equalTo(iconImageView.snp.bottom).offset(12)
$0.left.right.bottom.equalToSuperview()
$0.width.equalTo(60)
$0.height.equalTo(20)
}
}
}
3. 커스텀 뷰 생성(기존 컴포넌트 상속)
UILabel, UIButton처럼 기존 컴포넌트의 기능은 일부 이용하면서 UI만을 살짝 커스텀하고 싶을때에는
아래와 같이 해당 컴포넌트만을 상속받은 뒤 필요한 속성을 오버라이드하여 재정의하는 것도 좋은 방법입니다.
class AssumButton: UIButton {
// MARK: - Enumeration
enum buttonStyle: Int {
case primary = 0
case danger
}
// MARK: - Properties
var style: buttonStyle = .primary {
didSet {
self.setupUI()
}
}
override var isEnabled: Bool {
didSet {
self.setupUI()
}
}
override var isHighlighted: Bool {
didSet {
self.setupUI()
}
}
// MARK: - Initialize
required init(style: buttonStyle) {
super.init(frame: CGRect.zero)
self.style = style
self.setupUI()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
fatalError("init(coder:) has not been implemented")
}
// MARK: - Functions
func setupUI() {
// Common setup
layer.masksToBounds = true
layer.cornerRadius = 6
titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
// Indivisual setup
switch self.style {
case .primary:
setTitleColor(.white, for: .normal)
setTitleColor(.white, for: .disabled)
setTitleColor(.white, for: .highlighted)
case .danger:
setTitleColor(.red, for: .normal)
setTitleColor(.red, for: .disabled)
setTitleColor(.red, for: .highlighted)
}
self.layoutIfNeeded()
}
}
4. 커스텀 뷰 사용
뷰컨트롤러에서 위에 구현했던 커스텀 뷰들을 추가하고 배치합니다.
class ViewController: UIViewController {
// MARK: - Properties
// MARK: - UI Properties
let assumView = AssumView()
let assumButton = AssumButton(style: .primary)
// MARK: - Initialize
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupUI()
}
// MARK: - Functions
func setupUI() {
view.backgroundColor = .white
// assumView
view.addSubview(assumView)
assumView.snp.makeConstraints {
$0.center.equalToSuperview()
$0.width.height.greaterThanOrEqualTo(0)
}
// assumButton
view.addSubview(assumButton)
assumButton.snp.makeConstraints {
$0.bottom.equalTo(view.safeAreaLayoutGuide)
$0.left.right.equalToSuperview().inset(16)
$0.height.equalTo(40)
}
}
}
실행하여 결과를 확인합니다.
'iOS > Swift' 카테고리의 다른 글
[iOS] Code Snippet(코드 스니펫), 코드 즐겨찾기 (0) | 2023.06.14 |
---|---|
[iOS] SwiftLint 적용하기 (0) | 2023.06.05 |
[iOS] Moya 적용하기 (0) | 2023.06.01 |
[iOS] 커스텀 프레임워크(라이브러리) 소스코드 숨기기 (0) | 2023.05.23 |
[iOS] 커스텀 프레임워크 생성 및 사용 (3) | 2023.05.22 |
- Total
- Today
- Yesterday
- swift google signin
- swift nimble
- XCFramework
- ios xcframework
- nimble
- iOS Quick
- iOS Framework
- Quick
- swift google login
- iOS 테스트 코드
- iOS Nimble
- ios google signin
- ios 구글 로그인 sdk
- swift reactorkit
- Firebase Distribution
- XCTest
- swift google sdk
- iOS 유닛테스트
- swift framework
- swift 구글 로그인
- iOS Unit Tes
- iOS 단위테스트
- Framework
- ios google
- ios mvvm
- ios reactorkit
- swift google login sdk
- swift 구글 sdk
- swift xctest
- swift quick
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |