2020/1/31 Swift 型キャスト(Type Casting)

型キャストはインスタンスの型を調べる、あるいはそのインスタンスを、そのインスタンスの型のスーパークラス、あるいはサブクラスとして扱うことです。

Swiftの型キャストは

is

または

as

を用いて実装されます。この二つの演算子は簡潔で表現力のある型の調査方法、あるいは型を別の型へキャスト(変換)する方法を提供します。

型キャストのためにクラス階層を定義する

「特定のクラスのインスタンスの型を調べる」

「同じクラス階層の中で、あるクラスのインスタンスを他のクラスへ型キャストする」

これらの目的のために、クラス階層の中の型キャストを使用することができます。3つの継承関係のあるクラスと、それらのクラスのインスタンスを含む配列を定義し、型キャストのサンプルを作っていきます。

最初のクラスはベースクラスのMediaItemです。デジタルメディアライブラリに現れるいくつかの種類のアイテムの基本的な機能を表現します。String型のnameプロパティとイニシャライザを定義します。(全てのメディアアイテムが名前を有すると想定します。)

class MediaItem {
    var name: String
    init(name: String) {
        self.name = name
    }
}

次にMediaItemクラスのサブクラスを二つ定義します。一つはMovieクラス映画に関する情報をカプセル化するクラスです。directorプロパティと、それに対応したイニシャライザが定義されています。二つ目はSongクラスです。Songクラスにはartistプロパティとそれに対応するイニシャライザが追加されています。

class Movie: MediaItem {
    var director: String
    init(name: String, director: String) {
        self.director = 

2020/1/27 Swift メソッド

メソッドは、特定の型に結び付けられた関数です。クラス・構造体・列挙型は全てインスタンスメソッドを定義できます。インスタンスメソッドはその型のインスタンスから呼び出す特定の機能をカプセル化したものです。クラス・構造体・列挙型はタイプメソッドを定義することもできます。タイプメソッドは型そのものと結び付けられています。

インスタンスメソッド

インスタンスメソッドは特定のクラス・構造体・列挙型のインスタンスに属する関数です。インスタンスのプロパティにアクセスしたりインスタンスのプロパティを修正する手段を提供したり、インスタンスの目的に関係した機能を提供します。インスタンスメソッドの定義は関数の構文と同じです。

インスタンスメソッドの定義は型定義のブロック内に記述します。インスタンスメソッドは、その型の全てのインスタンスメソッドとプロパティに暗黙的にアクセスできます。インスタンスメソッドはその型のインスタンスからのみ呼び出すことができます。インスタンス無しで独立して呼び出すことはできません。

下のサンプルはシンプルなカウンターのクラス定義です。

sample1-1

class Counter {
    var count = 0
    func increment() {
        count += 1
    }
    func increment(by amount: Int) {
        count += amount
    }
    func reset() {
        count = 0
    }
}

let counter = 

2020/1/27 Swift プロトコル(Protocols)

プロトコル(Protocols)は、ある特定の仕事や機能に必要なメソッド・プロパティなどの設計図にあたります。それらの要請を実際に実装するためにプロトコルがクラス・構造体・列挙型に取り入れられます。あるプロトコルが要求する事柄を満たした型を「そのプロトコルに準拠した型」と言います。

プロトコルの構文

クラス・構造体・列挙型と似た方法でプロトコルを定義できます。

protocol SomeProtocol {
    // プロトコルの定義
}

独自の型は、自身の定義時に、準拠するプロトコル名を型名の後ろにコロンで区切って記述することで、自身がそのプロトコルに準拠する型であることを示します。準拠する複数のプロトコルを列挙することができ、その時はカンマで区切ります。

struct SomeStructure: FirstProtocol, AnotherProtocol {
    // 構造体の定義
}

上記サンプルではSomeStructure構造体はFirstProtocol,AnotherProtocolの二つのプロトコルに準拠する構造体です。

クラスがスーパークラスを持つ場合、下記のようにスーパークラス名を先に記述し、カンマで区切り、その後に準拠するプロトコル名を記述します。

class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
    // クラスの定義
}

必要なプロパティをプロトコルで要請する

プロトコルは自身に準拠する型に対して、特定の名前・型のインスタンスプロパティ・タイププロパティを用意することを要求することができます。プロトコルはプロパティがストアドプロパティかコンピューテドプロパティかは特定しません。プロパティの名前と型を特定します。それからプロトコルは各プロパティが「gettable」か、「gettableとsettable」かを特定します。

プロトコルがあるプロパティを「gettableとsettable」と指定した場合、そのプロパティは

  • 定数のストアドプロパティ
  • 読み取り専用コンピューテドプロパティ

であってはなりません。プロトコルがそのプロパティに対して「gettable」を要求している場合、全ての種類のプロパティがその要求を満たすことができます。

「gettable」はセッターを有していてもいなくても、とにかくゲッターを有していれば良いので、「gettable」と指定されたプロパティは

  • ゲッターのみ有するプロパティ
  • ゲッターとセッターを有するプロパティ

どちらでも問題ありません。


まとめ…

2020/1/25 Swift guard文(Early Exit)

guard文は、if文のように、式の結果のBool値により処理を場合わけします。条件式がtrueの場合にguard文の(ブロックの)後ろのコードが確実に実行したい場合にguard文を使用します。if文と違い、guard文は常にels節が必要です。条件式がtrueでない場合にelse節が実行されます。

 

もしguard文の条件式がtrueの場合、guard文のブロックの終わりの

}

の次から実行が続いていきます。条件式の一部としてオプショナルバインディングを用いて、変数あるいは定数に値を代入すると、guard文(のブロック)より後のコード内でその変数あるいは定数を利用できます。

guard文の条件式がfalseの場合、else節内が実行されます。else節のどこかで必ずelse節(guard文)が存在するブロックの外に移行する必要があります。制御をブロック外に移行するのにreturn,break,continue,throwなどが使えます。

必要な時にguard文を使用することは、同じことをif文を使用して実装するのと比べて、コードの可読性の向上が期待できます。

else節内で条件に違反した場合の処理を記述できますし、条件に合致した場合の処理をelse節の下に記述することができます。

 

 

参考

https://docs.swift.org/swift-book/LanguageGuide/ControlFlow.html

2020/1/25 Swift エラー処理(Error Handling)

エラーハンドリングはエラーが出るような状況に対応し、解決するためのプロセスです。Swiftは、実行時に回復可能なエラーをスロー、キャッチ、伝播、および操作するためのファーストクラスのサポートを提供します。

いくつかの処理は実行完了や完全な出力を常に保証するものではありません。オプショナル型は値が存在しないことを表すために使用されますが、操作が失敗した場合、コードがそれに応じて応答できるように、失敗の原因を理解しておくと役立つことがよくあります。

例として、ディスクの中のファイルを読み込み処理する作業を考えます。この作業に失敗する可能性はいくつか考えられます。「指定されたパスにファイルが存在しない」「ファイルはあるが読み取りが許可されていない」「ファイルがエンコードされていない」など。これらのエラー原因を区別・特定することで、プログラムがエラーを解決することが可能になりますし、ユーザがエラー状況を把握できるようになります。

エラーの表示とスロー

Swiftでは、エラーはErrorプロトコルに準拠した型の値として表現されます。この空のプロトコルは、準拠した型がエラー処理に使用できることを示します。

Swiftの列挙型は特に関連するエラー状態をモデリングするのに適しています。連想値を使用すればエラーの性質についての追加情報を伝えることができます。例えば、ゲームの中で自販機を運営する状況でのエラー状況の表現を以下のようにすることができます。

enum VendingMachineError: Error {
    case invalidSelection  //←商品の種類が不適切
    case insufficientFunds(coinsNeeded: Int)  //←お金が足りない(連想値で足りない金額を表現)
    case outOfStock  //←品切れ
}

エラーのスローは予期しない状況が発生し、通常の実行フローを続けることが不可能であることを示します。エラーをスローするためにthrow文を使用します。下のコードは、自販機でコインが5枚足りないことを示すエラーをスローしています。例えば下のコードは自販機で5枚コインが足りないことを示すエラーをスロー(投げる)しています。

throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

エラーハンドリング

エラーがスローされた場合、周囲のコードの一部がエラーの処理を担当する必要があります。たとえば、問題の修正、代替アプローチの試行、ユーザーへの失敗の通知などです。

Swiftではエラーハンドリングの四つの方法が用意されています。

工事中🏗

それぞれのアプローチを以下で説明します。

エラーが発生するとプログラムのフローが変わりますので、どこでエラーが発生したかを素早く察知することが重要です。エラーが発生する可能性がある箇所にtryキーワードを記述します。あるいはエラーが発生する可能性がある関数・メソッド・イニシャライザの前にtry?あるいはtry!変数を記述します。以下でこれらのキーワードについて説明します。


Throwing Functionsを使ってエラーを伝える

関数・メソッド・イニシャライザがエラーをスローすることを示すために、throwsキーワードを関数定義の引数部分の後に記述します。throwsキーワードが記述された関数をthrowing Functionと呼びます。戻り値の型注釈がある場合、以下のように、リターンアロー( -> )の前にthrowsキーワードを記述します。

func canThrowErrors() throws 

2020/1/24 Swift ディクショナリ(Dictionaries)

ディクショナリは、データの集合の中のキー(key)とバリュー(value、値)の関連性を格納する型です。一つのディクショナリの中のキーは全て同じ型、一つのディクショナリの中の全てのバリュー(値)は同じ型です。それぞれのバリュー(値)は一意(ユニーク)なキーと関連づけられ、キーは、ディクショナリの中でバリューの識別子としての役割を果たします。配列(array)の要素と違い、ディクショナリの要素は順番がありません(indexを持たない。)。

識別子と関連づいた値を探したりする時はディクショナリを使いますが、それは現実世界で辞書で定義を探すときに、特定の単語により探そうとすることと一緒です。

ディクショナリの簡略記法

Swiftのディクショナリ型は、Dictionary<Key,Value>と表現されます。Keyはディクショナリのキーとして使用される値の型です。Valueは、そのキーに格納される値の型です。

NOTE

ディクショナリのキーの型はHashableプロトコルに準拠していなければなりません。

ディクショナリ型は簡略記法として

[Key:Value]

と記述できます。機能的には

Dictionary<Key,Value>

[Key:Value]

も同じものを表しますが、一般的に簡略記法が好まれ、このガイドでもディクショナリ型を表記するとき簡略記法を用います。


空のディクショナリを生成する 

配列と同様に、以下のようにイニシャライザ構文を用いて空のディクショナリを生成できます。

var namesOfIntegers = [Int: String]()
// namesOfIntegers is an empty [Int: String] dictionary

上記サンプルでは、Int型のキーに人の名前を格納するため、[Int:String]型の空のディクショナリを生成しています。

それまでのコードにより型の情報が推測できる場合、空のディクショナリリテラルを用いて空のディクショナリを生成することができます。空のディクショナリリテラルは

[:]

です。

namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 

2020/1/17 Swift 継承(inheritance)

クラスはメソッド・プロパティ、そしてその他の特徴を他のクラスから継承できます。継承先のクラスはサブクラス、継承元(継承される)クラスはスーパークラスと呼ばれます。継承はSwiftにおいてクラスとその他の型を違うものとする基本的な挙動です。

Swiftのクラスは、スーパークラスのメソッド・プロパティ・サブスクリプトにアクセスしたり呼び出したりすることができ、スーパークラスのメンバの挙動を修正変更してオーバーライドすることもできます。Swiftはオーバーライドの定義が、スーパークラスの定義と矛盾しないかをチェックして、オーバーライドが正しく行われることをサポートします。

クラスは継承したプロパティの値が変更されたことを知らせるために、プロパティオブザーバーを追加することができます。オリジナルの定義がストアドプロパティかコンピューテドプロパティかは関係なく、全てのプロパティに対してプロパティオブザーバを追加できます。

ベースクラスを定義する

スーパークラスを持たないクラスは、ベースクラスとして知られています。

NOTE

Swiftのクラスはユニバーサルベースクラスを継承しません。スーパークラスを継承していることを明示しない場合そのクラスはベースクラスになります。

下のサンプルはベースクラスVehicleを定義しています。このベースクラスはデフォルト値0.0でストアドプロパティcurrentSpeedを定義しています。currentSpeedの型はDouble型と推定されます。currentSpeedプロパティの値は、読み取り専用String型プロパティのdescriptionで使用され、descriptionはその車の説明文を生成します。

ベースクラスVehicleは、makeNoiseメソッドも定義します。Vehicleインスタンスを生成してmakeNoiseメソッドを呼び出しても、makeNoiseメソッドは特に何もしません。後にVehicleクラスのサブクラスを作るときに、オーバーライドするためのメソッドとして用意しています。

sample1-1

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // do nothing - an arbitrary vehicle doesn't 

2020/1/12 Swift イニシャライザ(Initialization)工事中🏗

初期化(Initialization)は、クラス・構造体・列挙型のインスタンスを準備するプロセスです。このプロセスはインスタンスのストアドプロパティの初期化と、その他のインスタンスを使用するに際必要なセットアップや初期化が含まれます。

イニシャライザを定義することで初期化処理を実装します。イニシャライザは特定の型のインスタンスが生成される際呼び出される特別なメソッドです。Swiftのイニシャライザは値を返しません。イニシャライザの一番の役割は、インスタンスが初めて使われる時に正常に初期化されていることを確実にすることです。

クラス型のインスタンスはデイニシャライザを実装することもできます。デイニシャライザはクラスのインスタンスが削除(割当解除)される直前に独自のクリーンアップをします。

ストアドプロパティの初期化

クラスと構造体はインスタンスが生成される時までに、全てのストアドプロパティが適切な値で初期化されていなければなりません。ストアドプロパティの値が不確定のままの状態は許されません。

ストアドプロパティの初期化方法としては、イニシャライザによる初期化、あるいはストアドプロパティの宣言時にデフォルト値を代入する方法があります。

NOTE

イニシャライザによる初期化時、あるいは宣言時のデフォルト値の代入時は、プロパティオブザーバが呼ばれることはありません。

イニシャライザ

イニシャライザは、特定の方のインスタンス生成時に呼び出されます。一番基本的なイニシャライザの定義は以下のようにインスタンスメソッドのように定義します。

sample1-1

init() {
    // perform some initialization here
}

sample1-2ではFahrenheitで表現される温度を格納するFahrenheit構造体を定義しています。一つのDouble型のストアドプロパティtemperatureを持っています。

sample1-2

struct Fahrenheit {
    var temperature: Double
    init() {
        temperature = 32.0
    }
}
var f = Fahrenheit()
print("The default 

2020/1/11 Swift ジェネリック(Generics)

ジェネリックコードを使うと、自分で定義した要請に応じて、あらゆる型に対応する柔軟で再利用可能な関数と型を作り出すことができます。重複を避け、意図を明確に抽象化したコードを記述できます。

ジェネリックはSwiftのもっとも強力な機能の一つであり、Swift標準ライブラリの多くがジェネリックコードにより書かれています。実はもうすでに私たちはジェネリック型を使っています。

例えばSwiftの配列とディクショナリはどちらもジェネリック型のコレクションです。要素がInt型の配列、要素がString型の配列、または他の型の配列も生成することができます。同様に特定の型の要素を持つディクショナリを生成することもできます。要素の型について制限はありません。

ジェネリックが解決する問題

sample1-1は二つのInt型の値を交換する、標準的な非ジェネリック関数swapTwoInts(_:_:)です。

sample1-1

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now