Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ha-nabi/swift
Swift 개발에 있어 범용적으로 사용할 수 있는 Swift Code Convension Guide를 정리합니다.
https://github.com/ha-nabi/swift
codeconvention swift
Last synced: 10 days ago
JSON representation
Swift 개발에 있어 범용적으로 사용할 수 있는 Swift Code Convension Guide를 정리합니다.
- Host: GitHub
- URL: https://github.com/ha-nabi/swift
- Owner: ha-nabi
- License: mit
- Created: 2024-04-05T07:18:09.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2024-08-01T09:38:41.000Z (4 months ago)
- Last Synced: 2024-10-11T22:50:18.826Z (about 1 month ago)
- Topics: codeconvention, swift
- Homepage:
- Size: 80.1 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Swift Code Convension Guide
Swift 개발에 있어 범용적으로 사용할 수 있는 코드 컨벤션 가이드입니다이 가이드는 코드의 일관성을 유지하고, 팀원 간의 협업을 원활하게 하기 위해 만들어졌습니다
## Index
- [Indentation](#indentation)
- [Naming](#naming)
- [Style](#style)
- [Functions](#functions)
- [Closures](#closures)
- [Operators](#operators)
- [Patterns](#patterns)
- [File Organization](#file-organization)
## **Indentation**
- 기본 4 whiteSpace 들여쓰기 사용
```swift
if exampleCode {
// ...
}
```
## Naming
- **타입과 프로토콜의 이름에는 PascalCase를 사용하고, 그 외에는 lowerCamelCase를 사용하기**
```swift
protocol SpaceThing {
// ...
}class SpaceFleet: SpaceThing {
enum Formation {
// ...
}class Spaceship {
// ...
}var ships: [Spaceship] = []
static let worldName: String = "Earth"func addShip(_ ship: Spaceship) {
// ...
}
}let myFleet = SpaceFleet()
```
- `@ViewBuilder` 메서드 경우 PascalCase 사용
```swift
@ViewBuilder
private func ExampleComponent() -> some View {
...
}
```
- Bool 타입 변수 선언 시, `is` || `has` 로 시작 할 수 있도록 선언
```swift
var isShowing: Bool = false
```
- 동작을 의미하는 변수 및 메서드 선언 시, 동사가 맨 앞으로 오도록 선언
```swift
enum Action {
case showDialog
...
}
```
- API - `fetch, add, update, delete` 명칭 사용 ( not used - remove, get, create … )
```swift
func fetchList() {
...
}
```
- extension 사용 시, 파일명 `xxxxx +.swift`
## Style
- **식별자 바로 뒤에 콜론(:)을 놓고 그 뒤에 공백을 두기**
```swift
var something: String = "코드 컨벤션 만들기"func addWork(_ work: String) {
// ...
}
```
- **쉽게 추론할 수 있는 유형은 타입 표기 생략하기 ( 객체 생성 )**
```swift
// WRONG
let host: Host = Host()// RIGHT
let host = Host()
``````swift
enum Direction {
case left
case right
}func someDirection() -> Direction {
// WRONG
return Direction.left// RIGHT
return .left
}
```
- `self.` - 네이밍이 겹치지 않는 이상 사용하지 않기
```swift
final class Listing {
init(capacity: Int, allowsPets: Bool) {
// WRONG
self.capacity = capacity
self.isFamilyFriendly = !allowsPets // `self.` not required here// RIGHT
self.capacity = capacity
isFamilyFriendly = !allowsPets
}private let isFamilyFriendly: Bool
private var capacity: Intprivate func increaseCapacity(by amount: Int) {
// WRONG
self.capacity += amount// RIGHT
capacity += amount// WRONG
self.save()// RIGHT
save()
}
}
```
- 여러 줄이 있는 배열은 각 괄호가 별도의 줄에 있도록 하기 ( 배열 속성 2개 이상의 경우 )
```swift
// WRONG
let rowContent = [listingUrgencyDatesRowContent(),
listingUrgencyBookedRowContent(),
listingUrgencyBookedShortRowContent()]// RIGHT
let rowContent = [
listingUrgencyDatesRowContent(),
listingUrgencyBookedRowContent(),
listingUrgencyBookedShortRowContent()
]
```
- guard let 구문 - else 문 클로저가 return 이 아닐 경우, 클로저 줄 내려서 사용
( 조건 여러개는 당연히 조건에만 여러 줄 사용 )
```swift
guard let xxxx = xxxx else { return }guard let xxxx = xxxx,
xxxx.sdsda.isEmpty,
xxxx.ssss.isEmpty else { return }guard let xxxx = xxxx else {
throw abcdError.aaaaa
}
```
- switch case 문은 각 case 별로 한줄씩 띄어서 사용
```swift
func handle(_ action: SpaceshipAction) {
switch action {case .engageWarpDrive:
warpDrive.engage()case .enableArtificialGravity:
artificialGravityEngine.enable(strength: .oneG)case .scanPlanet(let planet):
scanner.scan(planet)case .handleIncomingEnergyBlast:
energyShields.engage()
}
}
```
- 한줄 주석과 여러줄 주석을 구분하기
```swift
한줄 주석
//여러줄 주석
///
```
### Functions
- **함수 정의에서 Void 리턴 타입을 생략하기**
```swift
// WRONG
func doSomething() -> Void {
...
}// RIGHT
func doSomething() {
...
}
```
- **긴 함수의 호출 ( 파라미터 2개 이상 )**
```swift
// WRONG
universe.generateStars(at: location, count: 5, color: starColor, withAverageDistance: 4)// WRONG
universe.generateStars(at: location,
count: 5,
color: starColor,
withAverageDistance: 4)// RIGHT
universe.generateStars(
at: location,
count: 5,
color: starColor,
withAverageDistance: 4
)
``````swift
// RIGHT
func generateStars(
at location: Point,
count: Int,
color: StarColor,
withAverageDistance averageDistance: Float
) async throws -> String {
populateUniverse()
}// RIGHT
func generateStars(
at location: Point,
count: Int,
color: StarColor,
withAverageDistance averageDistance: Float
) {
populateUniverse()
}
```
### **Closures**
- **사용하지 않는 클로저 파라미터의 이름은 밑줄(`_`)로 표시하기**
```swift
// WRONG
someAsyncThing() { argument1, argument2, argument3 in
print(argument3)
}// RIGHT
someAsyncThing() { _, _, argument3 in
print(argument3)
}
```
### **Operators**
- **중위 연산자는 양쪽에 공백이 하나씩 두기 및** 다양한 공백 너비보다는 괄호를 사용하여 연산자가 많은 문을 시각적으로 그룹화하기
```swift
// WRONG
let capacity = 1+2
let capacity = currentCapacity ?? 0
let mask = (UIAccessibilityTraitButton|UIAccessibilityTraitSelected)
let capacity=newCapacity
let latitude = region.center.latitude - region.span.latitudeDelta/2.0// RIGHT
let capacity = 1 + 2
let capacity = currentCapacity ?? 0
let mask = (UIAccessibilityTraitButton | UIAccessibilityTraitSelected)
let capacity = newCapacity
let latitude = region.center.latitude - (region.span.latitudeDelta / 2.0)
```
- 삼항 연산자의 표현이 너무 길어지면, 줄 내려서 사용하기
```swift
let xx = ab ? a : blet destinationPlanet = solarSystem.hasPlanetsInHabitableZone ?
solarSystem.planetsInHabitableZone.first :
solarSystem.uninhabitablePlanets.first
```
- 조건이 여러 개의 경우, 각 조건이 별도의 줄에 있도록 하기 ( 조건 2개 이상의 경우 )
```swift
// WRONG
if selectImage != userSaveImage && userNickname != nickname && userManager.uid != "" {
// ...
}// RIGHT
if selectImage != userSaveImage &&
userNickname != nickname &&
userManager.uid != "" {
// ...
}
```
## Patterns
- **열거형에서 `switch`를 사용할 때 `default` case를 사용하지 말기**
```swift
// WRONG
switch trafficLight {
case .greenLight:
// Move your vehicle
default:
// Stop your vehicle
}// RIGHT
switch trafficLight {
case .greenLight:
// Move your vehicle
case .yellowLight, .redLight:
// Stop your vehicle
}
```
- **기본 클래스는 `final`**
```swift
// WRONG
class SettingsRepository {
// ...
}// RIGHT
final class SettingsRepository {
// ...
}
```
- **한줄일 경우엔`return` 생략**
```swift
// WRONG
["1", "2", "3"].compactMap { return Int($0) }var size: CGSize {
return CGSize(
width: 100.0,
height: 100.0)
}func makeInfoAlert(message: String) -> UIAlertController {
return UIAlertController(
title: "ℹ️ Info",
message: message,
preferredStyle: .alert)
}var alertTitle: String {
if issue.severity == .critical {
return "💥 Critical Error"
} else {
return "ℹ️ Info"
}func type(of planet: Planet) -> PlanetType {
switch planet {
case .mercury, .venus, .earth, .mars:
return .terrestrial
case .jupiter, .saturn, .uranus, .neptune:
return .gasGiant
}
}// RIGHT
["1", "2", "3"].compactMap { Int($0) }var size: CGSize {
CGSize(
width: 100.0,
height: 100.0)
}func makeInfoAlert(message: String) -> UIAlertController {
UIAlertController(
title: "ℹ️ Info",
message: message,
preferredStyle: .alert)
}var alertTitle: String {
if issue.severity == .critical {
"💥 Critical Error"
} else {
"ℹ️ Info"
}func type(of planet: Planet) -> PlanetType {
switch planet {
case .mercury, .venus, .earth, .mars:
.terrestrial
case .jupiter, .saturn, .uranus, .neptune:
.gasGiant
}
}
```
## **File Organization**
- **서로 다른 종류의 프로퍼티 선언 사이에 빈 줄을 추가하기**
```swift
// WRONG
static let gravityEarth: CGFloat = 9.8
static let gravityMoon: CGFloat = 1.6
var gravity: CGFloat// RIGHT
static let gravityEarth: CGFloat = 9.8
static let gravityMoon: CGFloat = 1.6var gravity: CGFloat
```
- import 문 관리
내부 / 외부 한 줄 띄고 관리 ( 외부를 상단에, 내부를 하단에, test 최하단 )
a-z 알파벳 순으로
```swift
import Constellation
import DLSPrimitives
import Epoxyimport Foundation
@testable import Epoxy
```
- 프로퍼티 순서
- 한줄 띄어서 구분
- `propertyWrapper` 가 붙는 프로퍼티를 최상단에 선언
- EnvironmentObject, StateObject, ObservedObject, State, Binding, private 순으로 선언
- var / let 의 경우, var 를 상단에 let 을 하단에 선언
```swift
struct xxx {
@EnvironmentObject var ...
@StateObject var ...
@ObservedObject var ...
@State var ...
@Binding var ...
@Presents var ppp: ...
private var ...
var aaa
var bbb
var ccc
let ddd
let eee
}
```
- 연산 프로퍼티는 프로퍼티 중 맨 밑에 선언
```swift
// WRONG
var atmosphere: Atmosphere {
didSet {
print("oh my god, the atmosphere changed")
}
}
var gravity: CGFloat
// RIGHT
var gravity: CGFloat
var atmosphere: Atmosphere {
didSet {
print("oh my god, the atmosphere changed")
}
}
```
- In TCA
- @Dependency 위치는 Action 과 body 사이에 사용
- @Dependency 도 알파벳 순으로 선언
```swift
enum Action {
...
}
@Dependency(\.dismiss) var dismiss
@Dependency(\.swiftDataService) var swiftData
var body: some ReducerOf {
```
- 프로퍼티 && 액션
- 관련 기능끼리 모으는걸 우선시하고, 내부에서는 알파벳 순으로 정렬하기