Skip to content

Swift Style Guide

HyeRyeong Jang edited this page Jun 9, 2024 · 1 revision

목차

코드 레이아웃

들여쓰기 및 띄어쓰기

  • 들여쓰기는 탭(tap) 대신 2개의 스페이스(space)를 사용합니다.

    struct ContentView: View { 
      @State private var greeting = "hi"
        // doSomething()
    }
  • 콜론(:)을 쓸 때는 오른쪽에만 공백을 둡니다.

    let names: [String: String]?

임포트

  • 모든 임포트는 알파벳 순으로 정렬합니다.

    import Combine
    import ComposableArchitecture
    import Foundation
    import TCACoordinators

개행

  • 모든 개행은 관심사 단위로 합니다.

줄바꿈

최대 길이를 초과하는 경우 줄바꿈합니다.

  • 함수 정의가 최대 길이를 초과하는 경우 매개변수를 기준으로 줄바꿈합니다.

    func request(
      _ request: Request, 
      didFailTask task: URLSessionTask, 
      earlyWithError error: AFError
    )
  • 리듀서의 길이가 최대 길이를 초과하는 경우 제너릭 타입을 기준으로 줄바꿈합니다.

    let veryLongNameAppReducer: Reducer<
      VeryLongNameAppState,
      VeryLongNameAppAction,
      VeryLongNameAppEnvironment
    >
  • if let 구문이 길 경우 줄바꿈 후 let에 맞춥니다.

    if let data = functionWhichReturnsOptionalDataType(),
       let statusCode = data.functionWhichReturnsOptionalStatusCode() 
    else { 
      return 
    }
  • guard let 구문이 길 경우 줄바꿈 후 let에 맞춥니다.

    guard let data = functionWhichReturnsOptionalDataType(),
          let statusCode = data.functionWhichReturnsOptionalStatusCode() 
    else { 
      return 
    }

    단, 옵셔널 바인딩할 값이 2개 이상이면 무조건 줄바꿈합니다.

    guard let data = functionWhichReturnsOptionalDataType(),
          let statusCode = data.functionWhichReturnsOptionalStatusCode() 
    else { 
      return 
    }

최대 행 길이

최대 행 길이는 120자입니다.

Xcode의 Preferences → Text Editing → Display의 'Page guide at column' 옵션을 활성화하고 120자로 설정하면 편리합니다. columnlength

네이밍

변수 및 상수

  • 변수 및 상수는 명사형으로 작성하되, lowerCamelCase를 사용합니다.
var myAge = 20
let myName = "taeyeon"

구조체 및 클래스

  • 구조체 및 클래스는 UpperCamelCase를 사용합니다.
struct MyStruct {
  // Code
}

class MyClass {
  // Code
}

함수

  • 함수는 동사형으로 작성하되, lowerCamelCase를 사용합니다.
func play() {
  // Code
}

프로토콜

  • 프로토콜은 형용사형으로 작성하되, UpperCamelCase를 사용합니다.
protocol Runnable {
  // Code
}

리듀서 액션

  • Inner action에 _접두사를 붙여 액션을 구분합니다.
public enum CustomAction: Equatable {
  // MARK: - User Action
  case buttonTapped:
  
  // MARK: - Inner Business Action
  case _saveName(String)
  case _updateId(String)
  
  // MARK: - Inner SetState Action
  case _setName(String)
  case _setId(String)
}

코드 스타일

클로저

  • 반환형이 없는 클로저는 다음과 같이 작성합니다.
// Good😊
let closure: (() -> Void)?

// Bad🙁
let closure: (() -> ())?
let closure: ((Void) -> (Void))?
let closure: ((Void) -> ())?
  • 매개변수의 괄호는 다음과 같이 생략하여 사용합니다.
// Good😊
{ a, b in
    // doSomething
}

// Bad🙁
{ (a, b) in
    // doSomething
}
  • 매개변수 타입의 정의는 생략합니다.
// Good😊
{ a, b in 
    // doSomething()
}

// Bad🙁
{ a: Int, b: Int in 
    // doSomething()
}

{ (a: Int, b: Int) in 
    // doSomething()
}

구조체 및 클래스

  • 생성자의 위치는 반드시 프로퍼티 뒤에 작성합니다.
// Good😊
struct MyStruct {
  let firstProperty: String
  let secondProperty: Int
  let thirdProperty: String
	
  init(firstProperty: String, secondProperty: Int, thirdProperty: String) {
    self.firstProperty = firstProperty
    self.secondProperty = secondProperty
    self.thirdProperty = thirdProperty
  } 
}

// Bad🙁
struct MyStruct {
  init(firstProperty: String, secondProperty: Int, thirdProperty: String) {
    self.firstProperty = firstProperty
    self.secondProperty = secondProperty
    self.thirdProperty = thirdProperty
  } 
  
  let firstProperty: String
  let secondProperty: Int
  let thirdProperty: String
}
  • 프로퍼티와 생성자의 순서는 동일하게 작성합니다.
// Good😊
struct MyStruct {
  let firstProperty: String
  let secondProperty: Int
  let thirdProperty: String
	
  init(firstProperty: String, secondProperty: Int, thirdProperty: String) {
    self.firstProperty = firstProperty
    self.secondProperty = secondProperty
    self.thirdProperty = thirdProperty
  } 
}

// Bad🙁
struct MyStruct {
  let secondProperty: Int
  let firstProperty: String
  let thirdProperty: String
	
  init(firstProperty: String, secondProperty: Int, thirdProperty: String) {
    self.firstProperty = firstProperty
    self.secondProperty = secondProperty
    self.thirdProperty = thirdProperty
  } 
}

열거형

  • case let을 사용하되, 연관값의 바인딩은 다음과 같이 작성합니다.
// Good😊
case let .buttonTapped(name, age):

// Bad🙁
case let .buttonTapped(name: String, age: Int):
case .buttonTapped(let name, let age):
case .buttonTapped(let name: String, let age: Int):

타입

  • Array, Dictionary<T: U> 보다 [T], [T: U]를 사용합니다.
// Good😊
var array: [Int]?
var dictionary: [String: String]?

// Bad🙁
var array: Array<Int>?
var dictionary:  Dictionary<String: String>?
  • 빈 배열과 빈 딕셔너리는 타입을 명시하여 작성합니다.
// Good😊
var array: [Int] = []
var dictionary: [String: String] = [:]

// Bad🙁
var array = [Int]()
var dictionary = [String: String]()
Clone this wiki locally