Swift

Swift The Programming Language Collection Types & Control Flow まとめ

More than 3 years have passed since last update.


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リテラルから推論することはできないため、typeSetは明示的に宣言する必要がある

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ループで繰り返し処理できる


  • Settypeは順序を持たないので集合内の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
}