他バージョン
参考
ドキュメントから漏れている予約語もあるため、下記情報を統合してカウントしています。
- The Swift Programming Language (Swift 4) Lexical Structure
- The Swift Programming Language (Swift 4) Summary of the Grammar
- https://github.com/apple/swift/include/swift/Syntax/SyntaxKinds.def
宣言 (declarations)
クラス、変数、定数、メソッド、関数などの宣言部分で使用する予約語
class
場所によって意味が異なります。
- クラスの宣言や、メソッドやプロパティの前に指定することでクラスメソッド、クラスプロパティの宣言をします。
class Sample {
var member = 1
}
let a = Sample()
let b = a
a === b // -> true (指すものは同じ)
a.member = 2
b.member // -> 2
- プロトコルで、適用先をクラスだけに制限したいときにも使います。
protocol SampleProtocol : class {
}
class Sample : SampleProtocol {
}
deinit
デストラクタの宣言をします。これは class でのみ有効です。
スーパークラスの deinit はサブクラスの deinit 実行後に自動的に呼ばれます。
class SuperClass {
deinit { print("Super Class's deinit is called") }
}
class SubClass: SuperClass {
deinit { print("Sub Class's deinit is called") }
}
var subClass: SubClass? = SubClass()
subClass = nil
Sub Class's deinit is called
Super Class's deinit is called
enum
列挙型の宣言をします。
extension
定義済みのクラス、構造体、プロトコル、列挙型に対して function または computed property を追加します。
where
で適応する条件を指定できます。
fileprivate
アクセス修飾子の一種です。
同じファイル内からのアクセスが可能です。
関連: public, private, internal, open
参考: The Swift Programming Language # Access Control
func
function の宣言をします。
import
モジュールを読み込みます。
init
コンストラクタを宣言します。
inout
intout 指定された引数として渡された変数は、function 内での変更が適応されます。(表面的には参照渡しに似た動作になります)
具体的には下記の動作をします。
- function の呼び出し時に、引数として与えられた値がコピーされ、そのコピーが function の中で使われます。
- function の終了時に引数として与えられた変数にコピーが代入されます。
class SampleClass {}
func inoutSampleForClass(sampleClass: inout SampleClass?) {
sampleClass = nil
}
func withoutInoutSampleForClass(var sampleClass: SampleClass?) {
sampleClass = nil
}
var sampleClass: SampleClass? = SampleClass()
// inout なし
withoutInoutSampleForClass(sampleClass)
sampleClass // => SampleClass のインスタンス
// inout あり
inoutSampleForClass(&sampleClass)
sampleClass // => nil
func inoutSample(a: inout Int) {
a = 100
}
func withoutInoutSample(var a: Int) {
a = 100
}
var varInt = 1
// inout なし
withoutInoutSample(varInt)
varInt // => 1
// inout あり
inoutSample(&varInt)
varInt // => 100
internal
アクセス修飾子の一種です。
同じモジュール内からアクセスできます。
アクセス修飾子をつけなかった場合、デフォルトで internal
となります。
関連: public, private, open, fileprivate
参考: The Swift Programming Language (Swift 3) # Access Control
let
定数を宣言します。
関連: var
open
アクセス修飾子の一種です。アクセス制限の種類の中で最もアクセス制限の緩い指定です。
外のモジュールからのアクセス、継承・オーバーライドが可能です。
性質上、この制限を指定できるのは class または オーバーライド可能な class member のみです。
public との違いは、継承・オーバーライドの許可範囲 (外のモジュールからの継承・オーバーライド可能性) です。
関連: public, private, internal, fileprivate
参考: The Swift Programming Language # Access Control
operator
独自の演算子を定義します。
演算子として採用できる文字については規定があります。詳細は iOS Developer Library の Language Reference > Lexical Structure > Operators をご覧ください。
関連: prefix, postfix, infix
prefix operator ☁
prefix func ☁ (a: inout Int) -> Int {
a *= a
return a
}
postfix operator *** // 複数文字列も可能
postfix func *** (a: inout Int) -> Int {
a *= a
return a
}
infix operator ☁
func ☁ (left: Int, right: Int) -> Int {
return left + right
}
var hoge = 2
☁hoge // => 4
hoge*** // => 16
1 ☁ 2 // => 3
precedencegroup
左右に被演算子をとる演算子の優先度グループを定義します。
higherThan で、どのグループより優先度が高いか指定できます。lowerThan では、他のモジュールのどのグループより優先度が低いか指定できます。associativity と assignment も指定できます。
infix operator <#operator name#> : <#precedence group name#>
precedencegroup GroupA {
associativity: none
}
precedencegroup GroupB {
higherThan: GroupA
associativity: none
}
infix operator ***: GroupA
infix operator +++: GroupB
func *** (left: Int, right: Int) -> Int {
return left * right
}
func +++ (left: Int, right: Int) -> Int {
return left + right
}
1 +++ 1 *** 0 // => 0
関連: operator, associativity, assignment
private
アクセス修飾子の一種です (型、変数、定数、function の公開範囲の指定)
最も制限の強いアクセス修飾子で、下記の条件を満たす場合のみにアクセスできます。
- 同じファイル内
- 同じ型
class A {
private var privateVar = ""
}
extension A {
func f() {
// ✅OK
print(privateVar)
}
}
class B {
let a = A()
func f() {
// ❗️error: 'privateVar' is inaccessible due to 'private' protection level
a.privateVar
}
}
protocol
プロトコルを宣言します。
public
アクセス修飾子の一種です (クラス、変数、定数、メソッド、関数の公開範囲の指定)
同じターゲット(モジュール)外からアクセス可能になります。open
と異なり、継承は禁止されます。
主に、ライブラリなどで API として公開するものに対して指定します。
関連: private, internal, open
static
static 変数や static function を宣言します。
protocol での宣言時 (下記参照) は class func
と class var
も意味に含みます。
protocol SampleProtocol {
static func staticFuncInProtocol()
static var staticVarInProtocol: Int { get }
}
class Sample {
// `static func staticFuncInProtocol()` can be implemented by `static func` or `class func`
class func staticFuncInProtocol() {}
// ditto
class var staticVarInProtocol: Int { return 1 }
}
struct
構造体を宣言します。
subscript
クラスや構造体に [] を実装します。
Objective-C の場合についてはクラスに [], {} を実装するに書いてみました。
class SubscriptSample {
var hoge: Any?
subscript(index: Int) -> String {
get {
return "Int もらいました"
}
set {
hoge = newValue
}
}
subscript(index: String) -> String {
get {
return "String もらいました"
}
// setter なくても良いです
}
subscript(index: AnyObject?) -> String {
return "何かもらいました"
}
subscript(x: Int, y: Int) -> String {
return "\(x), \(y)"
}
subscript() -> String {
return "nothing"
}
}
let subscriptSample = SubscriptSample()
var optionalSample: Int? = 1;
subscriptSample[3] // => "Int もらいました"
subscriptSample["a"] // => "String もらいました"
subscriptSample[nil] // => "何かもらいました"
subscriptSample[optionalSample] // => "何かもらいました"
subscriptSample[1, 2] // => "1, 2"
subscriptSample[] // => "nothing"
typealias
型の別名を宣言(*1)、または、associated type に対して型を指定(*2)します。
typealias IntAlias = Int
typealias Point = (Int, Int)
protocol P {
associatedtype T
}
struct S: P {
typealias T = Any
}
参考:
The Swift Programming Language (Language Reference -> Declaration -> Type Alias Declaration)
The Swift Programming Language (Language Reference -> Declaration -> Protocol Associated Type Declaration)
associatedtype
associated type (付属型) の宣言をします。
protocol SampleProtocol {
associatedtype AssociatedType // 付属型を宣言します
func sampleFunc(param :AssociatedType) -> AssociatedType
}
struct SampleStruct: SampleProtocol {
func sampleFunc(param: Int) -> Int { // 付属型が Int であると決定されます
return param + param
}
}
参考:
The Swift Programming Language (Language Reference -> Declaration -> Type Alias Declaration)
The Swift Programming Language (Language Reference -> Declaration -> Protocol Associated Type Declaration)
var
変数を宣言します。
Keywords used in statements
break
switch 文やループから抜けます。
for, while の前にラベルをつけることで抜けるブロックを指定できます。
詳細: [document の Control Flow -> Labeled Statements] (https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html)
var i = 0
firstLoop: while true {
print("first loop: \(i)")
while true {
i += 1
print("second loop: \(i)")
switch i {
case 5:
print("break firstLoop")
break firstLoop
default:
break
}
}
}
print("finish: \(i)")
first loop: 0
second loop: 1
second loop: 2
second loop: 3
second loop: 4
second loop: 5
break firstLoop
finish: 5
関連: continue, fallthrough
case
列挙子リストの宣言、switch 文内で条件分岐、switch 文内以外で if, for との併用により、パターンマッチングができます。
let optionalSample: Int? = 1;
let optionalArraySample: [Int?] = [1, 2, nil, 3]
if case let x? = optionalSample {
print("optionalSample: \(x)")
}
for case let x? in optionalArraySample {
print("optionalArraySample: \(x)")
}
optionalSample: 1
optionalArraySample: 1
optionalArraySample: 2
optionalArraySample: 3
参考:
Swift 2: Pattern Matching with “if case”,
The Swift Programming Language (Patterns -> Optional Pattern)
関連: enum
continue
次のループ処理へ移動します。
break と同様にラベルをつけることで移動するループ処理を指定することができます。
var i = 0
firstLoop: while true {
print("first loop: \(i)")
if i != 0 { break }
while true {
i += 1
print("second loop: \(i)")
switch i {
case 5:
print("continue firstLoop")
continue firstLoop
default:
break
}
}
}
print("finish: \(i)")
first loop: 0
second loop: 1
second loop: 2
second loop: 3
second loop: 4
second loop: 5
continue firstLoop
first loop: 5
finish: 5
関連: break, fallthrough
default
switch 文内の条件分岐で、case に当てはまらなかった場合の処理の宣言をします。
関連: switch, case
defer
スコープを抜ける際に実行する処理を記述します。
func deferSample() {
defer {
print("in defer")
}
print("end of scope")
}
deferSample()
end of scope
in defer
参考:
The Swift Programming Language (Statements -> Defer Statement)
The defer keyword in Swift 2: try/finally done right
do
スコープを作成します。
catchを繋げることで、スコープ内で発生した例外をcatch文で処理することができます。
関連: catch, try
else
条件分岐で使用します。
また、guard文では文法上必須となります。
関連: if, guard
fallthrough
switch 文の中で、マッチした case 文の次の case 文または default 文内の処理を実行します。
(厳密には、fallthrough
の所属している case ブロックの中から抜け、所属する case 文の次の case 文または default 文内の処理を実行します)
let a = 1
switch a {
case 1:
print("1")
fallthrough
case 2:
print("2")
default:
print("default")
}
switch (a) {
case 1:
printf("1\n");
case 2:
printf("2\n");
break;
default:
printf("default\n");
}
1
2
補足
下記の補足です。
厳密には、
fallthrough
の所属している case ブロックの中から抜け、所属する case 文の次の case 文または default 文内の処理を実行します。
下記のように、fallthrough
が呼ばれると、即座に case ブロックから抜けます。
そのため、その下の print("1-2")
は実行されません。
switch 1 {
case 1:
defer { print("defer") } // ブロック(スコープ) から抜ける様子を観察
print("1-1")
if true {
fallthrough
}
print("1-2")
case 2:
print("2")
default:
print("default")
}
1-1
defer
2
for
繰り返し処理を記述できます。
for i in 1...10 {
// 処理
}
for _ in 1...10 {
// 処理
}
guard
変数または定数が条件に一致するか評価し、一致していない場合、続く else のブロックが実行されます。
このブロックの中では必ず以下のいずれかを使用し、guard が記述されているスコープを抜けなくてはいけません。
- return
- break
- continue
- throw
- fallthrough
- fatalError 等の
Never
型を返す関数の呼び出し
func guardSample1(value: Int?) -> String {
guard let value = value, value > 10 else {
// この中では必ずスコープを抜ける処理を書きます
return "in else block"
}
// ここからは value がアンラップされ、また、10 より大きいことが保証されます
return "\(value)"
}
guardSample1(nil) // => in else block
guardSample1(10) // => in else block
guardSample1(100) // => 100
func guardSample2(a: String, b: Int?) -> String {
// 複数の変数・定数の評価もできます
guard let intValue = Int(a), let b = b else {
return "in else block"
}
// ここからは b がアンラップされます
return "\(intValue + b)"
}
guardSample2("a", b: 1) // => in else block
guardSample2("1", b: 1) // => 2
guardSample2("1", b: nil) // => in else block
関連: return, break, continue, throw
if
続く条件を評価し、一致した(true)場合ブロック内を実行します。
unwrap する場合にも使用します。この構文を Optional binding と言います。詳細はこちら ([Swift] Optional 型についてのまとめ Ver2) に解説されていて分かりやすかったです。
func ifLetSample(value: Int?) {
if let a = value {
type(of: value) // Optional<Int>.Type
type(of: a) // Int.Type
}
}
in
文脈によって下記のように意味が変わります。
- クロージャのボディの開始箇所を表します
- for ~ in の形で取り出す要素の配列を指定します
関連: for
repeat
C言語等の言語における
do {...} while(...)
の do
の役割です。
関連: while
return
返り値を指定します。
返り値は下記の 2 パターンです。
- 要素が一つの場合はその要素
- それ以外の場合は tuple
func sample() {
return
}
var a = sample() // -> ()
参考: Remove @noreturn attribute and introduce an empty Never type
switch
条件分岐を行います。
switch (1, "a") {
case (1, "b"):
print("1, b")
case (1, _):
print("1, _") // ここがマッチします。 (_ はワイルドカード)
case (1, "a"):
print("1, a") // 上がマッチするので評価されません
}
関連: case
where
マッチングの条件を追加します。
while
下記の2種類の繰り返し構文を記述できます。
while condition {
statements
}
repeat {
statements
} while condition
関連: repeat
Keywords used in expressions and types
as
大きく分けて、2 種類の役割があります。
- キャスト
class A {}
let anyObj: AnyObject = A()
let a = anyObj as! A // AnyObject から A にキャスト
- 型を明示すること
let v = 1 as Double
Any
すべての型のインスタンス (関数型も含む) を表現します。
実態は空の protocol です。
参考:
Type Casting for Any and AnyObject
Import Objective-C id as Swift Any type
catch
例外が投げられた際にブロック内が実行されます。
false
真偽値リテラルの一種で、偽を表します。
is
ある型またはあるプロコトルを実装した型として振る舞えるかどうかを検査します。
1 is Int // -> true
(1, 1) is AnyObject // -> false
(1, 1) is (Int, Int) // -> true
// プロトコルの検査
protocol SampleProtocol { }
class SampleClass: SampleProtocol { }
let sampleClassInstance = SampleClass()
sampleClassInstance is SampleClass // true
sampleClassInstance is SampleProtocol // true
nil
nil リテラルを表します。
Optional.None == nil // -> true
rethrows
引数にとったクロージャが投げた例外を呼び出し元に対して更に投げます。
func sample(callback: () throws -> Int) rethrows {
try callback()
}
super
親クラスを表します。
self
- インスタンスメソッド内などで単独で使用した場合、インスタンス自身を返します
- [expression (式) に対して呼び出した場合、式が評価された値が返ります](#expression (式) に対して呼び出した場合、式が評価された値が返ります )
- [type (型) に対して呼び出した場合、自身の型が返ります](#type (型) に対して呼び出した場合、自身の型が返ります )
インスタンスメソッド内などで単独で使用した場合、インスタンス自身を返します
class Sample {
var a: Int?
func sampleMethod() -> Sample {
a = 1
return self // 自身 (playground 上では Sample と見えますが、プロパティ a が変更されているので上で作成したインスタンスだと確認できます)
}
}
expression (式) に対して呼び出した場合、式がそのまま返ります
<#expression#>.self
(1 + 1).self
の返り値は (1 + 1)
という式と同等です。
(1 + 1).self // (1 + 1)
(1 + 1).self // 2 as Int ではない
// 証明
(1 + 1).self + 1.0 // OK
(1 + 1) + 1.0 // OK
let exp = 1 + 1 // 2 as Int
exp + 1.0 // Error (type mismatch)
type (型) に対して呼び出した場合、自身の型が返ります
<#type#>.self
class Sample {
}
Sample.self // -> Sample.Type
Sample.self.init() // -> Sample のインスタンス (= Sample.self は自身の型を返しています)
参考: The Swift Programming Language (Language Reference -> Expressions -> Postfix Self Expression)
Self
自身の型を返します。
throw
例外を投げます。
throws
メソッド、関数の宣言部に書き、例外が投げられる可能性があることを示します。
true
真偽値リテラルの一種で、真を表します。
try
例外が投げられる可能性のある関数・メソッドを実行します。
Keywords that begin with a number sign (#)
#available
OS 及びそのバージョンによる条件を表現します。
if #available(iOS 10.0, *) {
print("iOS10 or later")
}
#colorLiteral
下記の構文で色を表現するリテラルを記述できます。
#colorLiteral(red: <# expression #>, green: <# expression #>, blue: <# expression #>, alpha: <# expression #>)
型を明示しない場合は、AppKit モジュールをインポートした場合は NSColor 型、UIKit モジュールをインポートした場合は UIColor 型として解釈されます。
#column
#column が評価された場所の列番号 (Int)
#error
記載した行に対するエラーを compile 時に発生させます。
関連: #warning
#if, #else, #elseif, #endif
コンパイル時に指定のコードを含めるか否かを制御します。
#if <# Custom Flag に設定した名前 (設定せずにコンパイルすると無視される) #>
print("DEBUG")
#endif
#if swift(>=3.0)
print("Swift3.0")
#endif
#if arch(arm64)
print("arm64")
#endif
#if os(OSX)
print("OSX")
#endif
#if swift(>=3.0)
print(">=Swift3.0")
#elseif swift(>=2.0)
print(">=Swift2.0")
#else
print("else")
#endif
参考:
#file
#file が評価された場所のファイル名 (String)
#fileLiteral
下記の構文でファイルリテラルを記述できます。
#fileLiteral(resourceName: "<# ファイル名 #>")
型を明示しない場合は URL 型として解釈されます。(Foundation モジュールがインポートされている場合のみ)
また、ファイルが取得できなかった場合、実行時エラーとなります。
参考:
#function
#function が評価された場所の関数・メソッドの名前 (String) を表現します。
#imageLiteral
下記の構文で画像リソースを表現するリテラルを記述できます。
#imageLiteral(resourceName: "<# ファイル名 #>")
型を明示しない場合は、AppKit モジュールをインポートした場合は NSImage 型、UIKit モジュールをインポートした場合は UIImage 型として解釈されます。
#keypath
key や keypath (string literal) を生成します。
class Object: NSObject {
let value = 1
var matryoshka: Object?
}
#keyPath(Object.value) // "value"
#keyPath(Object.matryoshka.value) // "matryoshka.value"
let object = Object()
object.matryoshka = Object()
object.value(forKey: #keyPath(Object.value)) // 1
object.value(forKeyPath: #keyPath(Object.matryoshka.value)) // 1
関連:
#line
#line が評価された場所の行番号 (Int)
#selector
Selector を生成します。
Swift3 から、以前の機能に加え、Objective-C で記述された class のプロパティの getter, setter メソッドの Selector を \#selector
を用いて生成できるようになりました。(以前は \#selector
が対応していなかったため、文字列で指定していました)
@interface ViewController : UIViewController
@property(assign) int num;
@end
#selector(getter: ViewController.num)
#selector(setter: ViewController.num)
参考:
- Using Swift with Cocoa and Objective-C (Swift 3) > Interacting with Objective-C APIs
- Hannibal #selector
#sourceLocation
#line, #file の値を操作します。
(Swift2.2~ での #line の機能の一つが #sourceLocation に分離されました)
(注: 私の環境 [Xcode8.0] では #file が変化することを確認できませんでした)
参考:The Swift Programming Language (Swift 3) > Line Control Statement
#warning
記載した行に対する warning を compile 時に発生させます。
関連: #error
#dsohandle
#line, #filename, #function と同様に、書かれている場所に関する情報を表すキーワードです。
自身が書かれているライブラリがロードされている場所のアドレスを表します。(アドレスなので、他のキーワードと違い、UnsafePointer
型です)
provides an UnsafePointer to the current dynamic shared object (.dylib or .so file)
引用: Modernizing Swift's Debugging Identifiers
特定の文脈でのみ予約語として使用
assignment
左右に値を取る演算子を宣言した際に、Optional Chaining 評価の一連の流れで演算するかを指定します。
true を指定すると、Optional Chaining 評価の一環として演算を行おうとします。false は既定の動作で、Optional Chaining の評価が終わってから、その評価結果と演算します。
precedencegroup OperationFoldedIntoOptionalChaining {
assignment: true
}
precedencegroup OperationOutsideOfOptionalChaining {
assignment: false
}
infix operator ~~ : OperationFoldedIntoOptionalChaining
infix operator ~^ : OperationOutsideOfOptionalChaining
func ~~ (left: Int, right: Int) -> Int {
print("~~")
return left + right
}
func ~^ (left: Int?, right: Int) -> Int {
print("~^")
return left?.advanced(by: right) ?? -1
}
let values = nil as [Int]?
values?.count ~~ 5 // => nil
values?.count ~^ 5 // => -1
/*
~~ 演算は、
最初に `values` の nil 判定、nil でなければ `.count ~~ 5` を評価
values.map { $0.count ~~ 5 } と同等。この例では `~~` 演算は実行されない。
~^ 演算は、最初に `values?.count` を評価、続いて `その結果 ~^ 5` を評価
普通に `(values?.count) ~^ 5` としたのと同等。演算子の既定の動作。
*/
関連: infix, operator, precedencegroup
associativity
左右に値を取る優先度グループを宣言した際に、結合方向を指定します。
指定できる値は下記の 3 種類です。
precedencegroup <#precedence group name#> {
higherThan: <#lower group name#>
associativity: <#left | right | none#>
}
precedencegroup MyAddition {
associativity: none
}
infix operator +++ : MyAddition
infix operator --- : MyAddition
func +++ (left: Int, right: Int) -> Int {
return left + right
}
func --- (left: Int, right: Int) -> Int {
return left - right
}
1 +++ 1 --- 1
/*
error: adjacent operators are in non-associative precedence group 'MyAddition'
1 +++ 1 --- 1
^ ~~~
*/
関連: left, right, none, operator, precedencegroup
convenience
init の前に記述することで、convenience initializer を宣言します。
関連: init
dynamic
Objective-C のランタイムを使用して値にアクセスします。
dynamic <#var | let #> <# name #>
詳細
Objective-C runtime と pure Swift では、呼び出す処理を決定する方法 (method dispatch) が異なります。
Objective-C runtime の場合、実行時に Class に対して問い合わせて実行すべき処理を探していきます (message passing 方式)。
例えば、instance.methodA()
を実行するとき、instance
の持つ Class の情報に対して、"methodA" (呼び出したい function 名) があるか検索します。無かったらその Class の親 Class に対して問い合わせる、なかったら更にその親 Class に、といった処理を実行時に行います。
一方、Swift ではコンパイル時に「型に対してどんな method があるか」という情報を持つ table を作ります。直接呼び出す場合もありますが、継承関係がある場合など、実行時にしか呼び出す処理が決まらない場合はこの table を参照して処理を決定します。重要なのは、この table はコンパイル時に作られてから後で変更できないということです。
Objective-C の場合、Class の情報を書き換えることができます。つまり、実行時に method を増やしたり、method 名を変えたり、処理を入れ替えたりできます。
このような Objective-C の機能を使いたい場合、dynamic
を指定することで、Swift の method table 上には載らず、Objective-C の機構を使って処理するようになります。
didSet
Stored プロパティまたは変数の値が変更された際の処理を宣言します。
final
継承、オーバーライドを不可にします。
get
文脈によって意味が異なります。
computed property 内: プロパティにアクセスした際の処理
class A {
var value: Int {
get { return 1 }
}
}
protocol 内で宣言した場合: 値が取得可能であることの宣言
protocol Sample {
var value: Int { get }
}
class A: Sample {
let value = 1
}
class B: Sample {
var value: Int { return 1 }
}
infix
左右に被演算子をとる演算子の処理を定義します。
infix operator ☁
func ☁ (left: Int, right: Int) -> Int {
return left + right
}
1 ☁ 2 // => 3
関連: operator
indirect
列挙体を列挙子の中で再帰的に使えるようになります。
詳細:
indirect を指定すると付加情報を間接指定するようになります。
間接指定しない場合、付加情報のメモリサイズが確定できないため、その列挙体のために確保するメモリサイズも決まりません。
間接指定する場合、付加情報の場所(アドレス)を保持することになるので列挙体のサイズが確定できるようになります。
indirect enum SampleEnum {
case Num(Int)
case IndirectNum(SampleEnum)
}
SampleEnum.IndirectNum(SampleEnum.IndirectNum(SampleEnum.IndirectNum(SampleEnum.Num(1))))
indirect は列挙子の前に書くことも可能です。
enum SampleEnum {
case Num(Int)
indirect case IndirectNum(SampleEnum)
}
詳細: Swift Programming Language (Enumerations -> Recursive Enumerations)
lazy
遅延評価します。
left
演算子を定義した際に、左結合を指定します。
詳細: このページの associativity 項
関連: associativity, operator, right, none
mutating
値型のオブジェクトにおいて、自身または自身のプロパティを書き換えるインスタンスメソッドに対して宣言する。
enum SampleEnum {
case A, B, C
case a, b, c
mutating func upperCase() {
switch self {
case .a: self = .A
case .b: self = .B
case .c: self = .C
default: break
}
}
}
struct SampleStruct {
var x = 0
mutating func modifyX(x: Int) {
self.x = x
}
mutating func reset() {
self = SampleStruct()
}
}
none
演算子を定義した際に、結合方向を指定しません。
詳細: このページの associativity 項
関連: associativity, operator, right, left
nonmutating
値型のインスタンスメソッドが自身に変更を加えないことを宣言します。
使い所:
computed property 内で定義する set はデフォルトで mutating 指定になります。iOS の API 内では下記のように setter の mutaing を無効にするために使用しています。
var value: Value { get nonmutating set }
optional
プロトコルで指定されたメソッドやプロパティの実装を任意とします。
override
親クラスのメソッドやプロパティをオーバーライドする際に宣言します。
postfix
独自の後置演算子を定義します。
postfix operator ***
postfix func *** (a: inout Int) -> Int {
a *= a
return a
}
var hoge = 4
hoge*** // => 16
prefix
独自の前置演算子を定義します。
prefix operator ***
prefix func *** (a: inout Int) -> Int {
a *= a
return a
}
var hoge = 4
***hoge // => 16
Protocol
Protocol のメタタイプを取得します。
let protocolMetatype: SampleProtocol.Protocol = SampleProtocol.self
関連: Type
required
サブクラスにイニシャライザのオーバーライドを強制します。
また、サブクラスでそのイニシャライザをオーバーライドする際には override ではなく、required を指定します。
right
演算子を定義した際に、右結合を指定します。
詳細: このページの associativity 項
関連: associativity, operator, left, none
set
文脈によって意味が異なります。
computed property 内: プロパティにアクセスした際の処理
class A {
var value: Int {
get { return 1 }
set {}
}
}
protocol 内で宣言した場合: 値を受け渡し可能であることを宣言
protocol Sample {
var value: Int { get set }
}
class A: Sample {
var value = 1
}
class B: Sample {
var value: Int {
get { return 1 }
set {}
}
}
Type
クラス、構造体、列挙体のメタタイプを取得します。
class Sample {
required init() {}
}
let metatype: Sample.Type = Sample.self
let instance = metatype.init()
関連: Protocol
unowned
弱参照の変数を宣言します。
weak と違い、参照している値よりも生存期間が短い、つまり、アクセスした際に参照先が解放されていない (nil となっていない) ことを前提とします。値が破棄されているとランタイムエラーになります。
// unowned = unowned(safe)
unowned var safe: AnyObject
// capture list 内で指定することが多いです
{ [unowned a] in /* ... */ }
関連: weak, unowned(safe), unowned(unsafe)
unowned(safe)
unowned
へ修飾することで参照の動作を指定できます。
unowned
(何も指定しなかった場合)は unowned(safe)
扱いとなります。 関連する指定に unowned(unsafe)
があります。
// unowned = unowned(safe)
unowned(safe) var safe: AnyObject
// capture list 内で指定することが多いです
{ [unowned(safe) a] in /* ... */ }
関連: unowned(unsafe), unowned
unowned(unsafe)
unowned
へ修飾することで参照の動作を指定できます。
unowned
または unowned(safe)
と違い、参照先が解放された際にアクセスしても nil
と評価されません。つまり、解放されている場所を指し続けているためメモリに対して安全なアクセスをしません。
Objective-C の __unsafe_unretained
と同様の動作です。
// like `__unsafe_unretained`
unowned(unsafe) var unsafe: AnyObject
{ [unowned(unsafe) a] in /* ... */ }
関連: unowned(safe), unowned
weak
弱参照の変数を宣言します。
unowned と違い、参照している値が nil になることを許容します。
willSet
stored property または変数への代入が実行される前の処理を記述します。
関連: didSet
その他
_
ワイルドカード
switch (1, "a") {
case (1, "b"):
print("1, b")
case (1, _):
print("1, _") // ここがマッチします。 (_ はワイルドカード)
}
関連: case
引数名の省略
class Sample {
var a: Int
init(param: Int) {
a = param
}
}
let sample = Sample(param: 1)
class Sample {
var a: Int
init(_ param: Int) {
a = param
}
}
let sample = Sample(1)
値を捨てる
let a: Int
(a, _) = (0, 1)
a // -> 0