일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- appstore
- stack
- error
- rxswift
- Git
- Firebase
- mac
- github
- darkmode
- Xcode
- SwiftUI
- Session
- Notification
- UIButton
- window
- IOS
- MacOS
- FLUTTER
- iOS16
- Realm
- 웹뷰
- Swift
- JPA
- Python
- Code
- Apple
- Archive
- view
- 한글
- 개발자
- Today
- Total
EEYatHo 앱 깎는 이야기
Swift ) 코드 컨벤션 - EEYatHo iOS 본문
노션 링크
📌 코드 포맷팅
띄어쓰기, 쉼표, 콜론, 줄바꿈 등. 기능 및 성능과는 직접적인 연관이 없는, 코드들의 모양 (겉부분) 을 다룹니다.
통일된 코드 포멧은, 우리 뇌의 청킹을 도와, 타인의 코드를 더 쉽게 볼 수 있게 도와줍니다.
1. import
- import 순서
내장 프레임워크를 먼저 import 한 후, 한줄 띄우고 third-party 들을 import 합니다.
이후 알파벳 순으로 정렬합니다.
✅ Preferred
import Foundation
import UIKit
import AdSupport
import AppTrackingTransparency
import RxCocoa
import RxSwift
import SwiftyJSON
⛔ Not Preferred
import UIKit
import AppTrackingTransparency
import Foundation
import RxSwift
import RxCocoa
import SwiftyJSON
import AdSupport
- 필요한 최소한의 모듈만 import 합니다.
✅ Preferred
import UIKit
var view: UIView
⛔ Not Preferred
import Foundation
import UIKit // not required
var view: UIView
2. 들여쓰기
- control(^) + i
control(^) + i 를 이용해 들여쓰기 합니다.
✅ Preferred
var vaildProductCount: Int {
allProducts
.filter { $0.isVaild }
.count
}
⛔ Not Preferred
var vaildProductCount: Int {
allProducts
.filter { $0.isVaild }
.count
}
3. 띄어쓰기
- 콜론(:)
클래스 상속, 클래스 프로토콜 채택, 타입 선언, 호출 파라미터, 선언 파라미터, 제네릭 프로토콜 채택, 딕셔너리에서 콜론(:) 사용 시, 오른쪽에만 띄어쓰기를 하나 둡니다.
삼항연산자를 제외한 모든 곳 입니다.
✅ Preferred
class MyViewController: UIViewController { ... }
extension MyViewController: UITableViewDataSource { ... }
let headerDictionary: [String: String] = [
"Content-Type": "application/json"
]
someFunction(name: someString)
func myFunction<T, U: SomeProtocol>(firstParam: T, secondParam: U) { ... }
⛔ Not Preferred
class MyViewController:UIViewController { ... }
extension MyViewController : UITableViewDataSource { ... }
let headerDictionary:[String : String] = [
"Content-Type":"application/json"
]
someFunction(name : someString)
func myFunction<T, U:SomeProtocol>(firstParam : T, secondParam:U) { ... }
- 삼항연산자에서 콜론(:) 사용 시, 양 옆에 띄어쓰기를 하나 둡니다.
✅ Preferred
var dayString = day < 10 ? "0\\(day)" : "\\(day)"
⛔ Not Preferred
var dayString = day < 10 ? "0\\(day)": "\\(day)"
- 쉼표(,)
배열, 함수, switch-case 등 모든 곳에서 쉼표(,) 사용 시, 오른쪽에만 띄어쓰기를 하나 둡니다.
✅ Preferred
let array = ["A", "B", "C"]
func testFunc<T, U>(firstParam: T, secondParam: U) { ... }
someFunction(name: "a", age: 15)
switch number {
case 1, 2, 3:
// Do something
default:
break
}
let dict: [String: Int] = [
"a": 1,
"b": 2
]
⛔ Not Preferred
let array = ["A","B" , "C"]
func testFunc<T,U>(firstParam: T , secondParam: U) { ... }
someFunction(name: "a",age: 15)
switch number {
case 1 , 2,3:
// Do something
default:
break
}
let dict: [String: Int] = [
"a": 1 ,
"b": 2
]
- 연산자
연산자는 양 옆에 띄워쓰기를 하나 둡니다.
✅ Preferred
let answer = 1 + 2 / 3 % (4 * 5)
⛔ Not Preferred
let answer = 1+2/3%(4*5)
- 함수 선언 소괄호
일반적으로 함수 선언시, 함수명과 소괄호를 붙혀쓰고, 연산자 오버로딩시 띄어쓰기 하나를 둡니다.
Swift 내장 프레임워크를 참고하였습니다. (ex. Equatable 구현부)
✅ Preferred
func testFunc() {}
func == (lhs: SomeClass, rhs: SomeClass) {}
⛔ Not Preferred
func testFunc () {}
func ==(lhs: SomeClass, rhs: SomeClass) {}
- 리턴 타입 ( 화살표 )
함수와 클로저 리턴 타입에 사용되는 화살표는 양 옆에 띄워쓰기를 하나 둡니다.
✅ Preferred
func someFunc() -> String { ... }
let completion: () -> Void
⛔ Not Preferred
func someFunc()->String { ... }
let completion: ()->Void
- 한줄 클로저
한줄 클로저 등, 중괄호 안쪽은 띄워쓰기를 하나 둡니다.
✅ Preferred
numArray
.filter { $0 % 2 == 0 }
.map { "\\($0)" }
.joined(separator: ",")
guard let self = self else { return }
⛔ Not Preferred
numArray
.filter {$0 % 2 == 0}
.map {"\\($0)" }
.joined(separator: ",")
guard let self = self else { return}
4. 줄 바꿈
- Page guide 120 charactor
Xcode 의 Page guide 기준, 120 charactor 을 넘으면 반드시 줄 바꿈 합니다.
SwiftLint 의 기본값을 참고했습니다.
✅ Preferred
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { ... }
⛔ Not Preferred
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { ... }
- guard let self = self else { return }
guard let self = self else { return } 은 한 줄로 씁니다.
✅ Preferred
guard let self = self else { return }
⛔ Not Preferred
guard let self = self else {
return
}
- // MARK: -
// MARK: - 주석은 위로 2개 아래로 1개 빈 줄을 둡니다.
✅ Preferred
final class HomeViewController: UIViewController { ... }
// MARK: - UITableViewDataSource
extension HomeViewController: UITableViewDataSource { ... }
// MARK: - UITableViewDelegate
extension HomeViewController: UITableViewDelegate { ... }
⛔ Not Preferred
final class HomeViewController: UIViewController { ... }
// MARK: - UITableViewDataSource
extension HomeViewController: UITableViewDataSource { ... }
// MARK: - UITableViewDelegate
extension HomeViewController: UITableViewDelegate { ... }
- 여는 중괄호 ( 1TBS 스타일 )
여는 중괄호({) 를 새 줄에 배치하지 않습니다.
1TBS 스타일을 사용합니다.
✅ Preferred
func someMethod() {
// Do something
}
⛔ Not Preferred
func someMethod()
{
// Do something
}
5. 소괄호
- 불필요한 소괄호 생략
if, switch-case, 파라미터, 후행 클로저 등 불필요한 소괄호는 생략합니다.
✅ Preferred
if count > 0 { ... }
switch type { ... }
_ = arr.filter { num in num % 2 == 0 }
⛔ Not Preferred
if (count > 0) { ... }
switch (type) { ... }
_ = arr.filter() { (num) in num % 2 == 0 }
📌 네이밍
네이밍은 코드의 첫인상 입니다.
클래스와 함수의 표기법이 같은 경우, 생성자인지 함수인지 헷갈리게하고,
동의어를 여러개 쓴 경우, 같은 의미임에도 다른 의미가 있는지 불필요한 생각을 하게도 합니다.
1. 표기법
- UpperCamelCase
클래스, 구조체, 열거형, 프로토콜, Xcode 안에서 만들수 있는 파일 이름(.swift, .storyboard, .xcassets, .plist 등) 에는 UpperCamelCase 를 사용합니다.
단어의 첫글자를 대문자로 표기합니다.
✅ Preferred
class MyViewController { ... }
struct MyModel { ... }
enum SomeEnum { ... }
protocol RootPresentable { ... }
// swift 파일 이름 : MyViewController.swift
// storyboard 파일 이름 : LaunchScreen.storyboad
// xcassets 파일 이름 : AppIcon.xcassets
⛔ Not Preferred
class myViewController { ... }
struct myModel { ... }
enum someenum { ... }
protocol rootpresentable { ... }
// swift 파일 이름 : Myviewcontroller.swift
// storyboard 파일 이름 : launchScreen.storyboad
// xcassets 파일 이름 : app_icon.xcassets
- lowerCamelCase
변수, 상수, 함수, case, Xcode 외부에서 가져온 파일 이름(.png, .json, .wav )등 에는 lowerCamelCase 를 사용합니다.
단어의 첫글자를 대문자로 표기하되, 첫글자를 소문자로 표기합니다.
✅ Preferred
var myVariable = 0
let leftPadding = 16.0
func someFunc() { ... }
enum {
case firstCase
case secondCase
}
// 이미지 파일 이름 : logout24Gray800
// Lottie 파일 이름 : live.json
// 사운드 파일 이름 : foundItem.wav
⛔ Not Preferred
var myvariable = 0
let LEFT_PADDING = 16.0
func SomeFunc() { ... }
enum {
case FirstCase
case secondcase
}
// 이미지 파일 이름 : logout_24_gray_800
// Lottie 파일 이름 : Live.json
// 사운드 파일 이름 : FOUND_ITEM.wav
2. 명명법
- 동의어
동의어들 중에 어떤 것을 사용할지 정리합니다.
뜻 | ✅ 사용할 이름 | ⛔ 사용하지 않을 이름 |
상품 | product | item |
편성표 | timeline | schedule, pairing, timeLine |
상품 ID | productId | pid, id, pdid, crawlId, shopVenderProductId |
엔티티 ID | entitiyId | eid, id, itemId |
유저 ID | xid | serverId, userId, userToken |
쇼핑사명 | shop | genre2, logo |
타입 | type | case, kind |
유저 터치 | tap | touch, click, press, tab |
유저 텍스트 입력 | write | input, text, change |
유저 스크롤 | scroll | drag, pullUp, pullDown |
요청 | get | request, fetch |
초기화 | create | init |
여백 | padding | margin, space, edge |
- 액션 함수
액션함수(유저 인터렉션을 처음 처리하는 함수) 와 ReactorKit.Action 는, 주어 + 동사 + 목적어 순으로 사용합니다.
액션이 일어나기 전을 will, 일어난 후를 did 로 표현합니다.
ex) tap, write, scroll 등
✅ Preferred
@objc func backButtonDidTap() { ... }
⛔ Not Preferred
@objc func pop() { ... }
@objc func clickBack() { ... }
- API 함수
API 를 호출하는 함수는 앞에 HTTP 함수를 붙힙니다.
ex) get, post, put, delete, patch 등
✅ Preferred
static func getAccessToken() -> Observable<Data> { ... }
static func patchShippingAddress() -> Observable<Data> { ... }
⛔ Not Preferred
static func requestAccessToken() -> Observable<Data> { ... }
static func takeAccessToken() -> Observable<Data> { ... }
static func fetchAccessToken() -> Observable<Data> { ... }
static func updateShippingAddress() -> Observable<Data> { ... }
static func modifyShippingAddress() -> Observable<Data> { ... }
- 약어
약어는 모두 대문자로 표기하고, 약어로 시작하는 경우에만 소문자로 표기합니다.
✅ Preferred
var productID: Int?
var urlString: String?
var homeVC: ViewController?
⛔ Not Preferred
var productId: Int?
var URLString: String?
var homevc: ViewController?
- 명확한 이름
클래스, 함수, 변수 어디든. 가능한 명확하고 모든 의미를 포함하는 이름을 사용합니다.
이름이 길어져도 의미가 있는 이름이, 타인의 코드를 볼 때 훨씬 빠르고 편합니다.
✅ Preferred
class RoundAnimationButton { ... }
func startAnimating() { ... }
let animationDuration: CGFloat
let personImageView: UIImageView
let titleLabel: UILabel
⛔ Not Preferred
class CustomButton { ... }
func srtAnimating() { ... }
let aniDur: CGFloat
let personImage: UIImageView // image? imageView?
let title: UILabel // String? label?
- Protocol
프로토콜의 이름은, 애플의 API 디자인 가이드라인을 참고합니다.
- 무엇인가 설명하는 프로토콜은 명사로 읽어야 합니다. (e.g. Collection).
- 기능을 설명하는 프로토콜은 able, ible, ing 접미사를 사용합니다.(e.g. Equatable, ProgressReporting)
- 어떤 것도 적합하지 않은 경우, Protocol 을 접미사로 사용할 수 있습니다.
✅ Preferred
protocol ImagePresentable { ... }
protocol NotificationUIProtocol { ... }
⛔ Not Preferred
protocol ImagePresent { ... }
protocol NotificationUIType { ... }
📌 Detail. 코드 스타일
1. 타입추론 최대한 사용
가능하면 타입추론을 사용합니다.
✅ Preferred
let selector = #selector(viewDidLoad)
view.backgroundColor = .red
let toView = context.view(forKey: .to)
let view = UIView(frame: .zero)
⛔ Not Preferred
let selector = #selector(ViewController.viewDidLoad)
view.backgroundColor = UIColor.red
let toView = context.view(forKey: UITransitionContextViewKey.to)
let view = UIView(frame: CGRect.zero)
2. self 생략
필수가 아닌 이상, self 를 사용하지 않습니다.
✅ Preferred
private let name: String
private let isAdult: Bool
init(name: Int, age: Bool) {
self.name = name
idAdult = age > 18
}
⛔ Not Preferred
private let name: String
private let isAdult: Bool
init(name: Int, age: Bool) {
self.name = name
self.idAdult = age > 18
}
3. tuple 값 네이밍
tuple 이 가진 값에는 명확성을 위해 이름을 붙혀줍니다.
✅ Preferred
func someFunc() -> (x: Int, y: Int) {
return (x: 4, y: 4)
}
enum SomeEnum {
case someCase(x: Int, y: Int)
}
⛔ Not Preferred
func someFunc() -> (Int, Int) {
return (4, 7)
}
enum SomeEnum {
case someCase(Int, Int)
}
4. 배열과 딕셔너리 생성
배열과 딕셔너리를 생성할 때 [T], [T: U] 를 사용합니다.
✅ Preferred
var stringArray: [String]?
var stringDictionary: [Int: String]?
⛔ Not Preferred
var stringArray: Array<String>?
var stringDictionary: Dictionary<Int, String>?
5. 내장 프로퍼티 선언과 초기화
내장 프로퍼티는 가능하면 unwrapped Optional 을 사용하고, 생성자에서 초기화합니다.
✅ Preferred
class SomeClass: NSObject {
init() {
someInt = 0
someString = "created"
super.init()
}
var someInt: Int
var someString: String
}
⛔ Not Preferred
class SomeClass: NSObject {
init() {
super.init()
}
var someInt: Int = 0
var someString: String?
}
6. 타입 메소드는 static
타입 메소드는 static 을 사용합니다.
✅ Preferred
class
⛔ Not Preferred
class SomeClass: NSObject {
init() {
super.init()
}
var someInt: Int = 0
var someString: String?
}
7. final 사용
상속이 필요없는 class, 함수, 변수는 final 키워드를 사용합니다.
final 을 사용하면, 동적 디스패치를 거치지 않고 직접 호출하기 때문에, 컴파일 성능 이점이 있습니다.
✅ Preferred
final class SomeClass: NSObject {
final var arr: [Int]
final func someFunc() {}
}
⛔ Not Preferred
class SomeClass: NSObject {
var arr: [Int]
func someFunc() {}
}
8. 프로토콜 채택시, 코드 나누기
프로토콜 채택시, extension과 // MARK: - 주석으로 나눕니다.
✅ Preferred
final class HomeViewController: UIViewController { ... }
// MARK: - UITableViewDataSource
extension HomeViewController: UITableViewDataSource { ... }
// MARK: - UITableViewDelegate
extension HomeViewController: UITableViewDelegate { ... }
⛔ Not Preferred
final class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { ... }
9. switch-case default 미사용
switch-case 문 사용시, 가능하면 default 를 사용하지 않습니다.
새로운 case 생성시 놓칠 수 있기 때문입니다.
✅ Preferred
switch someEnum {
case someCase1:
print("someCase1")
case someCase2, soemCase3:
break
}
⛔ Not Preferred
switch someEnum {
case someCase1:
print("someCase1")
default:
break
}
10. 사용하지 않는 코드
Xcode가 자동으로 생성했지만, 사용하지 않는 코드는 모두 제거합니다.
✅ Preferred
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
}
⛔ Not Preferred
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = .white
}
- 참고 링크
'iOS, Swift' 카테고리의 다른 글
iOS ) 점진적 배포 - EEYatHo iOS (0) | 2023.03.02 |
---|---|
iOS 및 개발자 컨퍼런스 정리 (0) | 2023.01.12 |
iOS ) Simulator 단축키 (0) | 2022.11.15 |
iOS ) iOS 16 개발자 모드 - EEYatHo iOS (0) | 2022.11.01 |
Swift ) 웹뷰 Status Code 테스트, 에러처리 stub - EEYatHo iOS (0) | 2022.06.17 |