mzgkworks

iOSを中心にプログラミング関係について書く

【Swift】構造体

黒帯本iOS開発の基礎を学び直す。
P.79 Chapter 2-03

クラスを使うのがいいのか、構造体を使うのがいいのかはまだよくわからない。
P. 80の図がわかりやすい

クラスとの違い

  • 継承ができない
  • メソッドの引数にオブジェクトを渡した場合、値渡しになる
    • 参照渡しではないので、値を変更しても元は影響を受けない

クラス

  • 関数Aでクラス(インスタンス)のnameプロパティに佐藤をセット
  • 関数Bにクラスを渡す(参照渡し)
  • 関数Bで渡されたクラスのnameに鈴木をセット
  • 関数Aのクラスのnameは鈴木になる

構造体

  • 関数Aで構造体(インスタンス)のnameプロパティに佐藤をセット
  • 関数Bに構造体を渡す(値渡し)
  • 関数Bで渡された構造体のnameに鈴木をセット
  • 関数Aの構造体のnameは佐藤のまま

【Swift】クラス

黒帯本iOS開発の基礎を学び直す。
P.69 Chapter 2-03

インスタンス

  • クラスはあくまで定義(設計書)
  • 値の保持、処理を行うのはインスタンス
// クラスのインスタンス化
var インスタンス = クラス名()

プロパティに値を設定する

インスタンス名.プロパティ = 値
インスタンス名.メソッド(値)
// メソッド名は **set + プロパティ名**

継承

  • 元クラスの内容(プロパティ・メソッド)を引き継いで、拡張できる
  • 元クラスに機能を追加してしまうと、必要の無い機能を持ち既存のインスタンスの挙動に影響がでる可能性があるので、継承を使う
  • 開発工数の削減
  • 品質の保証

override

  • 継承元のメソッドの機能を変えることができる
override func 継承元のメソッド名()

super

  • 継承先でoverrideしたメソッド内で、継承元のoverride前のメソッドをcallして既存処理を行う
// 継承元
class Dog() {
    func bark() {
        print("わんわん")
    }
}

// 継承先(Dogを継承したGuideDogクラス)
class GuideDog: Dog {
    // 鳴き声を拡張
    override func bark() {
        super.bark() // 拡張前の元処理を実行
        // 拡張した内容(わんわん -> きゃんきゃん)
        print("きゃんきゃん")
    }
}

【Swift】必ず処理されるdefer

黒帯本iOS開発の基礎を学び直す。
P.65 Chapter 2-02

defer内に定義した処理は、メソッド終了時に必ず呼び出される

defer {
    メソッド終了時に行いたい処理
}

throw発生時にも終了時刻を出力させる例

func longMethod() throws {
    // なんらかの処理(エラー発生時にthrowを行う)
}

// longMethod()を利用する
do {
    // 正常・エラーに関わらず処理終了時に必ず行う処理
    defer {
        print("処理終了時刻: \(NSDate())")
    }

    print("処理開始時刻: \(NSDate())")
    try longMethod()    // try句をつける
} catch {
    print("エラー発生")
}

throw発生時の出力結果

  • 処理開始時刻: 2016-03-29 02:10:10
  • 処理終了時刻: 2016-03-29 02:10:15
  • エラー発生

【Swift】エラー通知とハンドリング

黒帯本iOS開発の基礎を学び直す。
P.63 Chapter 2-02

エラー処理が記述されているメソッドにthrowされる

func A()

  • func Bの呼び出し
  • エラー発生時の処理を記述

func B()

  • func Cの呼び出し

func C()

  • エラー発生時のthrow処理を記述
  • 関数宣言にthrowをつける
    • func 関数名(引数名: 型) throws -> 戻り値の型
  • throw処理の記述

上記関係の場合、func Cでthrowされたエラーはfunc Aで処理される。

ハンドリング

// エラータイプの宣言
enum MyError: ErrorType {
    case InvalidValue
}

// エラーをthrowする可能性がある関数
func doubleUp(value: Int) throws -> Int {
    if value < 0 {
        throw MyError.InvalidValue
    }
    return value * 2
}

// エラーハンドリングが必要なdoubleUp関数を利用する
func callDoubleUp() {
    do {
        // try句をつける(ここで引数に-1を渡すとdoubleUpでthrow -> catch文へ飛ぶ)
        var doubleResultValue = try doubleUp(-1)
        print("正常終了")
    } catch MyError.InvalidValue {
        print("エラー発生")
    }
}

【Swift】関数(引数の別名 引数名)

黒帯本iOS開発の基礎を学び直す。
P.60 Chapter 2-02

書式

  • func 関数名(引数の別名 引数名: 型) -> 戻り値の型

// メソッド(内部では引数名を使う)
func showTestScore(mathmaticsTestScore score: Int) -> String {
    return "数学の点数は\(score)点"
}

// メソッドの呼び出し(引数は別名を指定する)
showTestScore(mathmaticsTestScore: 80)

【Swift】if let文(アンラップ後の変数名はラップ変数と同じ名前にする)

黒帯本iOS開発の基礎を学び直す。
P.58 Chapter 2-02

if let文

  • optional型の変数を使用する場合の、判定時に使用するif文

if let文で使うアンラップ変数名

後で使わない

  • アンラップ後の変数を使用しない場合には、「_(アンダーバー)」で省略が可能
var value: String?
value = "こんにちわ"
if let _ = value {
    print("valueはnilではない")
}

後で使う

  • 同じ変数名を使う
  • if let文内でアンラップ前の変数が使えるため不具合発生の確率がある
  • 同じ名前にした場合、if let文中ではアンラップ後の変数が優先的に使用されるため
var value: String?
value = "こんにちわ"
if let value = value {
    print(value)    // アンラップ後のvalueが使われる
}

【Swift】辞書

黒帯本iOS開発の基礎を学び直す。
Chapter 2-02

ミュータブル(可変)とイミュータブル(不変)

  • varで宣言 : ミュータブル
  • letで宣言 : イミュータブル
  • Obective-CであったNSMutableDictionaryとかで区別しなくてもいい

要素なしで宣言

// 次の4つは同じことを意味する
let dict1: [String:Int] = [String:Int]()
let dic2 =  [String:Int]()   // 自分はこれを標準として使用する
// ,で宣言するので注意!!
let dic3: Dictionary<String,Int> = Dictionary<String,Int>()
let dic4 = Dictionary<String,Int>()

初期値あり

let dict5 = ["りんご":1, "みかん":2]
let dict6: Dictionary<String,Int> = ["メロン":1, "スイカ":2]