Skip to content

MaeumgaGym Swift Style Guide

박준하 edited this page Feb 6, 2024 · 6 revisions

💪🏿 Naming

1-1. Class

클래스 네이밍은 UpperCamelCase를 사용해주세요

final class MainView: UIView {
  // ...
}

1-2. 변수 및 상수

변수와 상수의 네이밍은 lowerCamelCase를 사용해주세요

let nameList: [String] = []

1-3. 함수

함수 네이밍에 대한 규칙이 명확하게 정의되어 있습니다. Action 함수의 이름도 명확하게 지정되어 있습니다.

func backButtonDidTap() {
  // ...
}

1-4. 열거형

Enum 네이밍과 각 case의 네이밍에 대한 규칙이 잘 지켜지고 있습니다.

enum Result {
  case success
  case failure
}

1-5. 프로토콜

프로토콜 네이밍 규칙이 잘 따라지고 있습니다.

protocol PickerDelegate {
  // ...
}

1-6. 기타 네이밍

함수 작성 순서와 각 함수의 역할이 명확하게 정의되어 있습니다.

🏛️ 코드 레이아웃

2-1. Protocol 사용 시

Extension을 사용하여 프로토콜을 분리하는 접근은 좋습니다.

extension MainViewController: UITableViewDataSource {
  // ...
}
extension MainViewController: UITableViewDelegate {
  // ...
}

2-2. 임포트

모듈 임포트 순서와 빈 줄로 구분하는 방법이 깔끔합니다.

import UIKit

import RxSwift
import RxCocoa

import then
import snpkit

// 그외의 의전성 모듈

2-3. 생명주기(Life Cycle)

생명주기 메서드는 아래와 같게해주세요

viewDidLoad   ↓ viewWillAppear  ↓ viewDidAppear  ↓ viewWillDisappear  ↓  viewDidDisappear

2-4. 줄바꿈

Lint에서 경고를 주겠자만 아래의 형식을 지키면 편합니다 함수 정의가 최대 길이를 초과하는 경우에는 아래와 같이 줄바꿈합니다.

func collectionView(
  _ collectionView: UICollectionView,
  cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
  // doSomething()
}
func animationController(
  forPresented presented: UIViewController,
  presenting: UIViewController,
  source: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
  // doSomething()
}

함수를 호출하는 코드가 최대 길이를 초과하는 경우에는 파라미터 이름을 기준으로 줄바꿈합니다.

let actionSheet = UIActionSheet(
  title: "정말 계정을 삭제하실 건가요?",
  delegate: self,
  cancelButtonTitle: "취소",
  destructiveButtonTitle: "삭제해주세요"
)

단, 파라미터에 클로저가 2개 이상 존재하는 경우에는 무조건 내려쓰기합니다.

UIView.animate(
  withDuration: 0.25,
  animations: {
    // doSomething()
  },
  completion: { finished in
    // doSomething()
  }
)

if let 구문이 길 경우에는 줄바꿈하고 한 칸 들여씁니다.

if let user = self.veryLongFunctionNameWhichReturnsOptionalUser(),
   let name = user.veryLongFunctionNameWhichReturnsOptionalName(),
  user.gender == .female {
  // ...
}

guard let 구문이 길 경우에는 줄바꿈하고 한 칸 들여씁니다. else는 guard와 같은 들여쓰기를 적용합니다.

guard let user = self.veryLongFunctionNameWhichReturnsOptionalUser(),
      let name = user.veryLongFunctionNameWhichReturnsOptionalName(),
      user.gender == .female
else {
  return
}
  • 빈 줄에는 공백이 포함되지 않도록 합니다.
  • 모든 파일은 빈 줄로 끝나도록 합니다.
  • MARK 구문 위와 아래에는 공백이 필요합니다.
  • extension 전에 줄 바꿈은 하나만.
// MARK: Layout

override func layoutSubviews() {
  // doSomething()
}

// MARK: Actions

override func menuButtonDidTap() {
  // doSomething()
}

2-5. self

self 사용을 지양하라는 규칙이 있습니다. 이는 가독성을 향상시키는 좋은 습관입니다.

2-6. 주석

주석을 최대한 작성하지 않도록 하는 규칙이 명확하게 정의되어 있습니다. 주석은 필요할 때에만 사용하는 것이 좋습니다.

기타

3-1. 프로그래밍 권장사항

초기화와 함께 변수를 정의하는 것은 좋은 습관입니다.

let label = UILabel().then {
  $0.textAlignment = .center
  $0.textColor = .black
  $0.text = "Hello, World!"
}

Literal을 관리하는 방식도 효과적입니다.

enum ImageLiterals {
    enum NavigationBar {
        static var icArrowLeft: UIImage { .load(named: "ic_back")}
    }
}

모든 Error 메세지는 한국어로 작성하시는 것을 권장합니다.

마지막으로, 상속되지 않는 클래스는 final로 선언하고, 변수는 private으로 선언하는 등의 권장합니다.

위와 같이 하면 우리도 아마 좋은 개발자의 길을 걷고 있는 것이 아닐까? 🏃