Skip to content

Code Convention

Hyungyu Kim edited this page Nov 13, 2021 · 9 revisions

StyleShare - swift style guide 을 기본으둜 따라간닀.

StyleShare 의 Swift Style Guide λ₯Ό 기본으둜 ν•΄μ„œ μΆ”κ°€ν•˜κ±°λ‚˜ μˆ˜μ •ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

SwiftLint λ₯Ό ν†΅ν•΄μ„œ ν†΅μΌμ„±μžˆλŠ” ν΄λ¦°μ½”λ“œλ₯Ό μΆ”κ΅¬ν•©λ‹ˆλ‹€.

➑️ 넀이밍

πŸ“Œ 클래슀

  • UpperCamelCase μ‚¬μš©

πŸ“Œ ν•¨μˆ˜

  • lowerCamelCase μ‚¬μš©ν•˜κ³  λ™μ‚¬λ‘œ μ‹œμž‘

@IBAction

- λ™μ‚¬μ›ν˜• + λͺ©μ μ–΄ ex) touchBackButton

λ·° μ „ν™˜

- pop, push, present, dismiss
- 동사 + To + λͺ©μ μ§€ λ·° (λ‹€μŒμ— 보일 λ·°)
- dismissλŠ” dismiss + ν˜„μž¬ λ·°

register

- register + λͺ©μ μ–΄ ex) registerXib

μ„œλ²„ν†΅μ‹ 

- μ„œλΉ„μŠ€ν•¨μˆ˜λͺ… + WithAPI ex) getListWithAPI

μ• λ‹ˆλ©”μ΄μ…˜

- λ™μ‚¬μ›ν˜• + λͺ©μ μ–΄ + WithAnimation ex)showButtonsWithAnimation

델리게이트

delegate λ©”μ„œλ“œλŠ” ν”„λ‘œν† μ½œλͺ…μœΌλ‘œ λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό ꡬ뢄

쒋은 예:

protocol UserCellDelegate {
  func userCellDidSetProfileImage(_ cell: UserCell)
  func userCell(_ cell: UserCell, didTapFollowButtonWith user: User)
}

λ‚˜μœ 예:

protocol UserCellDelegate {
  func didSetProfileImage()
  func followPressed(user: User)

  // `UserCell`μ΄λΌλŠ” ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•  경우 컴파일 μ—λŸ¬ λ°œμƒ
  func UserCell(_ cell: UserCell, didTapFollowButtonWith user: User)
}

πŸ“Œ λ³€μˆ˜, μƒμˆ˜

  • lowerCamelCase μ‚¬μš©

πŸ“Œ μ—΄κ±°ν˜•

  • 각 case μ—λŠ” lowerCamelCase μ‚¬μš©

πŸ“Œ μ•½μ–΄

μ•½μ–΄λ‘œ μ‹œμž‘ν•˜λŠ” 경우 μ†Œλ¬Έμžλ‘œ ν‘œκΈ°, κ·Έ μ™Έμ—λŠ” 항상 λŒ€λ¬Έμž

// 쒋은 예:
  let userID: Int?
  let html: String?
  let websiteURL: URL?
  let urlString: String?
  
// λ‚˜μœ 예:
  let userId: Int?
  let HTML: String?
  let websiteUrl: NSURL?
  let URLString: String?

πŸ“Œ 기타 넀이밍

  • μ„€μ • λ©”μ„œλ“œλŠ” set~ 으둜 μ‹œμž‘. ex) setUI, setData, setList

https://github.com/SOPT-29th-Joint-Seminar-10/Client-iOS/wiki/_new

➑️ 파일λͺ…(μ•½μ–΄μ‚¬μš©)

  • ViewController β†’ VC
  • TableViewCell β†’ TVC
  • CollectionViewCell β†’ CVC

➑️ μ½”λ“œ λ ˆμ΄μ•„μ›ƒ

λ“€μ—¬μ“°κΈ° 및 띄어쓰기

  • λ“€μ—¬μ“°κΈ°μ—λŠ” νƒ­(tab) λŒ€μ‹  2개의 spaceλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

  • 콜둠(:)을 μ“Έ λ•Œμ—λŠ” 콜둠의 였λ₯Έμͺ½μ—λ§Œ 곡백을 λ‘‘λ‹ˆλ‹€.

    let names: [String: String]?
  • μ—°μ‚°μž μ˜€λ²„λ‘œλ”© ν•¨μˆ˜ μ •μ˜μ—μ„œλŠ” μ—°μ‚°μžμ™€ κ΄„ν˜Έ 사이에 ν•œ μΉΈ λ„μ–΄μ”λ‹ˆλ‹€.

    func ** (lhs: Int, rhs: Int)

πŸ“Œ μ€„λ°”κΏˆ

  • ν•¨μˆ˜ μ •μ˜κ°€ μ΅œλŒ€ 길이λ₯Ό μ΄ˆκ³Όν•˜λŠ” κ²½μš°μ—λŠ” μ•„λž˜μ™€ 같이 μ€„λ°”κΏˆν•©λ‹ˆλ‹€.

    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 ꡬ문 μœ„μ™€ μ•„λž˜μ—λŠ” 곡백이 ν•„μš”ν•©λ‹ˆλ‹€.

    // MARK: Layout
    
    override func layoutSubviews() {
      // doSomething()
    }
    
    // MARK: Actions
    
    override func menuButtonDidTap() {
      // doSomething()
    }

πŸ“Œ μž„ν¬νŠΈ

λͺ¨λ“ˆ μž„ν¬νŠΈλŠ” μ•ŒνŒŒλ²³ 순으둜 μ •λ ¬ν•©λ‹ˆλ‹€. λ‚΄μž₯ ν”„λ ˆμž„μ›Œν¬λ₯Ό λ¨Όμ € μž„ν¬νŠΈν•˜κ³ , 빈 μ€„λ‘œ κ΅¬λΆ„ν•˜μ—¬ μ„œλ“œνŒŒν‹° ν”„λ ˆμž„μ›Œν¬λ₯Ό μž„ν¬νŠΈν•©λ‹ˆλ‹€.

import UIKit

import SwiftyColor
import SwiftyImage
import Then
import URLNavigator

➑️ ν΄λ‘œμ €

  • νŒŒλΌλ―Έν„°μ™€ 리턴 νƒ€μž…μ΄ μ—†λŠ” Closure μ •μ˜μ‹œμ—λŠ”Β () -> Voidλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

    쒋은 예:

    let completionBlock: (() -> Void)?

    λ‚˜μœ 예:

    let completionBlock: (() -> ())? let completionBlock: ((Void) -> (Void))?

  • Closure μ •μ˜μ‹œ νŒŒλΌλ―Έν„°μ—λŠ” κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    쒋은 예:

    { operation, responseObject in
      // doSomething()
    }

    λ‚˜μœ 예:

    { (operation, responseObject) in
      // doSomething()
    }
  • Closure μ •μ˜μ‹œ κ°€λŠ₯ν•œ 경우 νƒ€μž… μ •μ˜λ₯Ό μƒλž΅ν•©λ‹ˆλ‹€.

    쒋은 예:

    ...,
    completion: { finished in
      // doSomething()
    }

    λ‚˜μœ 예:

    ...,
    completion: { (finished: Bool) -> Void in
      // doSomething()
    }
  • Closure ν˜ΈμΆœμ‹œ λ˜λ‹€λ₯Έ μœ μΌν•œ Closureλ₯Ό λ§ˆμ§€λ§‰ νŒŒλΌλ―Έν„°λ‘œ λ°›λŠ” 경우, νŒŒλΌλ―Έν„° 이름을 μƒλž΅ν•©λ‹ˆλ‹€.

    쒋은 예:

    UIView.animate(withDuration: 0.5) {
      // doSomething()
    }

    λ‚˜μœ 예:

    UIView.animate(withDuration: 0.5, animations: { () -> Void in
      // doSomething()
    })

➑️ 주석

μ½”λ“œλŠ” κ°€λŠ₯ν•˜λ©΄ 자체적으둜 λ¬Έμ„œκ°€ λ˜μ–΄μ•Ό ν•˜λ―€λ‘œ, μ½”λ“œμ™€ ν•¨κ»˜ μžˆλŠ” 인라인(inline) 주석은 ν”Όν•œλ‹€.

πŸ“Œ MARK 주석

// MARK: - Properties

// MARK: - @IBOutlet Properties

// MARK: - @IBAction Properties

// MARK: - View Life Cycle

// MARK: - Extensions
> setUI, registerXib, assignDelegate λ“±

// MARK: - Custom Method

// MARK: - @objc Function

// MARK: - Network
> λ„€νŠΈμ›Œν¬ λͺ©μ μ„ 가진 ν•¨μˆ˜λ“€

// TODO: -
> ν•΄μ•Όν•˜λŠ” 것

// FIXME: -
> κ³ μΉ  μ˜ˆμ •

πŸ“Œ 퀡헬프 주석

μ»€μŠ€ν…€ λ² μ„œλ“œ, ν”„λ‘œν† μ½œ, 클래슀의 κ²½μš°μ— 퀡헬프 주석 달기

/// (μ„œλ¨Έλ¦¬ λΆ€λΆ„)
/// (λ””μŠ€ν¬λ¦½μ…˜ λΆ€λΆ„)
class MyClass {
    let myProperty: Int

    init(myProperty: Int) {
        self.myProperty = myProperty
    }
}

/**
summary
- note: μ„€λͺ…

- parameters:
    - property: ν”„λ‘œνΌν‹°

- throws: 였λ₯˜κ°€ λ°œμƒν•˜λ©΄ customError의 ν•œ μΌ€μ΄μŠ€λ₯Ό throw
- returns: "\\(name)λŠ” ~" String
*/
    func printProperty(property: Int) {
        print(property)
    }
  • μ°Έκ³  :

[iOS - swift] 주석 처리, 퀡 ν—¬ν”„ 주석, //, ///

[Swift] Xcode 퀡헬프 및 λ§ˆν¬μ—… 문법

➑️ ν”„λ‘œκ·Έλž˜λ° ꢌμž₯사항

Type Annotation μ‚¬μš©

쒋은 예:

let name: String = "철수"
let height: Float = "10.0"

λ‚˜μœ 예:

let name = "철수"
let height = "10.0"

UICollectionViewDelegate, UICollectionViewDatsource λ“± μ‹œμŠ€ν…œ ν”„λ‘œν† μ½œ

ν”„λ‘œν† μ½œμ„ μ μš©ν•  λ•Œμ—λŠ” extension을 λ§Œλ“€μ–΄μ„œ κ΄€λ ¨λœ λ©”μ„œλ“œλ₯Ό λͺ¨μ•„λ‘‘λ‹ˆλ‹€.

쒋은 예:

final class MyViewController: UIViewController {
  // ...
}

// MARK: - UITableViewDataSource

extension MyViewController: UITableViewDataSource {
  // ...
}

// MARK: - UITableViewDelegate

extension MyViewController: UITableViewDelegate {
  // ...
}

λ‚˜μœ 예:

final class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  // ...
}****

➑️ κΈ°νƒ€κ·œμΉ™

  • self λŠ” μ΅œλŒ€ν•œ μ‚¬μš©μ„Β μ§€μ–‘
  • viewDidLoad() μ—μ„œλŠ”Β ν•¨μˆ˜ν˜ΈμΆœλ§Œ
  • delegate 지정, UIκ΄€λ ¨ μ„€μ • λ“±λ“± λͺ¨λ‘ ν•¨μˆ˜μ™€ 역할에 λ”°λΌμ„œ extension 으둜 λΉΌκΈ°
  • ν•„μš”μ—†λŠ” 주석듀 제거

identifier λž‘ 컬러 폰트