프렌트립 iOS 개발자들이 코드를 이해하고 작성하는데, 조금 더 도움을 주고 명확하게 의사소통하기 위한 스위프트 스타일 가이드입니다.
아래 내용들을 바탕으로 코드 리뷰 때, 신명나게 지적해주세요.😜
해당 내용들 중 반영하고 싶은 내용이나 수정하고 싶은 내용이 있다면 언제든 PR날려주세요!
더 원활한 코딩을 위한 개선은 언제든 환영이라구요!
- 디렉토리 이름은 대문자로 시작하는 단어로 설정합니다.
- 해당 디렉토리에 비슷한 기능을 하는 파일들이 들어있다면 단어의 끝에 복수로
s
를 붙여줍니다.- Good👏
- Domains, Analytics, Managers...
- Bad👎
- Model(X), Service(X)... => Models, Services
- Good👏
- 파일명은
UpperCamelCase
를 사용합니다. - 뷰 컨트롤러는 줄여서 쓰지 않고
ViewController
로 사용합니다. - 뷰모델 혹은 리액터는 뷰 컨트롤러와 매칭되는 **접두사(prefix)**를 사용합니다.
- Good👏
- HomeReactor.swfit - HomeViewController.swift
- Bad👎
- HomeViewReactor.swfit - HomeVC.swfit
- Good👏
- 클래스 이름은
UpperCamelCase
를 사용합니다.
- 함수 이름은
lowerCammerCase
를 사용합니다. - 함수 이름에
get
이란 단어는 최대한 지양합니다.- get이란 단어는 광범위 하므로 다른 개발자가 읽었을 때 한번에 이해할 수 있을 만한 함수의 액션을 나타내는 단어를 사용합니다.
- Good👏
func fetchUserInfo() { ... } func searchUser() { ... }
- Bad👎
func getUserInfo() { ... }
- 변수 이름은
lowerCammerCase
를 사용합니다. - 변수 타입 중 Bool타입은 is 와같은 be동사를 접두사를 붙여서 사용합니다.
- 배열 혹은 리스트와 같이 복수의 의미를 담고있는 변수라면 끝에 s를 붙여서 사용합니다.
- Good👏
var messages: [String] var userInfo: UserInfo var isFinished: Bool
- Bad👎
var message: [String] var finished: Bool
- Good👏
- 상수 이름은
lowerCammerCase
를 사용합니다.-
Good👏
let profileImageWidth = 100
-
Bad👎
let PROFILE_IMAGE_WIDTH = 100
-
- 열거형 enum 변수들은
lowerCammerCase
를 사용합니다.-
Good👏
enum ContentType { case text case image }
-
Bad👎
enum ContentType { case Text case IMAGE }
-
- 약어로 시작하는 경우에는 소문자를 사용합니다.
- 중간에 약어가 들어가는 경우에는 대문자를 사용합니다.
-
Good👏
var userID: String var html: String var imageURL: String
-
Bad👎
var userId: String var HTML: String var imageUrl: String
-
- 한줄 최대 길이는 100자로 설정합니다.
- XCode > Preferences > Text Editing > Display > Page guide at column에서 설정 가능합니다.
-
콜론(:)뒤에는 띄어쓰기를 사용합니다.
-
Good👏
var userID: String
-
Bad👎
var userID : String
-
-
삼항 연산자의 경우에는 콜론(:) 앞에도 띄어쓰기를 사용합니다.
-
Good👏
likeCount = isLiked ? 0 : 1
-
Bad👎
likeCount = isLiked ? 0: 1
-
-
함수를 정의할 때, 인자 콤마(,)뒤에는 띄어쓰기를 사용합니다.
-
Good👏
func sum(number1: Int, number2: Int)
-
Bad👎
func sum(number1: Int,number2: Int)
-
-
연산자 앞뒤로 공백을 추가해서 사용합니다.
-
Good👏
var sum = 20 + (40 / 2)
-
Bad👎
var sum = 20+(40/2)
-
-
함수의 인자 혹은 이름이 길어서 100자 이상길어질 경우 다음과 같이 줄바꿈 합니다.
-
Good👏
self.navigationController.pushViewController( viewController, animated: true )
-
Bad👎
self.navigationController.pushViewController(viewController, animated: true)
-
-
배열의 컨텐츠를 정의할 때 길이가 길어진다면 다음과 같이 줄바꿈 합니다.
-
Good👏
self.addSubViews([ self.titleLabel, self.titleButton, self.nextButton ])
-
Bad👎
self.addSubViews([self.titleLabel, self.titleButton, self.nextButton])
-
-
변수의 네이밍과 타입명이 길어서 정의하는데 100줄이 넘어간다면 다음과 같이 줄바꿈 합니다.
-
Good👏
private var myPageTableViewDataSource = RxTableViewSectionedReloadDataSource<MyPageSecionModel>()
-
Bad👎
private var myPageTableViewDataSource = RxTableViewSectionedReloadDataSource<MyPageSecionModel>()
-
-
if let 구문이 길어질 경우에는 쉼표 이후에 줄바꿈을 합니다.
-
Good👏
if let myInfo = self.userInfo, let myAge = myInfo.age, let myNickname = myInfo.nickname { .. }
-
Bad👎
if let myInfo = self.userInfo, let myAge = myInfo.age, let myNickname = myInfo.nickname { .. }
-
-
guard let ... else 는 한줄에 표시합니다.
-
Good👏
guard let myInfo = self.userInfo else { return }
-
Bad👎
guard let myInfo = self.userInfo else { return }
-
-
switch문 안의 case문은 줄바 꿈 후 내용을 정의합니다.
-
case문들 사이에는 한줄 공백을 추가합니다.
-
Good👏
switch action { case .tapHome: print("Tap home") case .tapRefresh: print("Tap refresh") }
-
Bad👎
switch action { case .tapHome: print("Tap home") case .tapRefresh: print("Tap refresh")
-
-
import중 System package 와 3rd party package 사이에 공백을 추가합니다.
-
Good👏
import Foundation import UIKIt import RxSwift import Rxcocoa
-
Bad👎
import Foundation import UIKi import RxSwift import Rxcocoa
-
- swifth 문 내부의 case에 parameter가 있을 경우 let은 맨 앞이 아닌 각 parameter 명 앞에 선언합니다.
-
Good👏
switch error { case .unknown: // Do something case .forbidden: // Do something case .custom(let message): // Do something
-
Bad👎
switch error { case .unknown: // Do something case .forbidden: // Do something case let .custom(message): // Do something
-
- 클래스, 구조체 지역 변수를 사용할 때,
self
를 명시적으로 사용합니다. - 더이상 상속이 이루어지지 않는 클래스에는
final
키워드를 붙입니다. - 프로토콜을 채택할 경우,
extension
을 사용합니다.-
Good👏
class ViewController: UIViewController { ... } extension ViewController: UITableViewDelegate { ... }
-
Bad👎
class ViewController: UIViewController, UITableViewDelegate { ... }
-
- 클로저 내의 인자에는 괄호를 사용하지 않습니다.
-
Good👏
asyncFunction() { argument1, argument2 in ... }
-
Bad👎
asyncFunction() { (argument1, argument2 in ... }
-
- 사용하지 않는 클로저 인자는
_
로 선언합니다.-
Good👏
asyncFunction() { _, argument2 in print(argument2) }
-
Bad👎
asyncFunction() { argument1, argument2 in print(argument2) }
-
- UI 컴포넌트 정의 사이에는 한줄 공백을 추가합니다.
-
Good👏
// MainView.swift let titleLabel = UILabel() let titleButton = UIButton()
-
Bad👎
// MainView.swift let titleLabel = UILabel() let titleButton = UIButton()
-
- UIView 상속 클래스들의 변수 및 함수 선언 순서는 다음과 같습니다.
- 상수
- UI컴포넌트 정의
- 생성자 및 소멸자
- override 함수
- public 함수
- private 함수
- 같은 접근 제어자를 가진 함수 내에서는 사용 순서대로 선언합니다.
- ViewController를 상속하는 클래스들의 변수 및 함수 선언 순서는 다음과 같습니다.
- 상수
- View, ViewModel 변수 정의
- 생성자 및 소멸자
- override 함수 (ViewController lifecycle)
- public 함수
- private 함수