⚡ Sangsakala Proxy 🏠 Home
Skip to content

About

StyleShare에서 작성한 Swift 한국어 스타일 가이드

Resources

Stars

0 stars

Watchers

1 watching

Forks

 
 

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 

Repository files navigation

Swift Style Guide

본 문서는 StyleShare 구성원들이 Swift 코드를 이해하기 쉽고 명확하게 작성하기 위한 스타일 가이드입니다. 구성원들의 의사결정에 따라 수시로 변경될 수 있습니다.

Table of Contents

--

공백

  • 들여쓰기에는 탭(tab) 대신 4개의 space를 사용합니다.

  • 모든 파일은 빈 줄(new-line)로 끝나도록 합니다.

  • 띄어쓰기로만 이루어진 라인은 띄어쓰기를 모두 제거합니다.

  • 콜론(:)을 쓸 때에는 콜론의 오른쪽에만 공백을 둡니다.

    let names: [String: String]
  • 연산자 오버로딩 함수 정의에서는 연산자와 괄호 사이에 한 칸 띄어씁니다.

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

줄바꿈

코드 최대 길이는 119자로 제한합니다.

GitHub에서 가로 스크롤 없이 코드를 볼 수 있는 최적의 길이입니다.

클래스 정의가 긴 경우에는 적당한 위치에서 줄바꿈하고, 한 단계 들여쓰기합니다.

class AwesomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIActionSheetDelegate,
    UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning {
    ...
}

함수 정의가 길 때에는 괄호를 기준으로 줄바꿈합니다.

func collectionView(collectionView: UICollectionView,
                    cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    ...
}

func animationControllerForPresentedController(presented: UIViewController,
                                               presentingController presenting: UIViewController,
                                               sourceController source: UIViewController)
                                               -> UIViewControllerAnimatedTransitioning? {
    ...
}

함수 호출 코드가 길 때에는 파라미터 이름을 기준으로 줄바꿈합니다.

let actionSheet = UIActionSheet(
    title: "정말 계정을 삭제하실 건가요?",
    delegate: self,
    cancelButtonTitle: "취소",
    destructiveButtonTitle: "삭제해주세요"
)

파라미터 이름이 없는 첫 번째 파라미터는 첫 줄에 씁니다. 만약 이름이 없는 첫 번째 파라미터가 너무 길다면 줄바꿈해도 무방합니다.

UIView.animateWithDuration(0.25,
    animations: {
        ...
    },
    completion: { finished in
        ...
    }
)

변수 정의가 길 때에는 적당한 위치에서 줄바꿈하고, 한 단계 들여쓰기합니다.

let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier.VeryVeryLongUser)
    as! UserCell

class 내부 코드의 가장 윗줄과 아랫줄에는 공백을 둡니다.

class ProfileViewController: UIViewController {

    var user: User?

}

// MARK: 앞에는 두 줄의 공백을, 뒤에는 한 줄의 공백을 둡니다.

// MARK: - Layout

override func layoutSubviews() {
    ...
}


// MARK: - Actions

override func menuButtonDidTap() {
    ...
}

if let 구문이 길 경우에는 let과 where를 기준으로 줄바꿈합니다.

(각 라인이 엄청나게 길다고 가정해봅시다.)

if let user = self.user,
       name = user.name
 where user.gender == .Female {
   ...
}

네이밍

Class Prefix

Swift에서는 네임스페이스 구분을 위한 Class Prefix를 사용하지 않습니다.

상수(constant)에는 소문자로 시작하는 Camel Case를 사용합니다.

좋은 예:

let maximumNumberOfLines = 3

나쁜 예:

let kMaximumNumberOfLines = 3
let MAX_LINES = 3

약어(abbreviation)는 대문자로 표시합니다.

좋은 예:

let userID: Int?
let HTML: String?
let websiteURL: NSURL?
let URLString: String?

나쁜 예:

let userId: Int?
let html: String?
let websiteUrl: NSURL?
let urlString: String?

함수 이름 앞에 사용되는 get을 지양합니다.

좋은 예:

func nameForUser(user: User) -> String?

나쁜 예:

func getNameForUser(user: User) -> String?

Action 함수의 네이밍은 '주어 + 동사 + 목적어' 형태를 사용합니다.

  • *Tap(눌렀다 뗌)*은 UIControlEvents의 .TouchUpInside에 대응하고, *Press(누름)*는 .TouchDown에 대응합니다.
  • will~은 특정 행위가 일어나기 직전이고, did~는 특정 행위가 일어난 직후입니다.
  • should~는 일반적으로 Bool을 반환하는 함수에 사용됩니다.

좋은 예:

func backButtonDidTap() {
    ...
}

나쁜 예:

func back() {
    ...
}

func pressBack() {
    ...
}

Delegate 메서드는 프로토콜명으로 네임스페이스를 구분합니다.

좋은 예:

protocol UserCellDelegate: NSObjectProtocol {

    func userCellDidSetProfileImage(button: FollowButton)
    func userCell(button: FollowButton, didTapFollowButtonWithUser user: User)
    
}

나쁜 예:

protocol UserCellDelegate: NSObjectProtocol {

    func didSetProfileImage()
    func followPressed(user: User)
    
    // `UserCell`이라는 클래스가 존재할 경우 에러 발생
    func UserCell(button: FollowButton, didTapFollowButtonWithUser user: User)

}

Closure

파라미터와 리턴 타입이 없는 Closure 정의시에는 () -> Void를 사용합니다.

좋은 예:

let completionBlock: (() -> Void)?

나쁜 예:

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

Closure 정의시 파라미터에는 괄호를 사용하지 않습니다.

좋은 예:

{ operaion, responseObject in
    ...
}

나쁜 예:

{ (operaion, responseObject) in
    ...
}

Closure 정의시 가능한 경우 타입 정의를 생략합니다.

좋은 예:

...,
completion: { finished in
   ...
}

나쁜 예:

...,
completion: { (finished: Bool) -> Void in
    ...
}

Closure 호출시 또다른 유일한 Closure를 마지막 파라미터로 받는 경우, 파라미터 이름을 생략합니다.

좋은 예:

UIView.animateWithDuration(0.5) {
    ...
}

나쁜 예:

UIView.animateWithDuration(0.5, animations: { () -> Void in
    ...
})

Closure 호출시 Closure를 유일한 파라미터로 받는 경우, 괄호를 생략해도 됩니다.

let sortedArray = array.sort { ... }
let sortedArray = array.sort() { ... }

간결한 Closure 호출시 파라미터와 return 구문을 생략합니다.

좋은 예:

let sortedArray = array.sort { $0 > $1 }

나쁜 예:

let sortedArray = array.sort { obj1, objc2 in
    return obj1 > obj2
}

클래스

UI 개발에 사용되는 상수들은 클래스 내부의 struct에서 관리합니다.

재사용성과 유지보수 측면에서 큰 향상을 가져옵니다. CGFloatLiteral과 SwiftyColor를 사용해서 코드를 단순화시킵니다.

class ProfileView: UIView {

    struct Metric {
        static let profileImageViewLeft = 10.f
        static let profileImageViewRight = 10.f
        static let nameLabelTopBottom = 8.f
        static let bioLabelTop = 6.f
    }
    
    struct Font {
        static let nameLabel = UIFont.boldSystemFontOfSize(14)
        static let bioLabel = UIFont.boldSystemFontOfSize(12)
    }
    
    // SwiftyColor에서 제공하는 Color Operator를 사용합니다.
    struct Color {
        static let nameLabelText = 0x000000~
        static let bioLabelText = 0x333333~70%
    }
    
    ...

}

이렇게 선언된 상수들은 다음과 같이 사용될 수 있습니다:

self.profileImageView.frame.origin.x = Metric.profileImageViewLeft
self.nameLabel.font = Font.nameLabel
self.nameLabel.textColor = Color.nameLabelText

클래스 내부에서는 self를 명시적으로 사용합니다.

구조체

구조체를 생성할 때에는 Swift 구조체 생성자를 사용합니다.

좋은 예:

let frame = CGRect(x: 0, y: 0, width: 100, height: 100)

나쁜 예:

let frame = CGRectMake(0, 0, 100, 100)

타입 선언

타입 선언은 필요한 경우에만 사용합니다.

좋은 예:

let name = "Suyeol Jeon"

나쁜 예:

let name: String = "Suyeol Jeon"

Array<T>와 Dictionary<T: U> 보다는 [T], [T: U]를 사용합니다.

좋은 예:

var messages: [String]?
var names: [Int: String]?

나쁜 예:

var messages: Array<String>?
var names: Dictionary<Int, String>?

Control Flow

중첩된 if let 구문은 하나로 합쳐서 사용합니다.

좋은 예:

if let user = self.user, name = user.name {
   ...
}

나쁜 예:

if let user = self.user {
    if let name = user.name {
        ...
    }
}

중첩된 if let과 if 구문은 if let...where 구문으로 줄여서 사용합니다.

좋은 예:

if let user = self.user where user.gender == .Female {
    ...
}

나쁜 예:

if let user = self.user {
    if user.gender == .Female {
        ...
    }
}

주석

문서화를 위한 주석에는 /// 을 사용합니다.

/// 사용자 프로필을 그려주는 뷰
class ProfileView: UIView {

    /// 사용자 닉네임을 그려주는 라벨
    var nameLabel: UILabel!

}

// MARK:를 사용해서 연관된 코드를 구분짓습니다.

Objective-C에서 제공하는 #pragma mark와 같은 기능으로, 연관된 코드와 그렇지 않은 코드를 구분할 때 사용합니다.

// MARK: - Init

override init(frame: CGRect) {
    ...
}

deinit {
    ...
}


// MARK: - Layout

override func layoutSubviews() {
    ...
}


// MARK: - Actions

override func menuButtonDidTap() {
    ...
}

기타

import는 위부터 ABC순으로 작성합니다.

import Alamofire
import SwiftyColor
import SwiftyModel
import JLToast
import UIKit
import UINavigationItem_Margin
import UITextView_Placeholder

라이센스

본 스타일 가이드 문서는 CC-By 3.0 라이센스를 따릅니다. 자세한 내용은 http://creativecommons.org/licenses/by/3.0/ 링크를 참조해주세요.

About

StyleShare에서 작성한 Swift 한국어 스타일 가이드

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors