코드를 구현하다 보면, 동일하게 반복되는 코드가 있습니다.
오늘은 이런 코드를 어떤 식으로 구현하면 좋을지에 대해 배웠습니다.
이전까지는 버튼을 예로 들면, 버튼의 외형은 동일하나, 그 안에 들어가는 텍스트의 크기나 굵기가 다를 경우가 있었어도, 이에 대해 대체할 방법에 잘 알지 못했습니다.
오늘은 몇 가지에 대해 알아보려고 합니다.
AuthHeaderView
import UIKit
class AuthHeaderView: UIView {
// MARK: - UI Components
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = UIImage(named: "logonew")
imageView.layer.cornerRadius = 45
imageView.clipsToBounds = true
return imageView
}()
private let titleLabel: UILabel = {
let label = UILabel()
label.textColor = .label
label.textAlignment = .center
label.font = .systemFont(ofSize: 26, weight: .bold)
label.text = "ERROR"
return label
}()
private let subTitleLabel: UILabel = {
let label = UILabel()
label.textColor = .label
label.textAlignment = .center
label.font = .systemFont(ofSize: 16, weight: .regular)
label.text = "ERROR"
return label
}()
// MARK: - Life Cycle
init(title: String, subTitle: String) {
super.init(frame: .zero)
self.titleLabel.text = title
self.subTitleLabel.text = subTitle
configureConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Constraints
private func configureConstraints() {
self.addSubview(imageView)
self.addSubview(titleLabel)
self.addSubview(subTitleLabel)
imageView.translatesAutoresizingMaskIntoConstraints = false
titleLabel.translatesAutoresizingMaskIntoConstraints = false
subTitleLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.imageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 30),
self.imageView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
self.imageView.widthAnchor.constraint(equalToConstant: 90),
self.imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
self.titleLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 19),
self.titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor),
self.titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor),
self.subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 12),
self.subTitleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor),
self.subTitleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor)
])
}
}
위의 코드는 iOS 앱 개발을 위한 UIKit 프레임워크를 사용하여 AuthHeaderView라는 커스텀 뷰를 구현한 코드입니다. 이 뷰는 사용자 인증 화면에 적합한 헤더를 제공하며 이미지, 제목, 및 부제목을 포함하고 있습니다.
주요 구성 요소 설명
1. 클래스 구조
- AuthHeaderView는 UIView를 상속받아 커스텀 뷰로 제작되었습니다.
- 이 뷰는 크게 3가지 UI 컴포넌트(UIImageView, UILabel, UILabel)로 구성되어 있습니다.
2. UI Components
- imageView:
- 타입: UIImageView
- 역할: 헤더에서 로고나 이미지를 표시합니다.
- 설정:
- contentMode: 이미지를 비율에 맞게 축소/확대하여 맞춥니다(.scaleAspectFit).
- layer.cornerRadius: 둥근 모서리를 위해 반지름 값을 45로 설정했습니다.
- clipsToBounds: 코너의 반경 설정이 적용되도록 클리핑합니다.
- titleLabel:
- 타입: UILabel
- 역할: 헤더의 주요 제목을 표시합니다.
- 설정:
- 색상: UIColor.label (다크모드/라이트모드 호환 가능)
- 폰트: 굵고 큰 텍스트 (.systemFont(ofSize: 26, weight: .bold)).
- subTitleLabel:
- 타입: UILabel
- 역할: 제목 아래 부제목을 표시합니다.
- 설정:
- 폰트: 상대적으로 작은 크기의 일반 텍스트 (.systemFont(ofSize: 16, weight: .regular)).
3. 생성자
- init(title: String, subTitle: String):
- 초기화 시 제목(title)과 부제목(subTitle) 텍스트를 설정합니다.
- super.init(frame: .zero)를 호출하여 부모 클래스 초기화.
- required init?(coder: NSCoder):
- 인터페이스 빌더에서 사용할 경우 미리 구현되도록 fatalError 처리. 이 뷰는 코드로만 사용하도록 설계된 것 같습니다.
4. 레이아웃 설정
configureConstraints() 메서드는 Auto Layout을 사용하여 뷰 내부 컴포넌트들의 위치와 크기를 설정합니다.
- imageView:
- 상단 여백: self.topAnchor로부터 30pt 간격.
- 수평 중앙: self.centerXAnchor와 정렬.
- 너비: 90pt, 높이는 너비와 같음(정사각형).
- titleLabel:
- imageView 아래: imageView.bottomAnchor로부터 19pt 간격.
- 양쪽 여백: self.leadingAnchor, self.trailingAnchor와 같음.
- subTitleLabel:
- titleLabel 아래: titleLabel.bottomAnchor로부터 12pt 간격.
- 양쪽 여백: self.leadingAnchor, self.trailingAnchor와 같음.
코드 요약
AuthHeaderView는 다음과 같은 구조의 헤더를 만드는 데 사용됩니다:
- 상단에 둥근 이미지를 표시
- 중간에 큰 제목(titleLabel) 텍스트 표시
- 아래에 작은 부제목(subTitleLabel) 텍스트 표시
- 레이아웃은 Auto Layout을 통해 모든 디바이스에서 적절히 동작하도록 설계됨.
활용 방법
여기서는 LoginController에서 사용되었습니다.
class LoginController: UIViewController {
// MARK: - UI Components
private let headerView = AuthHeaderView(title: "Sign In", subTitle: "Sign in to your account")
...
CustomTextField
import UIKit
class CustomTextField: UITextField {
// MARK: - Enum
enum CustomTextFieldType {
case username
case email
case password
}
private let authFieldType: CustomTextFieldType
init(fieldType: CustomTextFieldType) {
self.authFieldType = fieldType
super.init(frame: .zero)
self.backgroundColor = .secondarySystemBackground
self.layer.cornerRadius = 10
self.returnKeyType = .done
self.autocorrectionType = .no
self.autocapitalizationType = .none
self.leftViewMode = .always
self.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: self.frame.size.height))
switch fieldType {
case .username:
self.placeholder = "Username"
case .email:
self.placeholder = "Email"
self.keyboardType = .emailAddress
self.textContentType = .emailAddress
case .password:
self.placeholder = "Password"
self.textContentType = .oneTimeCode
self.isSecureTextEntry = true
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
위 코드는 UIKit을 활용하여 CustomTextField라는 커스텀 텍스트 필드를 구현한 코드입니다. 이 텍스트 필드는 사용자 인증과 관련된 필드(username, email, password)를 간편하게 생성하고 관리할 수 있도록 설계되었습니다.
주요 구성 요소 설명
1. 클래스 구조
- CustomTextField는 UITextField를 상속받아 사용자 정의 기능을 추가한 커스텀 텍스트 필드입니다.
- 필드의 종류에 따라 동작과 스타일이 다르게 설정됩니다.
2. 열거형 (Enum)
enum CustomTextFieldType {
case username
case email
case password
}
- 목적: 텍스트 필드의 종류를 정의합니다.
- 세 가지 타입이 있습니다:
- .username: 사용자 이름 입력용.
- .email: 이메일 주소 입력용.
- .password: 비밀번호 입력용.
3. 프로퍼티
- authFieldType (Private):
- 타입: CustomTextFieldType
- 텍스트 필드의 타입을 저장합니다.
- init 메서드에서 초기화되며, 타입에 따라 필드의 특성이 달라집니다.
4. 생성자
init(fieldType: CustomTextFieldType)
- 텍스트 필드의 타입(fieldType)을 지정받아 초기화합니다.
- 설정 내용:
- 공통 설정:
- backgroundColor: .secondarySystemBackground로 설정하여 배경색을 라이트/다크 모드에 맞게 조정.
- layer.cornerRadius: 모서리를 둥글게 설정 (반지름: 10).
- 키보드/자동완성 관련 설정:
- returnKeyType: .done로 설정하여 키보드에 "완료" 버튼 표시.
- autocorrectionType: .no로 설정하여 자동 수정 비활성화.
- autocapitalizationType: .none로 설정하여 첫 글자 자동 대문자 비활성화.
- 왼쪽 여백 추가:
- leftViewMode: .always로 설정하여 항상 왼쪽 여백을 유지.
- leftView: 너비 12pt의 UIView로 여백 공간 추가.
- 타입별 설정:
- .username:
- 플레이스홀더: "Username".
- .email:
- 플레이스홀더: "Email".
- 키보드 타입: keyboardType = .emailAddress로 이메일 입력에 적합한 키보드 사용.
- 텍스트 타입: textContentType = .emailAddress로 자동완성을 지원.
- .password:
- 플레이스홀더: "Password".
- 텍스트 타입: textContentType = .oneTimeCode로 비밀번호 자동 입력 지원.
- 보안 입력: isSecureTextEntry = true로 비밀번호를 가려서 표시.
- .username:
- 공통 설정:
5. 필수 생성자
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
- 인터페이스 빌더 사용을 방지합니다. 이 뷰는 코드로만 사용 가능하도록 설계되었습니다.
코드 요약
CustomTextField는 사용자 인증 UI에서 자주 사용되는 입력 필드들을 효과적으로 관리할 수 있도록 설계된 커스텀 텍스트 필드입니다.
활용 방법
let usernameField = CustomTextField(fieldType: .username)
let emailField = CustomTextField(fieldType: .email)
let passwordField = CustomTextField(fieldType: .password)
// 예시: 부모 뷰에 추가
view.addSubview(usernameField)
view.addSubview(emailField)
view.addSubview(passwordField)
// Auto Layout 설정 예시
usernameField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
usernameField.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
usernameField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
usernameField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
usernameField.heightAnchor.constraint(equalToConstant: 50)
])
장점
- 재사용성: 필드 타입에 따라 설정이 자동으로 적용되어 코드를 간결하게 유지.
- 유지보수성: 텍스트 필드 관련 설정을 한 곳에서 관리 가능.
- 가독성: 필드 타입을 명확히 구분해 코드 읽기가 쉽습니다.
CustomButton
import UIKit
class CustomButton: UIButton {
// MARK: Enum
enum FontSize {
case big
case med
case small
}
// MARK: - Life Cycle
init(title: String, hasBackground: Bool = false, fontSize: FontSize) {
super.init(frame: .zero)
self.setTitle(title, for: .normal)
self.layer.cornerRadius = 12
self.layer.masksToBounds = true
self.backgroundColor = hasBackground ? .systemBlue : .clear
let titleColor: UIColor = hasBackground ? .white : .systemBlue
self.setTitleColor(titleColor, for: .normal)
switch fontSize {
case .big:
self.titleLabel?.font = .systemFont(ofSize: 22, weight: .bold)
case .med:
self.titleLabel?.font = .systemFont(ofSize: 18, weight: .semibold)
case .small:
self.titleLabel?.font = .systemFont(ofSize: 16, weight: .regular)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
위 코드는 UIKit을 사용하여 CustomButton이라는 커스텀 버튼을 구현한 코드입니다. 이 버튼은 제목, 배경 색상, 그리고 폰트 크기를 쉽게 설정할 수 있도록 설계되었습니다.
주요 구성 요소 설명
1. 클래스 구조
- CustomButton은 UIButton을 상속받아 특정한 설정을 간단히 적용할 수 있는 커스텀 버튼입니다.
2. 열거형 (Enum)
enum FontSize {
case big
case med
case small
}
- 목적: 버튼 텍스트의 폰트 크기를 관리합니다.
- 세 가지 옵션:
- .big: 큰 폰트 (22pt, 굵은 글씨).
- .med: 중간 폰트 (18pt, 반굵은 글씨).
- .small: 작은 폰트 (16pt, 기본 굵기).
3. 생성자
init(title: String, hasBackground: Bool = false, fontSize: FontSize)
- 버튼의 제목, 배경 색상 유무, 폰트 크기를 설정합니다.
- 매개변수:
- title: 버튼에 표시될 텍스트.
- hasBackground: 버튼의 배경 색상을 설정 (true이면 배경색이 파란색, false이면 투명).
- fontSize: 텍스트의 폰트 크기(FontSize 열거형 사용).
4. 설정 내용
- 공통 설정:
- setTitle: 버튼 텍스트를 설정.
- layer.cornerRadius: 버튼의 모서리를 둥글게 설정 (반지름: 12).
- layer.masksToBounds: 뷰의 경계를 넘는 하위 콘텐츠를 잘라냄.
- 배경 색상:
- hasBackground가 true일 경우:
- 배경색: systemBlue (시스템 파란색).
- 텍스트 색상: 흰색.
- hasBackground가 false일 경우:
- 배경색: 투명 (.clear).
- 텍스트 색상: 파란색 (systemBlue).
- hasBackground가 true일 경우:
- 폰트 크기:
- fontSize의 값에 따라 버튼 텍스트의 크기와 굵기가 설정됩니다.
- .big: 22pt, 굵은 폰트 (.bold).
- .med: 18pt, 반굵은 폰트 (.semibold).
- .small: 16pt, 기본 굵기 (.regular).
- fontSize의 값에 따라 버튼 텍스트의 크기와 굵기가 설정됩니다.
5. 필수 생성자
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
- 인터페이스 빌더 사용을 방지합니다. 이 버튼은 코드로만 사용 가능합니다.
코드 요약
CustomButton은 버튼의 디자인 및 동작을 단순화하고, 다음과 같은 기능을 제공합니다:
- 버튼 텍스트와 배경 설정을 간편화.
- 시스템 스타일과 다크 모드에 적합한 색상 사용.
- 다양한 폰트 크기 제공.
버튼 생성
let loginButton = CustomButton(title: "Login", hasBackground: true, fontSize: .big)
let cancelButton = CustomButton(title: "Cancel", hasBackground: false, fontSize: .small)
버튼 추가 및 레이아웃 설정
view.addSubview(loginButton)
view.addSubview(cancelButton)
loginButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
loginButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
loginButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
loginButton.widthAnchor.constraint(equalToConstant: 200),
loginButton.heightAnchor.constraint(equalToConstant: 50)
])
cancelButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
cancelButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
cancelButton.topAnchor.constraint(equalTo: loginButton.bottomAnchor, constant: 20),
cancelButton.widthAnchor.constraint(equalToConstant: 100),
cancelButton.heightAnchor.constraint(equalToConstant: 40)
])
장점
- 재사용성:
- 텍스트, 배경, 폰트 크기를 간단히 설정할 수 있어 여러 화면에서 재사용 가능.
- 유지보수성:
- 버튼 스타일을 통합 관리할 수 있어 유지보수가 용이.
- 모던 디자인:
- 시스템 색상(systemBlue)과 다크 모드 호환으로 최신 UI 트렌드를 따름.
확장 가능성
- 버튼의 다른 속성(예: 테두리 색상, 텍스트 스타일 등)을 추가하면 다양한 스타일로 확장 가능합니다.
'Project > FirebaseTest' 카테고리의 다른 글
FireBase - 로그인과 로그아웃 처리하는 메서드 정의 (1) | 2024.12.03 |
---|---|
FireBase - 사용자 등록 기능 (0) | 2024.12.03 |
FireBase - Alert (0) | 2024.12.03 |
FireBase - UITextView with open WKWebView (0) | 2024.12.03 |
FireBase - Webkit (1) | 2024.12.03 |