Swift のツアー


伝統では、新しい言語で最初のプログラムは、スクリーンに "Hello,world !" という言葉を表示するものであるべきだと示唆しています。Swift では、これは、単一の行で行うことができます。


print("Hello, world!")

C や Objective-C でコードを書いた事がある場合、この構文は、おなじみに見えますが、Swift では、コードのこの行は完全なプログラムです。入力/出力、または文字列処理などの機能のために別のライブラリをインポートする必要はありません。グローバルスコープで書かれたコードは、プログラムのエントリポイントとして使用されているので、main() 関数は必要ありません。また、すべての文の末尾にセミコロンを書く必要はありません。


このツアーではは色々なプログラミングのタスクを実行する方法を示すことによって、Swift でコードを書き始めるのに十分な情報を提供します。何かわからない事があっても心配しないで下さい。このツアーで紹介するすべてはこの本の残りの部分で詳しく説明されています。


注意: 最高に経験するために、Xcode でプレイグラウンドとして、この章を開きましょう。プレイグラウンドでは、コードのリストを編集し、すぐに結果を確認することができます。
プレイグラウンドをダウンロード (ここではダウンロードできません。こちら へ。)


単純な値


let で定数を作成し、var で変数を作成します。定数の値はコンパイル時に知っている必要はありませんが、一度だけ、それに値を代入する必要があります。これは、一度決定するが、多くの場所で使用する値の名前に定数を使用できることを意味します。


  1. var   myVariable = 42
  2. myVariable = 50
  3. let  myConstant = 42


定数または変数は、それに代入する値と同じ型を持つ必要があります。ただし、常に明示的に型を記述する必要はありません。定数や変数を作成して値を与えると、コンパイラはその型を推論します。上記の例では、コンパイラは、その初期値が整数であるため myVariable が整数であると推論します。


初期値が十分な情報を提供しない(または初期値が存在しない場合)、変数の後にコロンで区切って、型を書くことで指定して下さい。


  1. let  implicitInteger = 70
  2. let  implicitDouble = 70.0
  3. let  explicitDouble: Double = 70


実験: 明示的な Float 型で 4 の値を持つ定数を作成して下さい。

値は、別の型に暗黙的に変換されることは決してありません。別の型に値を変換する必要がある場合は、明示的に希望の型のインスタンスを作って下さい。


  1. let  label = "The width is "
  2. let  width = 94
  3. let  widthLabel = label + String(width)


実験: 最後の行から String への変換を削除してみてください。どのようなエラーが出ましたか?


文字列内に値を含むさらに簡単な方法があります。括弧内に値を書き、括弧の前にバックスラッシュ(\)を書きます。たとえば、次のように:


  1. let  apples = 3
  2. let  oranges = 5
  3. let  appleSummry = "I have \(apples) apples."
  4. let  fruitSummary = "I have \(apples + oranges) pieces of fruit."


実験: 文字列内に浮動小数点演算を含むように、また挨拶で誰かの名前が含まれるように \() を使用して下さい。


複数の行を取る文字列には 3 つの二重引用符(""") を使います。引用符で囲まれた行の先頭にあるインデントは、閉じた引用符のインデントに一致する限り削除されます。


  1. let quotation = """
  2. I said "I have \(apples) apples."
  3. And then I said "I have \(apples + oranges) pieces of fruit."
  4. """


括弧([ ]) を使用して、配列や dictionary を作成し、括弧内にインデックスまたはキーを書き込むことによって、それらの要素にアクセスします。


  1. var shoppingList = ["catfish", "water", "tulips", "blue paint"]
  2. shoppingList[1] = "bottle of water"
  3. var occupations = [
  4.       "Malcolm": "Captain",
  5.       "Kaylee": "Mechanic",
  6. ]
  7. occupations["Jayne"] = "Public Relations"


空の配列や dictionary を作成するには、イニシャライザーの構文を使用します。


  1. let  emptyArray = [String]()
  2. let  emptyDictionary = [String: Float]()


例えば、関数に引数を渡したり、変数に新しい値を設定すると、[:] のような空の辞書や、[] のような空の配列を作成でき、型の情報が推測できます。


  1. shoppingList = [ ]
  2. occupations = [:]


制御フロー


条件付きを作るため、ifswitch を使い、for-in,while,及び repeat-while をループを作るために使用します。条件やループ変数用のの括弧はオプションです。ボディーの周りの中カッコは必須です。


  1. let  individualScores = [75, 43, 103, 87, 12]
  2. var  teamScore = 0
  3. for  score  in  individualScores {
  4.        if  score > 50 {
  5.           teamScore += 3
  6.        } else {
  7.           teamScore += 1
  8.        }
  9. }
  10. print(teamScore)


if 文では、条件はブール式でなければならず、つまり、if score { ... } のようなコードはエラーであり、ゼロへの暗黙の比較ではありません。


欠落している可能性がある値を処理する場合に iflet とを共に使用できます。これらの値は optional として表されます。optional の値は、値を含むか、値が欠けていることを示すために nil を含みます。optional として値をマークする値の型の後に疑問符(?)を書いてください。


  1. var optionalString: String? = "Hello"
  2. print(optionalString == nil)
  3. var  optionalName: String? = "John Appleseed"
  4. var  greeting = "Hello!"
  5. if  let  name = optionalName {
  6.        greeting = "Hello, \(name)"
  7. }


実験:optionalName を変更して nil にします。何の挨拶をされましたか? optionalNamenil の場合、別の挨拶を設定するために else 節を追加して下さい。


optional の値が nil の場合、条件付きは false であり、括弧内のコードはスキップされます。それ以外の場合、optional の値が開封され、コードブロック内の利用可能な開封値になり、これは let の後の定数に代入されます。


optional の値を処理するもう 1 つの方法は、?? 演算子を使用してデフォルト値を提供することです。optional の値が欠落している場合、デフォルト値が代わりに使用されます。


  1. let nickName: String? = nil
  2. let fullName: String = "John Appleseed"
  3. let informalGreeting = "Hi \(nickName ?? fullName)"


Switch は、どんな種類のデータでもサポートし、広範囲の比較操作をサポートし、それらが等しいかどうかのテストは、整数に限定されません。


  1. let  vegetable = "red pepper"
  2. switch  vegetable {
  3. case  "celery":
  4.         print("Add some raisins and make ants on a log.")
  5. case "cucumber", "watercress":
  6.         print("That would make a good tea sandwich.")
  7. case let x where x.hasSuffix("pepper"):
  8.         print("Is it a spicy \(x)?")
  9. default:
  10.         print("Everything tastes good in soup.")
  11. }


実験: デフォルトのケースを削除してみてください。どのようなエラーが出るでしょう?


定数へのパターンが一致した値を代入するパターンで let がどのように使用できるかに注目しましょう​​。


一致した switch case 内のコードを実行すると、プログラムは switch 文を終了します。実行は、次の case に進みませんので、明示的にそれぞれの case のコードの最後に switch を break する必要はありません。


各キー値のペアで使用する名前のペアを提供することにより、dictionary 内の項目を反復処理するために、for-in を使用して下さい。dictionary は順不同のコレクションであり、そのキー値は任意の順序で反復されます。


  1. let  interestingNumbers = [
  2.        "Prime": [2, 3, 5, 7, 11, 13],
  3.        "Fibonacci": [1, 1, 2, 3, 5, 8],
  4.        "Square": [1, 4, 9, 16, 25],
  5. ]
  6. var largest = 0
  7. for  (kind, numbers)  in interestingNumbers {
  8.        for  number  in  numbers {
  9.            if number > largest {
  10.            largest = number
  11.             }
  12.        }
  13. }
  14. print(largest)


実験:どの数字が最も大きかったかを記録するだけでなく、最も大きかった数字の種類は何だったかを記録するために別の変数を追加してみましょう。


条件が変化するまで、コードのブロックを繰り返すには while を使用します。ループが少なくとも一度実行されることを保証する代わりに、ループの条件を最後にすることができます。


  1. var  n = 2
  2. while  n < 100 {
  3.        n *= 2
  4. }
  5. print(n)
  6. var m  =  2
  7. repeat {
  8.        m *= 2
  9. } while m <  100
  10. print(m)


インデックスの範囲を作るために .. < を使用して、ループでインデックスを維持することができます。


  1. var total = 0
  2. for i in 0..<4 {
  3.         total += i
  4. }
  5. print(total)


.. < を使って、上限の値を省略した範囲を作り、... を使って両方の値を含む範囲を作成します。


関数とクロージャ


関数を宣言するためには、func を使用してください。括弧内の引数のリストと、その名前に従うことで関数を呼び出します。-> を使って関数の戻り値の型からパラメータの名前と型を分離します。


  1. func greet(person: String, day: String) -> String {
  2.        return "Hello \(person), today is \(day)."
  3. }
  4. greet(person:"Bob", day: "Tuesday")


実験: day のパラメータを削除して、特別な今日の昼食の挨拶が含まれるようにパラメータを追加してみましょう。

デフォルトでは、関数は引数用のラベルとして、それらのパラメータ名を使用します。パラメータ名の前にカスタム引数のラベルを書くか、または引数のラベルを使用しないように _ を書きます。


  1. func greet(_ person: String, on day: String) -> String {
  2.         return "Hello \(person), today is \(day)."
  3. }
  4. greet("John", on: "Wednesday")


例えば、関数から複数の値を返すために、複雑な値を作るためにタプルを使用してください。タプルの要素は、名前または数字のいずれかで参照できます。


  1. func  calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
  2.        var  min = scores[0]
  3.        var  max = scores[0]
  4.        var  sum = 0
  5.        for  score  in  scores {
  6.             if  score > max {
  7.                 max = score
  8.             } else if score < min {
  9.                 min = score
  10.             }
  11.             sum += score
  12.        }
  13.        return (min, max, sum)
  14. }
  15. let  statistics = calculateStatistics(scores:[5, 3, 100, 3, 9])
  16. print(statistics.sum)
  17. print(statistics.2)


関数は入れ子にできます。入れ子にされた関数は、外部関数で宣言された変数にアクセスできます。入れ子にされた関数を使用して、コードが長く複雑な関数を整理できます。


  1. func returnFifteen() -> Int {
  2.         var y = 10
  3.         func add() {
  4.                 y += 5
  5.         }
  6.         add()
  7.         return y
  8. }
  9. returnFifteen()


関数は最高級の型です。これは、関数がその値として別の関数を返せることを意味します。


  1. func  makeIncrementer() -> ((Int) -> Int) {
  2.        func  addOne(number: Int) -> Int {
  3.             return 1 + number
  4.        }
  5.        return addOne
  6. }
  7. var increment = makeIncrementer()
  8. increment(7)


関数は、別の関数を、引数の1つとして取ることができます。


  1. func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
  2.        for item in list {
  3.             if condition(item) {
  4.                 return true
  5.             }
  6.        }
  7.        return false
  8. }
  9. func lessThanTen(number: Int) -> Bool {
  10.        return number < 10
  11. }
  12. var numbers = [20, 19, 7, 12]
  13. hasAnyMatches(list: numbers, condition: lessThanTen)


関数は、実際にはクロージャ (後で呼び出すことができるコードのブロック) の特殊なケースです。クロージャのコードは、ネストされた関数で既にこの例を見ていますが、別のスコープにクロージャがある場合でも、クロージャが作成されたスコープ内で使用可能な変数や関数のようなものにアクセスできます。中括弧({})を使用してコードを囲んで、名前のないクロージャを書くことができます。引数を分離し、本体から型を返すように in を使用して下さい。


  1. numbers.map({   (number: Int) -> Int in
  2.        let result = 3 * number
  3.        return result
  4. })


実験: すべての奇数でゼロを返すようにクロージャを書き換えてみましょう。


もっと簡潔にクロージャを書くためにいくつかのオプションがあります。クロージャの型が既に分かっている場合、デリゲートの呼び出し関数のように、そのパラメータ、その戻り値の型、または両方の型を省略できます。単一の文のクロージャは、暗黙のうちにそれらの唯一の文の値を返します。


  1. let mappedNumbers = numbers.map({ number in 3 * number })
  2. print(mappedNumbers)


名前の代わりに、番号で、パラメータを参照することができ、このアプローチは、非常に短いクロージャーでは特に有用です。関数への最後の引数として渡されたクロージャは、括弧の直後に表示されることがあります。クロージャが関数の唯一の引数であるときは、かっこを完全に省略することができます。


  1. let sortedNumbers = sorted(numbers) { $0 > $1 }
  2. print(sortedNumbers)


オブジェクトとクラス


クラスを作成するには、class の後にクラスの名前を続けて使用して下さい。クラス内のプロパティの宣言は、クラスのコンテキストであることを除いては、定数または変数の宣言と同じように書かれます。同様に、メソッドおよび関数の宣言は、同じように書かれます。


  1. class Shape {
  2.        var numberOfSides = 0
  3.        func simpleDescription() -> String {
  4.             return "A shape with \(numberOfSides) sides."
  5.         }
  6. }

実験: let で定数のプロパティを追加して、引数を取る別のメソッドを追加してみましょう。


クラスの名前の後に括弧を書くことによって、クラスのインスタンスを作成します。プロパティとインスタンスのメソッドにアクセスするには、ドット構文を使用します。


  1. var shape = Shape()
  2. shape.numberOfSides = 7
  3. var shapeDescription = shape.simpleDescription()


Shape クラスのこのバージョンは、重要な何かが欠けています:インスタンスの作成時にクラスを設定するためのイニシャライザです。作成するには init を使用してください。


  1. class NamedShape {
  2.        var numberOfSides: Int = 0
  3.        var name: String
  4.        init(name: String) {
  5.             self.name = name
  6.        }
  7.        func simpleDescription() -> String {
  8.             return "A shape with \(numberOfSides) sides."
  9.        }
  10. }


イニシャライザへの name 引数から name プロパティを区別するために self が使用されるのに注意してください。クラスのインスタンスを作成するときにイニシャライザへの引数は、関数呼び出しのように渡されます。すべてのプロパティは、その宣言(numberOfSides のように)内や、(name のように)イニシャライザ内のいずれかで値が割り当てられる必要必要があります。


オブジェクトが割り当て解除される前に何らかの掃除を実行する必要がある場合は、デイニシャライザを作成するのに deinit を使用してください。


サブクラスは、コロンで区切られたクラス名の後に、それらのスーパークラスの名前を含みます。クラスは、標準的なルートクラスをサブクラス化する必要はなく、必要に応じてスーパークラスを省略したり含めたりできます。


スーパークラスの実装をオーバーライドするサブクラスのメソッドは override でマークされ、override なしで誤ってオーバーライドしたメソッドは、コンパイラによってエラーとして検出されます。コンパイラは、また実際にはスーパークラス内のどのメソッドもオーバーライドしない override でマークされたメソッドを検出します。


  1. class Square: NamedShape {
  2.        var sideLength: Double
  3.        init(sideLength: Double, name: String) {
  4.             self.sideLength = sideLength
  5.             super.init(name: name)
  6.             numberOfSides = 4
  7.        }
  8.        func area() -> Double {
  9.             return sideLength * sideLength
  10.        }
  11.        override func simpleDescription() -> String {
  12.             return "A square with sides of length \(sideLength)."
  13.        }
  14. }
  15. let test = Square(sideLength: 5.2, name: "my test square")
  16. test.area()
  17. test.simpleDescription()


実験: Circle と呼ばれる NamedShape の別のサブクラスを作成し、そのイニシャライザへの引数として半径と名前を取るものを作ります。Circle クラス上の area()simpleDescription() メソッドを実装しましょう。


保存されている単純なプロパティに加えて、プロパティは getter と setter を持つことができます。


  1. class EquilateralTriangle: NamedShape {
  2.        var sideLength: Double = 0.0
  3.        init(sideLength: Double, name: String) {
  4.             self.sideLength = sideLength
  5.             super.init(name: name)
  6.             numberOfSides = 3
  7.        }
  8.        var perimeter: Double {
  9.             get {
  10.                 return 3.0 * sideLength
  11.             }
  12.             set {
  13.                 sideLength = newValue / 3.0
  14.                }
  15.        }
  16.        override func simpleDescription() -> String {
  17.                return "An equilateral triangle with sides of length \(sideLength)."
  18.        }
  19. }
  20. var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
  21. print(triangle.perimeter)
  22. triangle.perimeter = 9.9
  23. print(triangle.sideLength)


perimeter の setter では、新しい値は、暗黙の名前 newValue を持っています。set の後の括弧内に明示的な名前を提供できます。


EquilateralTriangle クラスのイニシャライザには、3つの異なる段階があることに注意してください:


  1. サブクラスが宣言したプロパティの値を設定します。
  2. スーパークラスのイニシャライザを呼び出します。
  3. スーパークラスで定義されたプロパティの値を変更します。メソッド、getter、または setter を使用するすべての追加の設定作業もこの時点で行うことができます。

プロパティを計算する必要がないが、新しい値を設定した前後に実行されるコードを提供する必要がある場合、willSetdidSet を使用して下さい。あなたが提供するコードは、いつでもイニシャライザの外側で値の変更をした時に実行します。例えば、以下のクラスは三角形の辺の長さが常にその正方形の一辺の長さと同じであることを保証します。


  1. class TriangleAndSquare {
  2.        var triangle: EquilateralTriangle {
  3.                willSet {
  4.                        square.sideLength = newValue.sideLength
  5.                }
  6.        }
  7.        var square: Square {
  8.                willSet {
  9.                        triangle.sideLength = newValue.sideLength
  10.                }
  11.        }
  12.        init(size: Double, name: String) {
  13.                square = Square(sideLength: size, name: name)
  14.                triangle = EquilateralTriangle(sideLength: size, name: name)
  15.        }
  16. }
  17. var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
  18. print(triangleAndSquare.square.sideLength)
  19. print(triangleAndSquare.triangle.sideLength)
  20. triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
  21. print(triangleAndSquare.triangle.sideLength)


optional の値を操作する時は、? をメソッド、プロパティ、および添字などのような演算子の前に書くことが出来ます。もし ? の前の値が nil の時は、? の後のすべては無視され、式全体の値は nil になります。それ以外の場合は、optional の値は開封され、? の後のすべては開封された値に作用します。両方の場合とも、式全体の値は optional の値になります。


  1. let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
  2. let sideLength = optionalSquare?.sideLength


列挙型と構造体


列挙型を作成するためには enum を使用します。クラスや他のすべての名前付きの型と同じように、列挙型は、それらと関連するメソッドを持つことができます。


  1. enum Rank: Int {
  2.        case ace = 1
  3.        case two, three, four, five, six, seven, eight, nine, ten
  4.        case jack, queen, king
  5.        func simpleDescription() -> String {
  6.                switch self {
  7.                case .ace:
  8.                        return "ace"
  9.                case .jack:
  10.                        return "jack"
  11.                case .queen:
  12.                        return "queen"
  13.                case .king:
  14.                        return "king"
  15.                default:
  16.                        return String(self.rawValue)
  17.                }
  18.        }
  19. }
  20. let ace = Rank.Ace
  21. let  aceRawValue = ace.rawValue


実験: それらの生の値を比較することにより、2つの Rank 値を比較する関数を記述してみましょう。


デフォルトでは、Swift は生の値がゼロで開始し、1 ずつ増分しますが、明示的に値を指定することで、この動作を変更することができます。上記の例では、Ace は、明示的に 1 の生の値が与えられ、そして生の値の残りの部分は、順に割り当てられます。また、列挙型の生の型として文字列や浮動小数点数も使用できます。列挙型の case の生の値にアクセスするために rawValue プロパティを使用します。


init?(rawValue:) イニシャライザを使用し、生の値から列挙型のインスタンスを作成します。生の値と一致する列挙型 case か、一致する Rank がない場合は nil を返します。


  1. if let convertedRank = Rank(rawValue: 3) {
  2.        let threeDescription = convertedRank.simpleDescription()
  3. }

列挙型の case の値は、実際の値であり、それらの生の値を書き込むだけの他の方法ではありません。実際、意味のある生の値が存在しない case では、1つも提供する必要はありません。


  1. enum Suit {
  2.        case spades, hearts, diamonds, clubs
  3.        func simpleDescription() -> String {
  4.                switch self {
  5.                case .spades:
  6.                        return "spades"
  7.                case .hearts:
  8.                        return "hearts"
  9.                case .diamonds:
  10.                        return "diamonds"
  11.                case .clubs:
  12.                        return "clubs"
  13.                }
  14.        }
  15. }
  16. let hearts = Suit.Hearts
  17. let heartsDescription = hearts.simpleDescription()


実験: Suit に、スペードとクラブには"黒"を返し、ハートとダイヤモンドには"赤"を返す color() のメソッドを追加してみましょう。


上記の例で、列挙型の hearts の case が言及されている二つの方法に注目してください。hearts 定数に値を代入すると、その定数は指定された明示的な型を持っていないため、列挙型の case Suit.hearts は、そのフルネームで参照されます。switch の内部では、self の値はすでに suit であることが知られているので、列挙型の case は、省略形の .hearts によって参照されます。値の型が既に知られている時はいつでも省略形を使用できます。


列挙型に生の値がある場合、それらの値は宣言の一部として決定されます。つまり、特定の列挙型のすべてのインスタンスが常に同じ生の値を持つことを意味します。列挙型 case の別の選択肢は、case に関連付けられた値を持たせることです。これらの値は、インスタンスの作成時に決定され、列挙型 case の各インスタンスごとに異なる場合があります。関連付けられた値は、列挙型 case のインスタンスの格納されたプロパティのように動作すると考えることができます。たとえば、サーバーから日の出と日没の時刻を要求する場合を考えてみましょう。サーバーは要求された情報で応答するか、何が悪かったかの説明で応答します。


  1. enum ServerResponse {
  2.        case result(String, String)
  3.        case failure(String)
  4. }
  5. let success = ServerResponse.result("6:00 am", "8:09 pm")
  6. let failure = ServerResponse.failure("Out of cheese.")
  7. switch success {
  8. case let .result(sunrise, sunset):
  9.        print ( "Sunrise is at \(sunrise) and sunset is at \(sunset).")
  10. case let .failure(message):
  11.        print ( "Failure... \(message)")
  12. }


実験: ServerResponse および switch に第三の case を追加してみましょう。


日の出·日の入りの時間が、switch case に対する値に一致する一部として ServerResponse の値から抽出されることに注意してください。


struct を、構造体を作成するのに使用してください。構造体はメソッドおよびイニシャライザを含めた、クラスと同じ多くの動作をサポートしています。構造体とクラスの間の最も重要な違いの一つは、それらはコードの中で渡された場合に構造体は常にコピーされますが、クラスは参照によって渡されるということです。


  1. struct Card {
  2.        var rank: Rank
  3.        var suit: Suit
  4.        func simpleDescription() -> String {
  5.                return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
  6.        }
  7. }
  8. let threeOfSpades = Card(rank: .three, suit: .spades)
  9. let threeOfSpadesDescription = threeOfSpades.simpleDescription()


実験: Rank と suit の各々の組み合わせの一枚のカードで、トランプの完全な一組を作成して、Card にメソッドを追加してみましょう。


プロトコルと拡張機能


プロトコルを宣言するためには protocol を使用してください。


  1. protocol ExampleProtocol {
  2.        var simpleDescription: String { get }
  3.        mutating func adjust()
  4. }


クラス、列挙型、及び構造体は、すべてプロトコルを採用することができます。


  1. class SimpleClass: ExampleProtocol {
  2.        var simpleDescription: String = "A very simple class."
  3.        var anotherProperty: Int = 69105
  4. func adjust() {
  5.                simpleDescription += " Now 100% adjusted."
  6.        }
  7. }
  8. var a = SimpleClass()
  9. a.adjust()
  10. let aDescription = a.simpleDescription
  11. struct SimpleStructure: ExampleProtocol {
  12.        var simpleDescription: String = "A simple structure"
  13.        mutating func adjust() {
  14.                simpleDescription += " (adjusted)"
  15.        }
  16. }
  17. var b = SimpleStructure()
  18. b.adjust()
  19. let bDescription = b.simpleDescription


実験: このプロトコルに準拠した列挙型を書いてみましょう。


構造体を変更するメソッドをマークするために SimpleStructure の宣言の中で mutating キーワードを使う事に注意してください。SimpleClass の宣言は、クラスのメソッドはいつでもクラスを変更できるため、mutating としてマークする必要はありません。


新しいメソッドや計算されたプロパティのように、既存の型に機能を追加するのに extention を使用してください。あるいは、ライブラリやフレームワークからインポートした型にさえも、別の場所で宣言されている型にプロトコルの適合性を追加するために extension を使用できます。


  1. extension Int: ExampleProtocol {
  2.        var simpleDescription: String {
  3.                return "The number \(self)"
  4.        }
  5.        mutating func adjust() {
  6.                self += 42
  7.        }
  8. }
  9. print(7.simpleDescription)


実験: absoluteValue プロパティを追加する Double 型の拡張機能を書いてみましょう。


異なる名前の型を持つようなプロトコル名を使用できます:例えば、異なる型を持ち、しかしすべてが単一のプロトコルに準拠しているオブジェクトのコレクションを作成できます。型がプロトコル型の値を処理する場合、プロトコル定義の外側のメソッドは利用できません。


  1. let protocolValue: ExampleProtocol = a
  2. protocolValue.simpleDescription
  3. // print(protocolValue.anotherProperty) // Uncomment to see the error


変数 protocolValueSimpleClass の実行時の型を持っているにもかかわらず、コンパイラは ExampleProtocol の与えられた型として扱います。これは、誤ってクラスがそのプロトコルの適合性に加えて、クラスが実装するメソッドやプロパティにアクセスできないことを意味します。


エラー処理


Error プロトコルを採用している全ての型を使用してエラーを表す事ができます。


  1. enum PrinterError: Error {
  2.         case outOfPaper
  3.         case noToner
  4.         case onFire
  5. }


エラーを投げかけるため throw を使用して、エラーを投げかけることができる関数をマークするために throws を使用します。関数内でエラーを投げかけた場合、関数はすぐに返し、関数を呼び出したコードは、エラーを処理します。


  1. func send(job: Int, toPrinter printerName: String) throws -> String {
  2.         if printerName == "Never Has Toner" {
  3.                 throw PrinterError.noToner
  4.         }
  5.         return "Job sent"
  6. }


エラーを処理するにはいくつかの方法があります。一つの方法が do-catch を使用することです。do ブロックの内部では、それの前に try を書くことによって、エラーを throw できるコードをマークします。それに別の名前を付けない限り、catch ブロックの内部では、エラーは自動的に error の名前を与えられます。


  1. do {
  2.         let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
  3.         print(printerResponse)
  4. } catch {
  5.         print(error)
  6. }


実験: プリンターの名前を "Never Has Toner" に変えると、send(job:toPrinter:) 関数はエラーを throw します。


特定のエラーを処理する複数の catch ブロックを提供できます。switch 内の case の後と同じように、catch の後にパターンを書いてください。


  1. do {
  2.         let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
  3.         print(printerResponse)
  4. } catch PrinterError.onFire {
  5.         print("I'll just put this over here, with the rest of the fire.")
  6. } catch let printerError as PrinterError {
  7.         print("Printer error: \(printerError).")
  8. } catch {
  9.         print(error)
  10. }


実験: do ブロック内に、エラーを throw するコードを追加してみましょう。どのような種類のエラーが最初の catch ブロックで処理されるように throw する必要がありますか?第二および第三のブロックについてはどうですか?


エラーを処理する別の方法は、try? を使用し、optional に結果を変換する事です。関数がエラーを throw する場合、特定のエラーは破棄され、結果は nil となります。それ以外の場合、結果は関数が返した値を含む optional です。


  1. let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
  2. let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")


関数が戻る直前に、関数内の他のすべてのコードの後に実行されるコードのブロックを書くために defer を使用してください。コードは関数がエラーを throw するかどうかに関係なく、実行されます。それらが異なる回数実行する必要があるにもかかわらず、隣同士に設定と掃除するコードを書くために defer を使用できます。


  1. var fridgeIsOpen = false
  2. let fridgeContent = ["milk", "eggs", "leftovers"]
  3. func fridgeContains(_ food: String) -> Bool {
  4.         fridgeIsOpen = true
  5.         defer {
  6.                 fridgeIsOpen = false
  7.         }
  8. let result = fridgeContent.contains(food)
  9.         return result
  10. }
  11. fridgeContains("banana")
  12. print(fridgeIsOpen)


汎用(ジェネリック)


汎用の関数や型を作るために < > の山括弧の中に名前を書きます。


  1. func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
  2.        var result = [Item]()
  3.        for _ in 0..<numberOfTimes {
  4.                result.append(item)
  5.        }
  6.        return result
  7. }
  8. makeArray(repeating:"knock", numberOfTimes:4)


汎用の関数やメソッドの形式、ならびにクラス、列挙型、および構造体を作ることができます。


  1. // Reimplement the Swift standard library's optional type
  2. enum OptionalValue<Wrapped> {
  3.        case none
  4.        case some(Wrapped)
  5. }
  6. var possibleInteger: OptionalValue<Int> = .none
  7. possibleInteger = .some(100)


本体の直前に、要件のリストを指定するのに where を使いますー例えば、プロトコルを実装する型を必要としたり、二つの型が同じであることを要したり、または特定のスーパークラスを持っている事をクラスに必要としたり。


  1. func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
  2.         where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {
  3.        for lhsItem in lhs {
  4.                for rhsItem in rhs {
  5.                        if lhsItem == rhsItem {
  6.                                return true
  7.                        }
  8.                }
  9.        }
  10.        return false
  11. }
  12. anyCommonElements([1, 2, 3], [3])


実験: いずれか二つの配列に共通している要素の配列を返す関数を作るために anyCommonElements(_:_:) 関数を変更してみましょう。


<T: Equatable> と書くのは、 <T> ... where T: Equatable> と書くのと同じです。





前:バージョン互換性 次:Swift の基本
-webkit-text-size-adjust: 100%; 目次
Xcode 10 の新機能

Swift:はじめに
Swift と Cocoa と Objective-C
Swift Blog より

  • ようこそ Swift へ(Part I)
  • Swift について
  • バージョン互換性
  • Swift のツアー
  • 単純な値
    制御フロー
    関数とクロージャ
    オブジェクトとクラス
    列挙型と構造体
    プロトコルと拡張機能
    エラー処理
    汎用(ジェネリック)
  • Swift 言語のガイド(Part II)
  • Swift の基本
  • 定数と変数
  • 定数と変数の宣言
    型注釈
    定数と変数の命名
    定数と変数の印刷
    コメント
    セミコロン
  • 整数
  • 整数の境界
    Int
    UInt
    浮動小数点数
    安全な型と型推論
    数値リテラル
  • 数値型変換
  • 整数変換
    整数と浮動小数点間の変換
    型エイリアス
    ブール型
    タプル
  • Optional
  • nil
    if 文と強制開封
    Optional の結合
    暗黙に開封された Optionals
    エラー処理
  • アサーション(断言)と前提条件
  • アサーションを使用したデバッグ
    前提条件の実施
  • 基本演算子
  • 専門用語
    代入演算子
  • 算術演算子
  • 剰余演算子
    単項マイナス演算子
    単項プラス演算子
    複合代入演算子
    比較演算子
    三項条件演算子
    Nil 合体演算子
  • 範囲演算子
  • 閉鎖範囲演算子
    半開放範囲演算子
    片方の範囲
  • 論理演算子
  • 論理 NOT 演算子
    論理 AND 演算子
    論理 OR 演算子
    論理演算子の組み合わせ
    明示的な括弧
  • 文字列と文字
  • 文字列リテラル
    複数行の文字列リテラル
    文字列リテラル内の特殊文字
    空の文字列の初期化
    文字列の可変性
    文字列は値の型
    文字を使った作業
    文字列と文字を連結
    文字列補間
  • ユニコード(Unicode)
  • Unicode スカラー
    文字列リテラルの中の特別の文字
    拡張書記クラスタ
    文字を数える
  • 文字列のアクセスと変更
  • 文字列のインデックス
    部分文字列
    挿入と削除
  • 文字列の比較
  • 文字列と文字の等価性
    接頭辞と接尾辞の等価性
  • 文字列の Unicode 表現
  • UTF-8 の表現
    UTF-16 表現
    Unicode のスカラー表現
  • コレクション型
  • コレクションの可変性
  • 配列
  • 配列型省略構文
    空の配列の作成
    デフォルト値を持つ配列の作成
    2つの配列を共にして一つの配列に
    配列リテラルでの配列の作成
    配列へのアクセスと変更
    配列の繰り返し処理
  • セット
  • セット型のハッシュ値
    セット型の構文
    空のセットの作成と初期化
    配列リテラルでセットの作成
    セットへのアクセスと変更
    セットを反復処理
  • セット操作の実行
  • 基本的なセットの操作
    セットの身分と等価性
  • Dictionary
  • Dictionary 型の省略型構文
    空の Dictionary を作成
    Dictionary リテラルで Dictionary の作成
    Dictionary のアクセスと変更
    Dictionary を繰り返し処理
  • フロー制御
  • For-In ループ
  • While ループ
  • While
    Repeat-While
  • 条件文
  • if 文
  • Switch
  • 暗黙の Fallthrough なし
    範囲の一致
    タプル(Tuples)
    値の結合
    Where
    複合した case
  • 制御転送文
  • Continue
  • Break
  • ループ文内の Break
    Switch 文内の Break
    Fallthrough
    ラベル付きの文
    早期終了
    API 利用可能性の確認
  • 関数
  • 関数の定義と呼び出し
  • 関数のパラメータと戻り値
  • パラメータなしの関数
    複数パラメータの関数
    戻り値なしの関数
    複数の戻り値を持つ関数
    optional のタプル型の戻り値
  • 関数引数のラベルとパラメータ名
  • 引数のラベルの指定
    引数ラベルの省略
    デフォルトのパラメータ値
    可変個引数のパラメータ
    In-Out パラメータ
  • 関数型
  • 関数型の使用
    パラメータ型としての関数型
    戻り値の型としての関数型
    入れ子になった関数
  • クロージャ
  • クロージャ式
  • ソートするメソッド
    クロージャ式の構文
    文脈から型を推論
    単一式クロージャからの暗黙的戻り値
    引数名の省略
    演算子メソッド
    後続クロージャ
    値のキャプチャ
    クロージャは参照型
    クロージャのエスケープ
    オートクロージャ
  • 列挙型
  • 列挙型の構文
    switch 文で列挙型の値の一致
    関連する値
  • 生の値
  • 暗黙に割り当てられた生の値
    生の値からの初期化
    再帰的な列挙型
  • クラスと構造体
  • クラスと構造体を比較
  • 定義の構文
    クラスと構造体のインスタンス
    プロパティにアクセス
    構造体型のためのメンバー化イニシャライザ
    構造体と列挙型は値型
  • クラスは参照型
  • ID 演算子
    ポインタ
    クラスと構造体の間の選択
    文字列、配列、辞書の代入とコピーの動作
  • プロパティ
  • 格納されたプロパティ
  • 定数構造体インスタンスの格納されたプロパティ
    遅延した格納されたプロパティ
    格納されたプロパティとインスタンス変数
  • 計算されたプロパティ
  • セッタ宣言の省略形
    読み取り専用の計算されたプロパティ
    プロパティ監視者
    グローバルとローカル変数
  • 型プロパティ
  • 型プロパティの構文
    型プロパティの照会と設定
  • メソッド
  • インスタンスメソッド
  • self プロパティ
    インスタンスメソッド内から値の型を変更
    変異メソッド内で self に代入
    型メソッド
  • サブスクリプト
  • サブスクリプトの構文
    サブスクリプトの使用法
    サブスクリプトのオプション
  • 継承
  • 基本クラスの定義
    サブクラス化
  • オーバーライド(上書き)
  • スーパークラスメソッド、プロパティ、サブスクリプトへのアクセス
    オーバーライドするメソッド
  • オーバーライドするプロパティ
  • プロパティのゲッタとセッタのオーバーライド
    プロパティ監視者のオーバーライド
    オーバーライドの防止
  • 初期化
  • 格納されたプロパティの初期値を設定
  • イニシャライザ
    デフォルトのプロパティ値
  • 初期化のカスタマイズ
  • 初期化パラメータ
    パラメータ名と引数ラベル
    引数ラベルのないイニシャライザのパラメータ
    Optional のプロパティ型
    初期化中に定数プロパティへの代入
  • デフォルトのイニシャライザ
  • 構造体型のためのメンバ化イニシャライザ
    値型のイニシャライザデリゲート
  • クラスの継承と初期化
  • 指定イニシャライザとコンビニエンスイニシャライザ
    指定とコンビニエンスイニシャライザの構文
    クラス型のイニシャライザデリゲート
    二相の初期化
    イニシャライザ継承とオーバーライド
    自動イニシャライザの継承
    実際の指定とコンビニエンスイニシャライザ
  • 失敗可能イニシャライザ
  • 生の値を持つ列挙型のための失敗可能イニシャライザ
    初期化失敗の伝播
    失敗可能イニシャライザのオーバーライド
    init! の失敗可能イニシャライザ
    必須イニシャライザ
    クロージャや関数でのデフォルトのプロパティ値設定
  • デイニシャライザ
  • デイニシャライザはどのように働くか
    作動中のデイニシャライザ
  • Optional の連鎖
  • 強制開封の代替としての Optional の連鎖
    Optional の連鎖のモデルクラスの定義
    Optional の連鎖を使用したプロパティへのアクセス
    Optional の連鎖を通じてメソッドを呼び出す
  • Optional の連鎖を通じてサブスクリプトへのアクセス
  • Optional 型のサブスクリプトにアクセス
    連鎖の複数レベルのリンク
    optional の戻り値を持つメソッドでの連鎖
  • エラー処理
  • エラーの表現と Throw
    エラーの処理
    throw 関数を使用したエラーの伝播
    Do-Catch を使用したエラー処理
    エラー をOptional の値に変換
    エラー伝播を無効に
    クリーンアップアクションの指定
  • 型キャスト
  • 型キャストのためのクラス階層の定義
    型のチェック
    ダウンキャスト
  • Any と AnyObjecgt 用の型キャスティング
  • ネストした型
  • 実際のネストした型
    ネストした型への参照
  • 拡張機能
  • 拡張機能の構文
    計算されたプロパティ
    イニシャライザ
  • メソッド
  • 変異インスタンスメソッド
    サブスクリプト
    ネストした型
  • プロトコル
  • プロトコルの構文
    プロパティの要件
    メソッドの要件
    変異メソッドの要件
  • イニシャライザの要件
  • プロトコルイニシャライザ要件のクラス実装
    失敗可能イニシャライザの要件
    型としてのプロトコル
    デリゲート
  • 拡張機能を持つプロトコル準拠の追加
  • 拡張機能を持つプロトコルの採用を宣言
    プロトコル型のコレクション
    プロトコルの継承
    クラス専用プロトコル
    プロトコルの構成
    プロトコル準拠の確認
    Optional のプロトコル要件
  • プロトコル拡張機能
  • デフォルトの実装の提供
    プロトコル拡張機能に制約を追加
  • ジェネリック(汎用)
  • 汎用が解決する問題
    汎用関数
    型パラメータ
    型パラメータの命名
    汎用の型
    汎用型の拡張
  • 型の制約
  • 型制約の構文
    実際の型の制約
  • 関連型
  • 実際の関連型
    既存の型を拡張して関連型を指定
    型注釈を使用して関連型を制約
    汎用の Where 句
    汎用の Where 句を含む拡張機能
    関連する型と汎用の Where 句
    汎用のサブスクリプト
  • 自動参照カウント
  • どのように ARC は働くか
    実際の ARC
    クラスインスタンス間の強い循環参照
  • クラスインスタンス間の強い循環参照の解決
  • 弱い参照
    所有されていない参照
    所有されていない参照と暗黙に開封された Optional のプロパティ
    クロージャの strong な循環参照
  • クロージャの strong な循環参照の解決
  • キャプチャリストの定義
    弱い参照と所有されていない参照
  • メモリの安全性
  • メモリへのアクセス競合の理解
    メモリアクセスの特徴
    In-Out パラメータへのアクセスの競合
    メソッド内の Self へのアクセスの競合
    プロパティへのアクセスの競合
  • アクセス制御
  • モジュールとソースファイル
  • アクセスレベル
  • アクセスレベルの全体的指針
    デフォルトのアクセスレベル
    ターゲット一つのアプリのアクセスレベル
    フレームワークのアクセスレベル
    ユニットテストのターゲット用のアクセスレベル
    アクセス制御の構文
  • カスタム型
  • タプル型
    関数型
  • 列挙型
  • 生の値と関連する値
    ネストした型
    サブクラス化
  • 定数、変数、プロパティ、およびサブスクリプト
  • ゲッタとセッタ
  • イニシャライザ
  • デフォルトのイニシャライザ
    構造体型用のデフォルトメンバ化イニシャライザ
  • プロトコル
  • プロトコルの継承
    プロトコルの準拠
  • 拡張機能
  • 拡張機能の private メンバ
    汎用
    型エイリアス
  • 高度な演算子
  • ビット単位演算子
  • ビット単位の NOT 演算子
    ビット単位の AND 演算子
    ビット単位の OR 演算子
    ビット単位の XOR 演算子
  • ビット単位の左と右シフト演算子
  • 符号なし整数のシフト動作
    符号付き整数のシフト動作
  • オーバーフロー演算子
  • 値オーバーフロー
    優先順位と結合性
  • 演算子メソッド
  • 接頭辞と接尾辞演算子
    複合代入演算子
    等価演算子
  • カスタム演算子
  • カスタム挿入辞演算子の優先順位
  • 言語のガイド(Part III)
  • 言語リファレンスについて
  • 文法の読み方
  • 語彙の構造
  • 空白とコメント
    識別子
    キーワードと句読点
  • リテラル
  • 整数リテラル
    浮動小数点リテラル
    文字列のリテラル
    演算子

  • 型注釈
    型識別子
    タプル型
    関数型
    エスケープしないクロージャの制限事項
    配列型
    辞書型
    Optional の型
    暗黙に開封された Optional の型
    プロトコル構成の型
    メタタイプ型
    型の継承句
    型の推測

  • 接頭辞式
    Try 演算子
  • 二項式
  • 代入演算子
    三項条件演算子
    型キャスト演算子
  • 一次式
  • リテラル式
    Self 式
    スーパークラス式
  • クロージャ式
  • キャプチャ・リスト
    暗黙のメンバ式
    括弧で囲まれた式
    タプル式
    ワイルドカード式
    キーパス式
    セレクタ式
    キーパス文字列式
  • 接尾辞の式
  • 関数呼び出し式
    イニシャライザ式
    明示的なメンバ式
    接尾辞の Self 式
    サブスクリプト 式
    強制値の式
    Optional の連鎖式

  • ループ文
  • For-In 文
    While 文
    Repeat-While 文
  • 分岐文
  • if 文
    Guard 文
  • switch 文
  • switch 文は、網羅的である必要あり
    実行が暗黙的に case を Fall Through しない
    ラベル付き文
  • 制御転送文
  • break 文
    continue 文
    fallthrough 文
    return 文
    throw 文
    defer 文
    do 文
  • コンパイラ制御文
  • 条件コンパイルブロック
    行制御文
    利用可能条件
  • 宣言
  • トップレベルのコード
    コードブロック
    Import 宣言
    ­定数の宣言
  • 変数の宣言
  • 格納された変数と格納された変数のプロパティ
    計算された変数と計算されたプロパティ
    格納された変数監視者とプロパティの監視者
    型変数プロパティ
    型エイリアス宣言
  • 関数の宣言
  • パラメータ名
    In-Out パラメータ
    パラメータの特殊な種類
    メソッドの特殊な種類
    Throw する関数とメソッド
    Rethrow する関数とメソッド
    決して返さない関数
  • 列挙型の宣言
  • 任意の型の case を列挙
  • 間接による列挙
    生の値型の case を列挙
    列挙型 case へのアクセス
    構造体の宣言
    クラスの宣言
  • プロトコルの宣言
  • プロトコル・プロパティ宣言
    プロトコル・メソッド宣言
    プロトコル・イニシャライザ宣言
    プロトコル・サブスクリプト宣言
    プロトコルに関連した型の宣言
  • イニシャライザ宣言
  • 失敗可能イニシャライザ
    デイニシャライザ宣言
    拡張機能の宣言
    サブスクリプト宣言
    演算子の宣言
    優先順位グループ宣言
  • 宣言修飾子
  • アクセス制御レベル
  • 属性
  • 宣言の属性
  • インターフェイスビルダーで使われる宣言属性
    型の属性
  • パターン
  • ワイルドカードパターン
    識別子パターン
    値結合パターン
    タプルパターン
    列挙型 case パターン
    Optional のパターン
    型キャストパターン
    式のパターン
  • 汎用パラメータと引数
  • 汎用パラメータ句
  • 汎用の where 句
    汎用引数句
  • 文法のまとめ
  • 語彙の構造



    宣言
    属性
    パターン
    汎用パラメータと引数
  • マニュアルの変更履歴
  • 変更履歴












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)