「ゴルトン社長」のはじめの一歩

すげーブログ

世の中のすげーを伝える!

【初心者必見】iphoneアプリ開発_型の基礎・基本

最終更新日:2020年08月14日
f:id:BlueThree:20200814204123j:plain:w500
家に引きこもっている「ゴルトン社長」です。(twitter : @GoRuton_1stStep)

今日は、swift特有のOptional型の解説を記載しました

人気の記事!

人生を変えたい人に向けて「はじめの一歩」を踏み出したい人にオススメ!

www.goruton.com www.goruton.com www.goruton.com www.goruton.com

1)Optional 型の基本

f:id:BlueThree:20190701000950p:plain
Optional型のまとめ

Optional 型とは?
  • Optional 型 - nil の代入を許す
  • 非 optional 型 - nil の代入を許さない
var a: Int? // Optional 型
var b: Int  // 非 optional 型
var c: String? // Optional 型
var d: String  // 非 optional 型
var e: Int?
var f: Optional<Int> // Int? と同じ意味. T? は Optional<T> のシンタックスシュガーである
シンタックスシュガーとは?
- プログラミング言語において、既存の構文などを別の構文や記法で記述できるようにしたもの。
- 長い構文を簡略に記述できるようにしたり、複雑な構文を見やすくするために用意されることが多い。
- 糖衣構文などと訳される。
nilとは?
  • nilとはデータが無い、変数が空の状態を表します。
  • iOSではnilに対して操作することでアプリケーションが落ちてしまうことがありました。
  • そのような問題を解決するためにswiftではnilを基本的には許容しません。
  • しかし、オプショナル型を使うことでnilを扱うことができるようになります。
Optional は enum 型である
  • Optional は、標準ライブラリの中で enum 型として定義されている。
enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None    // nil に相当する
    case Some(T) // T 型(素の型)の値が入る(Int 型や String 型の値など)
    ...
}
Optional 型は nil が代入されるのを許す
  • 非 optional 型に nil を代入しようとすると、コンパイラエラーが発生する。
  • 非 Optional 型の場合、初期値には何も入っていない(nilも入っていない)
var a: Int? // Optional 型
a = nil     // -> OK
var b: Int // 非 optional 型
b = nil    // -> Compiler error: Type 'Int' does not conform to protocol 'NilLiteralConvertible'
var a: Int? // Optional 型
println(a)  // -> nil
var b: Int // 非 optional 型
println(b) // -> Compiler erorr: Variable 'b' used before being initialized
Optional 型は、非 Optional 型と同じようには扱えない
  • 下記のように,Int? 型は、Int 型とは別の型なので、同じように操作することはできない。
  • Int 型と同じように操作するためには、変数を「アンラップ」する必要がある(後述)。
var a: Int = 1
println(a + 2) // -> 3
var b: Int? = 1
println(b + 2) // -> Compiler error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?

2)ラップ(wrap)とアンラップ(unwrap)

「ラップされている」とは?「アンラップする」とは?
  • Optional 型(Optional 型)の変数のことを「ラップされている」と言う
  • Optional型に T 型の変数が「包まれている」ことに由来すると思われる
  • Optional 型(Optional 型)から T 型の変数を取り出すことを、「アンラップする」と言う。
Optional 型をアンラップする方法

Optional 型の変数をアンラップする方法として、以下のものがある。

  • Forced unwrapping
  • Optional chaining
  • Optional binding
  • 比較演算子
Forced unwrapping
  • 「!」 を optional 型の変数の後ろに付けるとアンラップすることができる。
  • これを Forced unwrapping と言う。
class Dog {
    func bark() -> String {
        return "Wan!"
    }
}

var wrappedDog: Dog? = Dog() // Optional 型

//
// アンラップをしないと、bark() メソッドを呼び出すことができない
//
println(wrappedDog.bark()) // -> Compiler error: 'Dog?' does not have a member named 'bark'

//「!」 を optional 型の変数の後ろに付けるとアンラップすることができる。
// これを Forced unwrapping と言う。

//
// Forced unwrapping
//
println(wrappedDog!.bark()) // -> Wan!

//
// Forced unwrapping でnil をアンラップしようとすると、ランタイムエラーが発生する。
wrappedDog = nil
println(wrappedDog!.bark()) // -> Runtime error: unexpectedly found nil while unwrapping an Optional value
Optional chaining
  • 「?」 を使ってアンラップすることを optional Chaining と言う。
//
// Optional Chaining
//
println(wrappedDog?.bark()) // -> Optional("Wan!")

// Optional chaining で nil をアンラップしようとすると、nil が返ってくる。
wrappedDog = nil
println(wrappedDog?.bark()) // -> nil
  • Forced unwrapping はアンラップをした後に、最終的な戻り値をそのまま返す。
  • 以下の場合、bark メソッドの戻り値(String 型)をそのまま返す。
//
// Forced unwrapping
//
println(wrappedDog!.bark()) // -> Wan!

注意: Optional Chaining は Optional 型を返す
<理由>
1 optional chaining が nil を返す可能性があるためである。
2 アンラップ対象の変数が nil だった場合、optional chaining はランタイムエラーを起こさずに nil を返す。
3 nil を許容するためには、戻り値は optional 型でなければならない。

  • Optional chaining はアンラップをした後に、最終的な戻り値を optional 型にラップしてから返す。
  • 以下の場合、bark メソッドの戻り値(String 型)を optional 型にラップしてから返す。
//
// Optional chaining
//
println(wrappedDog?.bark()) // -> Optional("Wan!")

上記の命令では以下の処理が行われている。

1 wrappedDog をアンラップする
2 bark() メソッドを呼ぶ
3 bark() メソッドが String 型を返す
4 String 型を optional 型にラップする
5 Optional 型を返す

注意:「?」には二つの別の意味がある
どちらも「?」を使っているが、意味が異なるので混同しないように注意。

var a: Int? // Optional 型宣言の意味
println(wrappedDog?.bark()) // -> Optional("Wan!") // Optional chainingの意味
Optional binding
  • if や while 文の条件式で宣言され、optional 型の変数を代入された変数は、非 optional 型になる。
  • これを「optional binding」と言う
var wrappedDog: Dog? = Dog() // Optional 型
// Optional binding
if var unwrappedDog = wrappedDog { // unwrappedDog はアンラップされた値(素の Dog 型)になる
    // varではなくてもletでも使用可能
    // unwrappedDog は非 optional 型なので、アンラップは不要
    println(unwrappedDog.bark()) // -> Wan!
}

// while文でもOK
while var unwrappedDog = wrappedDog {
    println(unwrappedDog.bark()) // -> Wan!
    break
}

// wrappedDog が nil だった場合、条件式は false になる
wrappedDog = nil
if var unwrappedDog = wrappedDog { // false
    println("This is not printed out.")
}
比較演算子

比較演算子を使うと、optional 型の変数が自動的にアンラップされる

var wrappedInt: Int? = 1 // Optional 型

// 自動的にアンラップされる
println(wrappedInt == 1) // -> true
println(wrappedInt >= 1) // -> true
println(wrappedInt >  1) // -> false
println(wrappedInt <= 1) // -> true
println(wrappedInt <  1) // -> false
println(wrappedInt != 1) // -> false

//Optional 型の変数を比較演算子の右に置いてもかまわない。
println(1 == wrappedInt) // -> true

//Optional 型の変数が nil であっても、エラーは発生しない。
wrappedInt = nil
println(wrappedInt == 1) // -> false

//注意: nil は負の無限大より小さい
println(nil < -Double.infinity) // -> true

var wrappedDouble: Double? = nil
if wrappedDouble < 0.0 {
    println("\(wrappedDouble) is a negative number.") // -> nil is a negative number.
}

3) Implicitly Unwrapped Optional 型とは?

「自動的にアンラップされる optional 型」のことである。

Implicitly Unwrapped Optional 型の宣言方法

「?」ではなく、「!」を使う

var a: Int! // Implicitly unwrapped optional 型
var b: Int? // Optional 型
var c: String! // Implicitly unwrapped optional 型
var d: String? // Optional 型

// T! は、ImplicitlyUnwrappedOptional<T> のシンタックスシュガーである
var e:ImplicitlyUnwrappedOptional<Int> // つまり,Int! と同じ
ImplicitlyUnwrappedOptional は enum 型である
  • ImplicitlyUnwrappedOptional は標準ライブラリの中で enum 型として定義されている。
enum ImplicitlyUnwrappedOptional<T> : Reflectable, NilLiteralConvertible {
    case None    // nil に相当する
    case Some(T) // T 型(素の型)の値が入る(Int 型や String 型の値など)
    ...
}
Implicitly Unwrapped Optional 型の初期値は nil
var a: Int! // Implicitly unwrapped optional 型
println(a)  // -> nil
Implicitly Unwrapped Optional 型は自動的にアンラップされる
var iwrappedDog: Dog! = Dog() // Implicitly unwrapped optional 型
// 「!」や「?」を付けなくても、自動的にアンラップされる
println(iwrappedDog.bark()) // -> Wan!

nil をアンラップしようとすると、ランタイムエラーが発生する。

iwrappedDog = nil
println(iwrappedDog.bark()) // -> Runtime error: unexpectedly found nil while unwrapping an Optional value

「!」には二つの別の意味がある
1) Implicitly unwrapped optional 型の宣言
2) Forced unwrapping

var a: Int! // Implicitly unwrapped optional 型 (1)

var wrappedDog: Dog? = Dog() // Optional 型
// Forced unwrapping
println(wrappedDog!.bark()) // -> Wan! (2)

4) Optional 型の代入演算子

var wrapped: Int?  = 1 // Optional 型
var iwrapped: Int! = 2 // Implicitly unwrapped optional 型
var unwrapped: Int = 3 // 非 optional 型


//Optional 型は、implicitly unwrapped optional 型に代入できる。
//Implicitly unwrapped optional 型は、optional 型に代入できる。
iwrapped = wrapped // OK
wrapped = iwrapped // OK


//Forced unwrapping でアンラップされた optional 型は、非 optional 型に代入できる。
unwrapped = wrapped! // OK

//Optional 型は、非 optional 型に「代入できない」。
unwrapped = wrapped 
// Compiler error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?

//Implicitly unwrapped optional 型は、 非 optional 型に代入できる
//(暗黙的にアンラップされていることに注意)。
unwrapped = iwrapped // OK


//Optional chaining でアンラップされた optional 型は、非 optional 型に「代入できない」
//(optional chaining の戻り値が optional 型であるため)。

unwrapped = wrapped?
// Compiler error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?


//非 optional 型は、optional 型やimplicitly unwrapped optional 型に代入できる。
wrapped = unwrapped // OK
iwrapped = unwrapped // OK
?? 演算子

1) a が nil でなければ、a!(a をアンラップしたもの) を返す。
2) a が nil であれば、b を返す。
つまり,a ?? b は、a != nil ? a! : bのシンタックスシュガーである

(1)
var a: Int? = 1
// a は nil でないので、a をアンラップしたものを返す
println(a ?? 2) // -> 1
println(a != nil ? a! : 2) // -> 1

(2)
a = nil
// a は nil なので、2 を返す
println(a ?? 2) // -> 2

参考リンク

iphone参考記事

https://bluethree-gift.hatenablog.com/archive/category/iphone%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA__%E5%88%9D%E5%BF%83%E8%80%85bluethree-gift.hatenablog.com

bluethree-gift.hatenablog.com

bluethree-gift.hatenablog.com

bluethree-gift.hatenablog.com

bluethree-gift.hatenablog.com

最後に!!

f:id:BlueThree:20200805191056j:plain:w500

最後までご覧いただき、本当にありがとうございます!!

最近は、たくさんの読者さんから「コメント」や「メッセージ」が届くようになりました!!
皆さんと会話できて嬉しいですし、コメントで毎日励まされています。

ありがとうございます!

これからも、ゴルトン社長は「毎日」ブログを更新しています! www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com

皆さんから人気がある記事

www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com

まとめ記事

www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com www.goruton.com