Skip to content

Instantly share code, notes, and snippets.

@taketin
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taketin/fd6d8f425482e5b30af6 to your computer and use it in GitHub Desktop.
Save taketin/fd6d8f425482e5b30af6 to your computer and use it in GitHub Desktop.

Swift Style Guide from raywenderlich.com

命名規則

  • 全てキャメルケースで記述する。
  • モジュールスコープの定数とクラスは開始文字 uppercase.
  • 関数と変数は開始文字 lowercase.
// Preffered
let MaximumWidgetCount = 100

class WidgetContainer {
  var widgetButton: UIButton
  let widgetHeightPercentage = 0.85
}
// Not Preferred
let MAX_WIDGET_COUNT = 100

class app_widgetContainer {
  var wBut: UIButton
  let wHeightPct = 0.85
}
  • 関数と initメソッドは、名前で機能が明確に判断できない場合外部パラメータ名を付け、呼び出し時も用いる。
func dateFromString(dateString: NSString) -> NSDate
func convertPointAt(#column: Int, #row: Int) -> CGPoint
func timedAction(#delay: NSTimeInterval, perform action: SKAction) -> SKAction!

// would be called like this:
dateFromString("2014-03-14")
convertPointAt(column: 42, row: 13)
timedAction(delay: 1.0, perform: someOtherAction)

クラス プレフィックス

  • Swift はモジュールによるネームスペース分割により名前空間の衝突を避ける事ができるので、クラス名にプレフィックスを付けるのではなく、モジュール名でアクセスする。
import MyModule

var myClass = MyModule.MyClass()
  • Swift を Objective-C から利用する場合は、下記の様な記述でプレフィックス付きクラス名を提供する事ができる。
@objc (RWTChicken) class Chicken {
   ...
}

スペーシング

  • 2 spaces の設定を Xcode で行う。
  • ブレースは開く時は文と同じ行で。閉じる時は改行する。
// Preffered
if user.isHappy {
  //Do something
} else {
  //Do something else
}
// Not Preffered
if user.isHappy
{
    //Do something
}
else {
    //Do something else
}
  • メソッド内で空白行を差し込んで機能を見た目に分割しようとする事があると思いますが、多くの場合これはメソッドを分割するリファクタリングが必要なケースです。

コメント

  • 必要であれば、コードの特定の部分が行う理由を説明するコメントを書いても良いが、常に最新の状態に保つか削除する様に気をくばる。
  • インラインコメントは避ける。コード自身が自己文書化されているべきである。
  • ※ ドキュメントを生成するためのコメントは除く

クラスと構造体

どちらを使ったら良いか?

  • 構造体は値型、クラスは参照型である
  • 構造体はアイデンティティを持たないものを定義する。生成した値 A と B は交換可能である。
  • クラスはアイデンティティを持つものを定義する。生成したインスタンス A と B は同一では無い。例えば Person クラスが保持しているプロパティ birthday が A と B で同一だとして、同じ人間では無い。誕生日自体は構造体として定義できるが。
  • 歴史的経緯で AnyObject 型に適合するために構造体がクラスとして定義されているものもある。(NSDate, NSSet など)

定義

  • 各定義については次のように、名前とコロンの間にスペースを入れず、コロンと型名の間にスペースを入れる。var x: Int
  • 共通の目的/コンテキストがある場合、単一の行に複数の変数や構造を定義する。var x: Int, y: Int
  • プロパティオブザーバやゲッター、セッターはインデントします。
  var diameter: Double {
    get {
      return radius * 2
    }
    set {
      radius = newValue / 2
    }
  }
  • アクセス修飾子のデフォルトは internal であり、変更しない場合は明示する必要はない。override 時も同様。

Self の使い方

  • self はコンパイラが必要とする時(引数とプロパティ名が同一の場合、closure 内でのパラメータ参照)のみ使用する。

プロトコル

  • Protocol を適用する場合、class 宣言に記述するのでは無く、extension を用いる。関連するメソッド定義をシンプルにまとめる事ができる。
// Preffered
class MyViewcontroller: UIViewController {
  // class stuff here
}

// MARK: - UITableViewDataSource
extension MyViewcontroller: UITableViewDataSource {
  // table view data source methods
}

// MARK: - UIScrollViewDelegate
extension MyViewcontroller: UIScrollViewDelegate {
  // scroll view delegate methods
}
// Not Preffered
class MyViewcontroller: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
  // all methods
}

関数

  • 開始ブレースは文と同じ行に書く。
  • シグネチャが長くなる場合は適切な箇所で改行し、インデントを加える。
func reticulateSplines(spline: [Double], adjustmentFactor: Double,
    translateConstant: Int, comment: String) -> Bool {
  // reticulate code goes here
}

クロージャ

  • 可能な限り trailing clusure (末尾クロージャ) を用い、引数に説明的な名称を付ける。
return SKAction.customActionWithDuration(effect.duration) { node, elapsedTime in 
  // more code goes here
}
  • 単一式であれば、暗黙のリターンを用いる。
attendeeList.sort { a, b in
  a > b
}

  • できる限り Swift のネイティブ型を利用します。必要に応じて Objective-C 型へのブリッジを行います。
// Preffered
let width = 120.0                                    //Double
let widthString = (width as NSNumber).stringValue    //String
// Not Preffered
let width: NSNumber = 120.0                                 //NSNumber
let widthString: NSString = width.stringValue               //NSString
  • SpriteKit のコードでは CGFloat を使用していますが、これはあまりにも多くの変換を必要とし、コードが複雑化するためです。

定数

  • 変数は var、定数は let で記述しますが、適切に定義すると var よりもはるかに let の方が多くなる事に気づきます。
  • Tip: この基準を満たすために役立つ方法として、全てを let で宣言し、コンパイラが怒った時だけ var に変更する、というものがあります。

オプショナル

  • ImplicitOptionalValue ! は viewDidLoad で設定されるサブビューを保持するインスタンス変数のみに使用してください。
  • 一度だけアクセスする場合や、複数のオプショナル値が連なっている場合はオプショナルチェーンを使用してください。
self.textContainer?.textLabel?.setNeedsDisplay()
  • アンラップして複数の操作を行った方が効率良い場合は、以下のように Optional Binding 構文 を使う。
if let textContainer = self.textContainer {
  // do many things with textContainer
}
  • オプショナルである事は型で明らかなので、変数や定数名に optionalStringmaybeView といった名前を付けない様にしてください。もともとの意味を隠してしまいます。

構造体のイニシャライザ

  • Swift ネイティブのイニシャライザではなく、従来の CGGeometryコンストラクタ を使用してください。
// Preferred
let bounds = CGRect(x: 40, y: 20, width: 120, height: 80)
var centerPoint = CGPoint(x: 96, y: 42)
// Not Preferred
let bounds = CGRectMake(40, 20, 120, 80)
var centerPoint = CGPointMake(96, 42)
  • CGRectInfinite CGRectNull といったグローバル定数よりも CGRect.infiniteRect CGRect.nullRect といった構造体定数の方が、.zeroRect といった省略系が使えるので良い。

型推論

  • 変数、定数の型は推論に任せる。型の指定は多くの場合必要ありません。
  • 型推論に任せるという事は、以前にも増して説明的な名付けが重要という事です。

糖衣構文

  • 完全なジェネリクス宣言よりも、ショートカット宣言が良いです。
// Preferred
var deviceModels: [String]
var employees: [Int: String]
var faxNumber: Int?
// Not Preferrerd
var deviceModels: Array<String>
var employees: Dictionary<Int, String>
var faxNumber: Optional<Int>

コントロールフロー

  • for文はインクリメントスタイルではなく for - in スタイルが良い。
// Preffered
for _ in 0..<3 {
  println("Hello three times")
}

for (index, person) in enumerate(attendeeList) {
  println("\(person) is at position #\(index)")
}
// Not Preferred
for var i = 0; i < 3; i++ {
  println("Hello three times")
}

for var i = 0; i < attendeeList.count; i++ {
  let person = attendeeList[i]
  println("\(person) is at position #\(i)")
}

セミコロン

  • コード後にセミコロンは書きません。1行には1つの式だけを書いてください。
  • 唯一の例外は for文等のコントロールフローを記述する時ですが、これもできるだけ for-in スタイルで書いてください。
  • NOTE: Swift のセミコロン省略は、一般的に安全では無いと考えられている Javascript のそれと異なります。

言語

  • Apple の API に合わせて、アメリカ英語のスペルを使用してください。
// Preffered
var color = "red"
// Not Preffered
var colour = "red"

スマイリーフェイス

  • スマイリーフェイスは raywenderlich.com の特徴的なスタイルです! :) は中途半端なので使ってはいけません。最大の笑顔を表現するために :] を使用しましょう。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment