나를 위한 Swift 코드 스타일에 대해 정리를 해봅시다.
지금 정리하는 내용 외에도 많은 내용이 있지만 우선적으로 중요하다 생각이 드는 내용들을 정리를 해보려 합니다.
네이밍
- 사용하는 곳에 무엇을 위한 기능인지 명확하게 이해하게끔 이름을 만듭니다.
- 간결하고 명료하게 할 수 있으면 좋겠지만 그렇지 않은 경우도 많기에 가능한 한 명료하게 이름을 만듭니다.
- 동적인 변수나 함수의 네이밍은 -ed, -ing 를 붙이면 좋습니다.
- UpperCamelCase
- 단어의 첫 글자를 모두 대문자로 정의하는 방법
- Class(객체), Structure(구조체), 열거형(Enumeration), 익스텐션(Extension), 프로토콜(Protocol) 등의 이름을 정의할 때 사용
- ex) MainController, User, AccountType, UserIndex 등
- lowerCamelCase
- 단어의 첫 글자를 제외한 단어의 첫 글자는 모두 CamelCase와 동일하게 대문자로 정의하는 방법
- 변수(Variable), 상수(Constant), 함수(Function), 프로퍼티(Property), 파라미터(Parameter) 등의 이름을 정의할 때 사용
- ex) user, userIndex, accountType, searchResults 등
- 약어
- 단어가 약어로 시작하는 경우 소문자로 표기하고 그 외에는 모두 대문자로 표기합니다.
올바른 예
let valueID: Int?
let html: String?
let weatherURL: URL?
let urlString: String?
부적절한 예
let valueId: Int?
let HTML: String?
let weatherUrl: URL?
let URLString: String?
Delegate
- 델리게이트는 프로토콜 명으로 네임스페이스를 구분합니다.
- 네임스페이스란 소스 코드에 불필요한 명칭 규칙을 사용하지 않아도 이름 충돌이 발생하지 않고 쉽게 설명할 수 있도록 제정된 개념이고 쉽게 설명해서 관련있는 기능들끼리 모아놓은 공간이라는 개념입니다.
올바른 예
protocol AuthentificationDelegate {
func authentificationView()
func authentificationComplete()
}
부적절한 예
protocol AuthentificationDelegate {
func setUserName()
func setUserProfile()
func AuthentificationView() // AuthentificationView라는 뷰가 존재할 경우에는 에러가 발생합니다.
}
클로저
- 리턴타입이 없는 클로저를 정의할 때는 (() -> Void) 방식으로 사용합니다.
올바른 예
func doSomething(completion: () -> Void) {
// do something
}
부적절한 예
func doSomething(completion: ()->Void) {
// do something
}
주석
-
// 를 사용해서 한줄 문서화 주석을 남깁니다.
// 이름을 가져올 함수
func getName(name: String) {
// 이름을 보여줄 라벨
let nameLabel = UILabel()
}
- /// 를 사용해서 한줄 문서화 주석을 남깁니다.
/// 이름을 가져올 함수
func getName(name: String) {
/// 이름을 보여줄 라벨
let nameLabel = UILabel()
}
- // MARK: - 를 사용해서 연관되는 코드들을 그룹화하고 구분짓습니다.
// MARK: - Properties
private let label = UILabel()
private let confirmButton = UIButton()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
import
- 모듈 임포트는 최상단에 작성하며 알파벳을 기준으로 나열합니다.
- 내장 라이브러리를 먼저 임포트하고 서드파티 라이브러리들을 임포트합니다.
- UIKit을 임포트 해야한다면 Foundation은 지워주도록 합니다.
import UIKit
import SnapKit
import SwiftyBeaver
import Then
줄바꿈
- 코드 안에서는 불필요한 줄바꿈은 하지 않습니다.
- 코드가 없는 빈 줄은 아무것도 없는 공백 상태를 유지합니다.(필수인지는 잘 모르겠음. 나중에 커밋했을 때 빈 줄마다 변경사항이 뜨면 보기가 불편함.)
- 코드가 끝나는 모든 파일의 마지막 줄은 항상 공백 상태를 유지합니다.
- // MARK: - 에는 위, 아래로 공백 상태를 유지합니다.
- 함수 내부 코드는 들여쓰기를 합니다.
func doSomething(completion: ()->Void) {
// do something
}
기타 사항
- 저는 미처 보지 못한 줄바꿈이나 들여쓰기는 Swimat이라는 프로그램을 사용합니다.
- 클래스에 프로토콜을 적용할 때는 extension을 활용하여 따로 작성합니다.
- 저는 위의 MARK 주석 뿐만 아니라 Helpers, Selectors, UITableViewDelegate, UITableViewDataSource 등 기능별로 나눈 주석 예약어를 사용합니다.
- 레이아웃이나 클로저를 통한 인스턴스 생성 시 SnapKit이나 Then을 주로 사용하여 코드의 가독성을 높입니다.
- 중복되는 코드는 리팩토링하여 여러곳에서 사용할 수 있도록 합니다.
private let previousButton: UIButton = {
let button = UIButton(type: .system)
button.tintColor = .systemBlue
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.layer.borderWidth = 2
button.layer.borderColor = UIColor.black.cgColor
button.layer.cornerRadius = 25
return button
}()
이러한 버튼이 여러개가 있을 때 아래 방식으로 커스텀 버튼을 만들어 여러 곳에서 재사용 가능하게 리팩토링합니다.
타이틀이나 이미지를 기본값을 설정하여 선택적으로 사용 가능합니다.
class ActionButton: UIButton {
init(title: String? = nil, image: UIImage? = nil) {
super.init(frame: .zero)
setTitle(title, for: .normal)
setImage(image, for: .normal)
setTitleColor(.white, for: .normal)
titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
layer.borderWidth = 2
layer.borderColor = UIColor.white.cgColor
layer.cornerRadius = 25
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
이후 아래 방식으로 재사용 가능합니다.
private let previousButton = ActionButton(title: "이전")
private let nextButton = ActionButton(title: "다음")
'Swift' 카테고리의 다른 글
[Swift] 키보드 뷰에 가려지는 버튼 움직이기 (0) | 2022.04.19 |
---|---|
FirebaseAuth 기능 구현 (0) | 2022.04.03 |
IOS) 간단한 토이프로젝트를 만들어 보다 (0) | 2021.08.09 |
[Swift} Optional 기본 개념 (0) | 2021.07.13 |
테이블 뷰 구현 이론 (0) | 2021.07.13 |