Collection Types
- Array: 順序を持つ値のcollection
- Set: 順序を持たないuniqueな値のcollection
- Dictionary: 順序を持たないkeyとvalueの関連のcollection
Mutability of Collections(コレクションの可変性)
- コレクションを生成して変数に代入した場合、生成されるコレクションは可変
- コレクションを生成後にアイテムを追加、削除、変更してコレクションを変更することができる
Arrays
Array Type Shorthand Syntax
- SwiftでのArrayのtypeは、
Element
がArrayに格納できる値のtypeとしたとき、Array<Element>
と記述する -
[Element]
と簡略して書くこともできる - 後者の方が望ましい
Creating an Empty Array
var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
// "someInts is of type [Int] with 0 items." と出力
someInts.append(3)
// someInts には Int 型の値が 1 件
someInts = []
// someInts は空配列になったが、型は [Int] のまま
Creating an Array with a Default Value
var threeDoubles = [Double](count: 3, repeatedValue: 0.0)
// threeDoubles は [Double] 型で、[0.0, 0.0, 0.0]
Creating an Array by Adding Two Arrays Together
-
+
でcompatible(一致する)typeの配列を足しあわせて新たな配列を生成できる - 新たな配列のtypeは足しあわせたarrayのtypeから推論
var anotherThreeDoubles = [Double](count: 3, repeatedValue: 2.5)
// anotherThreeDoubles は [Double] 型で、[2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is [Double] と推論され、[0.0, 0.0, 0.0, 2.5, 2.5, 2.5
Creating an Array with an Array Literal
var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList を 2つの初期値で初期化
var shoppingList = ["Eggs", "Milk"]
// type推論によりこのように宣言できる
Accessing and Modifying an Array
-
count
プロパティで配列内の要素の数は確認できる -
isEmpty
プロパティを利用すればcount
プロパティが0かを確認できる -
append
メソッドを呼び出してarrayの末尾に新しい要素を追加することができる -
+=
でarrayが持つ1つ以上の要素を追加できるshoppingList += ["Chocolate Spread", "Cheese", "Butter"]
- 取得したいvalueのindex(subscript syntax)を利用してvalueを取得できる
- subscript syntaxを利用して、指定したindexのvalueを変更できる
- 値の範囲を一度に変更するためにsubscript syntaxを利用することができる
shoppingList[4...6] = ["Bananas", "Apples"]
-
insert(_:)メソッドを用いて、Arrayの指定したindexにvalueをinsertできる
shoppingList.insert("Maple Syrup", atIndex: 0)
` -
removeAtIndex(_:)
メソッドで同様にvalueを削除できる
注意:
+ Arrayの末尾に新しい要素を追加するのにsubscript syntaxhは使えない
+ Arrayの範囲外となるindex valueにアクセス、または変更を試みた場合、実行時エラーが起きる
-
removeLast()
メソッドでArrayの末尾の値を、引数なしで削除できる
Iterating Over an Array(繰り返し処理)
-
for-in
ループで繰り返し処理できる - index valueが必要なときは、
enumerate()
メソッドを使う。enumerate()
メソッドはArray内の各要素をindexとvalueで構成されるtupleでreturnする
for (index, value) in shoppingList.enumerate() {
print("Item \(index + 1): \(value)")
}
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas
Sets
Hash Values for Set Types
- Setに格納するためには
hashable
であることが必要 - hash valueは、例えば
a == b
の実行結果がa.hashValue == b.hashValue
と同じになるように、すべてのオブジェクトを平等に比較するためにInt value
Set Type Syntax
-
Set<Element>
と記述。簡略な方法はない
Creating and Initializing an Empty Set
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// "letters is of type Set<Character> with 0 items." と出力
letters.insert("a")
// letters には Character 型の値が 1 件
letters = []
// letters は空集合になったが、型は Set<Character> のまま
Creating a Set with an Array Literal
- SetをArrayリテラルから推論することはできないため、type
Set
は明示的に宣言する必要がある
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres を 3 件の初期値で初期化
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
// 要素のtypeは宣言しなくてもok
Accessing and Modifying a Set
-
count
,isEmpty
,insert(_:)
,remove(_:)
,removeAll()
,contains(_:)
などメソッドある
Iterating Over a Set
-
for-in
ループで繰り返し処理できる -
Set
typeは順序を持たないので集合内のvalueを特定の順に繰り返し処理したいときはsort()
メソッドを使用する
for genre in favoriteGenres.sort() {
print("\(genre)")
}
// Classical
// Hip hop
// Jazz
Performing Set Operations
-
intersect(_:)
: 共通要素 -
exclusiveOr(_:)
: どちらかしかにない要素 -
union(_:)
: 和集合 -
subtract(_:)
: 取り除く
Set Membership and Equality
包含関係を示す(部分集合か真部分集合か)メソッドがある
Dictionaries
- 辞書は順番を持たないcollection
- 各valueはuniqueなkeyで関連付けられ辞書内でのvalueのidとなる
Dictionary Type Shorthand Syntax
-
Dictionary<Key, Value>
と記述。 - 簡略化すると
[Key: Value]
Dictionaryは型推論コストが高いので簡略に書きたい。
Creating an Empty Dictionary
var namesOfIntegers = [Int: String]()
namesOfIntegers = [:]
// namesOfIntegers は再び [Int: String] 型の空辞書
Creating a Dictionary with a Dictionary Literal
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
// 同じtypeのKeyとvalueを持つDictionary Literalで初期化する場合はtypeを記述する必要ない
Accessing and Modifying a Dictionary
- 基本配列と同様
- 特定のkeyに関連するvalueを変更するためにはsubsctript syntaxを利用する
airports["LHR"] = "London Heathrow"
// "LHR" の値は "London Heathrow" に変更されている
- accessするときはkeyに関連するvalueがない可能性もあるのでoptional valueがreturnする
- Dictionaryからkeyとvalueのpairを削除したいときはkeyに
nil
を代入すれば良い - もしくは
removeValueForKey(_:)
で削除
Iterating Over a Dictionary
- Dictionary内のkeyとvalueのペアをfor-inループで繰り返し処理可能
- 辞書の各項目はarrayと同様にtupleでreturnされる
-
.keys
でkeyを繰り返し処理するためのcollectionを取得できる -
.values
でvalueを繰り返し処理するためのcollectionを取得できる
let airportCodes = [String](airports.keys)
// airportCodes は ["YYZ", "LHR"]
let airportNames = [String](airports.values)
// airportNames は ["Toronto Pearson", "London Heathrow"]
Control Flow
For-In Loops
- シーケンスの各値が必要ない場合は
_
でおk
While Loops
while condition { // 条件がtrueなら繰り返す
statements
}
Repeat-While
repeat {
statements
} while condition // 条件がfalseになるまで繰り返す
Conditional Statements
If
if conditions1 {
hogehoge
} else if conditions2 {
fugafuga
} else {
hahahaha
}
Switch
switch some value to consider {
case value 1:
respond to value 1
case value 2,
value 3:
respond to value 2 or 3
default:
otherwise, do something else
}
- 最初に一致したswitch caseを完了後すぐにswitch文全体の実行は終了される(breakなしで)
- 各caseの本体には、少なくとも一つの実行文が必要
- 全てのcaseを網羅していたら
default:
は必要ない。defaultはない方が望ましい
Value Bindings
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// "on the x-axis with an x value of 2" と出力
Where
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// "(1, -1) is on the line x == -y" と出力
Control Transfer Statements(条件転送文)
Continue
- 実行中のループを停止して、次の周回の初めから再開します。
- ループを出てしまうのではなく、現在の周回を完了したということです。
Break
Break in a Loop Statement
- ループの実行を即座に終了し、ループの閉じ括弧 (}) の直後のコードに制御を転送します。
Break in a Switch Statement
- switch 文の実行を即座に終了し、switch 文の閉じ括弧 (}) の直後のコードに制御を転送します。
Fallthrough
- caseの処理が終わったらdefault caseの処理をする
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)
// "The number 5 is a prime number, and also an integer." と出力
Labeled Statements
- ループ文または条件文にラベルを付けることができる
- 複数ネストされたループがある場合、continue 文が影響するループを明確にできるようにするため
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// 最後のマスに移動し、ゲーム終了
break gameLoop
case let newSquare where newSquare > finalSquare:
// 最後のマスを越えたため、サイコロを振り直す
continue gameLoop
default:
// マスを移動し、上下移動を適用
square += diceRoll
square += board[square]
}
}
print("Game over!")
Early Exit
- guard 文は、if文と同様に、式のBool値によってコードを実行する。
- guard 文の後のコードが実行されるには、guard 文の条件が true である必要があります。
- if 文と異なり、guard 文には「常に」else 節があり、条件がtrueでない場合にelse節内のコードが実行されます。
メリット
- guard 文を使用することは、同じチェックをif文で実施することと比較して、コードの可読性が向上する
- 実行するコードをelseブロックで囲って記述する必要がなく、条件に反した場合の処理コードを条件のすぐ後に記述することができる
Checking API Availability
- API の可用性チェックをビルトインでサポートしており、デプロイ対象で利用できない API を誤って利用してしまうことがないようにできる
- Swift は、利用不可能なAPIを利用しようとした場合、コンパイル時にエラーを報告する
if #available(iOS 9, OSX 10.10, *) {
// iOS の iOS 9 API を使用、および OS X の OS X v10.10 API を利用
} else {
// それより前の iOS および OS X の API にフォールバック
}
if #available(platform name version, ..., *) {
statements to execute if the APIs are available
} else {
fallback statements to execute if the APIs are unavailable
}