宣言 (declarations)
クラス、変数、定数、メソッド、関数などの宣言部分で使用する予約語class
クラスの宣言や、メソッドやメンバ変数の前に指定することでクラスメソッド、クラス変数の宣言をします。 class のインスタンスは参照型です。 (swift での参照はC言語のポインタと似たものですが、C言語のように直接アドレスを指しているのではありません。そのため、*
は不要です。)
class Sample {
var member = 1
}
let a = Sample()
let b = a
a === b // -> true (指すものは同じ)
a.member = 2
b.member // -> 2
deinit
デストラクタの宣言をします。これは class でのみ有効です。(struct には実装できません)
スーパークラスの 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
定義済みのクラス、構造体、プロトコル、列挙体に対して振る舞いを追加します。func
メソッドまたは関数の宣言をします。import
モジュールを読み込みます。init
コンストラクタを宣言します。inout
メソッドまたは関数の引数の前に宣言します。 その引数には参照が渡されるようになります。class SampleClass {}
func inoutSampleForClass(inout sampleClass: 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(inout a: Int) {
a = 100
}
func withoutInoutSample(var a: Int) {
a = 100
}
var varInt = 1
// inout なし
withoutInoutSample(varInt)
varInt // => 1
// inout あり
inoutSample(&varInt)
varInt // => 100
internal
let
定数を宣言します。 関連: varoperator
独自の演算子を定義します。 演算子として採用できる文字については規定があります。詳細は iOS Developer Library の Language Reference > Lexical Structure > Operators をご覧ください。 関連: prefix, postfix, infixprefix operator ☁ {}
prefix func ☁ (inout a: Int) -> Int {
a *= a
return a
}
postfix operator *** {} // 複数文字列も可能
postfix func *** (inout a: 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
private
protocol
プロトコルを宣言します。public
アクセス修飾子の一種です (クラス、変数、定数、メソッド、関数の公開範囲の指定) 同じターゲット(モジュール)外からアクセス可能になります。ライブラリなどで API として公開するものに指定します。 関連: private, internalstatic
static 変数やstatic メソッドを宣言します。struct
構造体を宣言します。subscript
クラスや構造体に [] を実装します。 Objective-C の場合についてはクラスに [], {} を実装するに書いてみました。class SubscriptSample {
var hoge: AnyObject?
subscript(index: Int) -> String {
get {
return "Int もらいました"
}
set {
hoge = newValue
}
}
subscript(index: String) -> String {
get {
return "String もらいました"
}
// setter なくても良いです
}
subscript(index: AnyObject?) -> String {
return "何かもらいました"
}
}
let subscriptSample = SubscriptSample()
var optionalSample: Int? = 1;
subscriptSample[3] // => "Int もらいました"
subscriptSample["a"] // => "String もらいました"
subscriptSample[nil] // => "何かもらいました"
subscriptSample[optionalSample] // => "何かもらいました"
typealias
型の別名を宣言
typealias IntAlias = Int
typealias Point = (Int, Int)
protocol 内で associated type (付属型) の宣言(Swift2.1まで)
Swift2.2 からは associatedtype がこの役割となります。この場面での typealias は Swift2.2 から警告、Swift3 から使用不可となります
protocol SampleProtocol {
typealias AssociatedType // 付属型を宣言します
func sampleFunc(param :AssociatedType) -> AssociatedType
}
struct SampleStruct: SampleProtocol {
typealias AssociatedType = Int // 付属型の型を決めます
func sampleFunc(param: AssociatedType) -> AssociatedType {
return param + param
}
}
参考:
The Swift Programming Language (Language Reference -> Declaration -> Type Alias Declaration)
The Swift Programming Language (Language Reference -> Declaration -> Protocol Associated Type Declaration)
associatedtype
(Swift2.2から)
associated type (付属型) の宣言をします。
(Swift2.1までは typealias の役割でした)
protocol SampleProtocol {
associatedtype AssociatedType // 付属型を宣言します
func sampleFunc(param :AssociatedType) -> AssociatedType
}
struct SampleStruct: SampleProtocol {
func sampleFunc(param: Int) -> Int { // 付属型が Int であると決定されます
return param + param
}
}
var
変数を宣言します。Keywords used in statements
break
switch 文やループから抜けます。 for, while の前にラベルをつけることで抜けるブロックを指定できます。 詳細: document の Control Flow -> Labeled Statementsvar i = 0
firstLoop: while true {
print("first loop: \(i)")
while true {
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 {
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 defer keyword in Swift 2: try/finally done right)
func deferSample() {
let file = openFile("sample.txt")
defer { closeFile(file) } // 関数から抜ける時に閉じる
// 処理
}
deferSample()
do
スコープを作成します。 catchを繋げることで、スコープ内で発生した例外をcatch文で処理することができます。 関連: catch, tryelse
条件分岐で使用します。 また、guard文では文法上必須となります。 関連: if, guardfallthrough
switch 文の中で、次の case 文も評価します。 swift では、break を書かなくてもマッチした case の部分の処理をした後 swich 文を抜けます。 fallthrough を記述しておくとその下の処理も行われます。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
for
下記の2種類の繰り返し構文を記述できます。
for var i = 0; i < 10; i++ {
// 処理
}
for i in 1...10 {
// 処理
}
for _ in 1...10 {
// 処理
}
guard
変数または定数が条件に一致するか評価し、一致していない場合、続く else のブロックが実行されます。 このブロックの中では必ず以下のいづれかを使用し、guard が記述されているスコープを抜けなくてはいけません。func guardSample1(value: Int?) -> String {
guard let value = value where 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
if
続く条件を評価し、一致した(true)場合ブロック内を実行します。 unwrap する場合にも使用します。この構文を Optional binding と言います。詳細はこちら ([Swift] Optional 型についてのまとめ Ver2) に解説されていて分かりやすかったです。func ifLetSample(value: Int?) {
if let a = value {
value is AnyObject! // => false
a is AnyObject! // => true (a はアンラップされています)
// 処理
}
// 処理
}
in
文脈によって下記のように意味が変わります。
- クロージャのボディの開始箇所を表します
- for ~ in の形で取り出す要素の配列を指定します
関連: for
repeat
C言語等の言語における
do {...} while(...)
return
返り値を返します。 返り値は下記の2パターンです。 ●要素が一つの場合はその要素 ●それ以外の場合は tuple Swift では@noreturn 属性のメソッド・関数以外は必ず値を返すという決まりがあります。 そのため、void 関数・メソッドも空の tuple を返します。func sample() {
return
}
var a = sample() // -> ()
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
catch
例外が投げられた際にブロック内が実行されます。
dynamicType
実行時にインスタンスからメタタイプを取得します。
class SomeBaseClass {
required init() {}
}
class SomeSubClass: SomeBaseClass {
}
let someInstance: SomeBaseClass = SomeSubClass()
let runTimeInstance = someInstance.dynamicType.init()
runTimeInstance is SomeSubClass // -> true
false
Bool 型の値で偽を表します。
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
値が空であることを表します。
Optional.None == nil // -> true
rethrows
引数にとったクロージャが投げた例外をさらに投げます。
func sample(callback: () throws -> Int) rethrows {
try callback()
}
super
親クラスを返します。self
●インスタンスメソッド内などで単独で使用した場合、インスタンス自身を返します ●expression (式) に対して呼び出した場合、式が評価された値が返ります ●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 は自身の型を返しています)
Self
自身の型を返します。throw
例外を投げます。throws
メソッド、関数の宣言部に書き、例外が投げられる可能性があることを示します。true
Bool 型の値で真を表します。try
例外が投げられる可能性のある関数・メソッドを実行します。__COLUMN__
__COLUMN__ が評価された場所の列番号 (Int) swift3 から 使用不可#column
#column が評価された場所の列番号 (Int)__FILE__
__FILE__ が評価された場所のファイル名 (String) swift3 から 使用不可#file
#file が評価された場所のファイル名 (String) swift2.2 から使用可能__FUNCTION__
__FUNCTION__ が評価された場所の関数・メソッドの名前 (String) swift3 から 使用不可#function
#function が評価された場所の関数・メソッドの名前 (String) swift2.2 から使用可能__LINE__
__LINE__ が評価された場所の行番号 (Int) swift3 から 使用不可#line
#line が評価された場所の行番号 (Int) swift2.2 から使用可能特定の文脈でのみ予約語として使用
associativity
左右に値を取る演算子を宣言した際に、優先度、結合方向を指定します。 指定できる値は下記の3種類です。infix operator <#operator name#> {
precedence <#precedence level#>
associativity <#left | right | none#>
}
infix operator *** {
precedence 100
associativity none
}
infix operator +++ {
precedence 100
associativity none
}
func *** (left: Int, right: Int) -> Int {
return left * right
}
func +++ (left: Int, right: Int) -> Int {
return left + right
}
1 +++ 1 *** 1
/*
error: non-associative operator is adjacent to operator of same precedence
1 +++ 1 *** 1
^
*/
関連: left, right, none, operator, precedence
convenience
init の前に記述することで、convenience initializer を宣言します。
関連: init
dynamic
Objective-C のランタイムを使用して値にアクセスします。
dynamic <#var | let #> <# name #>
didSet
final
継承を不可にします。get
computed property として宣言されたものが呼び出されたときの処理を宣言します。infix
左右に被演算子をとる演算子の処理を定義します。infix operator ☁ {}
func ☁ (left: Int, right: Int) -> Int {
return left + right
}
1 ☁ 2 // => 3
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
nonmutating
値型のインスタンスメソッドが自身に変更を加えないことを宣言します。 使い所: computed property 内で定義する set はデフォルトで mutating になります。iOS の API 内では下記のように setter の mutaing を無効にするために使用しています。var value: Value { get nonmutating set }
optional
プロトコルの実装を任意に指定します。
override
親クラスのメソッドやプロパティを上書きする際に宣言します。
postfix
独自の後置演算子を定義します。
postfix operator *** {}
postfix func *** (inout a: Int) -> Int {
a *= a
return a
}
var hoge = 4
hoge*** // => 16
precedence
左右に被演算子をとる演算子の優先度 (0 ~ 255) を指定します。
infix operator <#operator name#> {
precedence <#0 ~ 255#>
associativity <#left | right | none#>
}
infix operator *** {
precedence 100
associativity none
}
infix operator +++ {
precedence 200
associativity none
}
func *** (left: Int, right: Int) -> Int {
return left * right
}
func +++ (left: Int, right: Int) -> Int {
return left + right
}
1 +++ 1 *** 0 // => 0
関連: operator, associativity
prefix
独自の前置演算子を定義します。
prefix operator *** {}
prefix func *** (inout a: Int) -> Int {
a *= a
return a
}
var hoge = 4
***hoge // => 16
Protocol
Protocol のメタタイプを取得します。
let protocolMetatype: SampleProtocol.Protocol = SampleProtocol.self
required
サブクラスにイニシャライザのオーバーライドを強制します。 また、サブクラスでそのイニシャライザをオーバーライドする際には override ではなく、required を指定します。right
演算子を定義した際に、右結合を指定します。 詳細: このページの associativity 項 関連: associativity, operator, left, noneset
computed property のセッターを宣言します。Type
クラス、構造体、列挙体のメタタイプを取得します。class Sample {
required init() {}
}
let metatype: Sample.Type = Sample.self
let instance = metatype.init()
unowned
リテインカウントを増やさずに参照を保持します。 weak と違い、参照している値が破棄されないことを前提とします。 nil になった場合は落ちます。 関連: weakweak
リテインカウントを増やさずに参照を保持します。 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