LoginSignup
20
14

More than 5 years have passed since last update.

つまづかないSwift Optional

Last updated at Posted at 2015-12-02

I はじめに

Optionalは難しくない

Swift初学者にとってOptionalの概念はつまづきやすいポイントの一つと考えられる。(私自身もつまづきました)。しかしいくつかのポイントを抑えれば、Optionalは簡単に理解でき、難しいものではない。

自分が学んだときに知っておきたかった事をまとめてみたので、新たに学ぶ人の参考になれば幸いです。

記事の対象レベル

プログラミング経験はあるが、Swiftは初学という人。
プログラミングは初めてだがSwiftやプログラミングについて若干の知識と理解がある人(ざっくりすぎてゴメンなさい)

II 概要

Optional型の概念

Optionalとは言語仕様によってnil参照を不可能にすることで、プログラムの安全性を高める仕組みである。

nilを参照してしまいプログラムがクラッシュするというような事態をほぼ回避できる。
(ちなみにObjective-Cではnil参照してもクラッシュしないがSwiftからしっかりクラッシュする仕様になった)

それぞれの型の違い

非Optional型(通常の型)

nilを入れられない。それ以外は普通の型。
nilが入らないので、この型を使う限りnil参照は起こらない。

Optional型

nilを入れられる。

使う際(型に値を入れるとき以外、メソッドを呼び出すなど)にはnilチェックを強制される。
このnilチェックの仕組みをappleはunwrapと呼んでいてunwrapの方法は複数用意されている。

使う際にnilチェックを強制されるので、この型を使う限りnil参照は起こらない。(例外あり)

III 使い方

宣言

宣言方法

宣言時に型の後ろに"?"をつける事で、その型をOptionalとして宣言できる。

OptionalDeclaration.swift
var name: String? // Optional
var name: String  // 非Optional

var count: Int?   // Optional
var count: Int    // 非Optional

宣言できる型(=全ての型)

しっかり確認したわけではないが、基本的にはあらゆる型をOptionalとして宣言できるようだ。
独自クラスにも適用可。

Declaration2.swift
var myClass: MyClass? // Optional
var myClass: MyClass  // 非Optional

宣言できる / すべき 場所

基本的に型を宣言する場所全てでOptional型を宣言できる

  • ローカル変数
  • メソッドの引数、戻り値
  • クラスのヘッダー etc.

それぞれの型の挙動

非Optional型(通常の型)

以下のようなことを行うとコンパイルエラーになる

  • nilを入れようとする
  • 初期化前に参照する
  • クラスのヘッダーで宣言して、initで初期化しない etc.
NonOptionalRules.swift
var name: String = nil         // コンパイルエラー

var station: String            // ローカルで宣言するだけではエラーにならない
station.lowercaseString        // 初期化前に参照したので、ここでコンパイルエラー
var nextStop: String = station // 同じくコンパイルエラー

// nameをinitで初期化してないのでコンパイルエラー,nameをOptionalで宣言すればエラーにならない
class MyClass {
    var name: String

    init() {

    }
}

Optional型

  • nilが入る
  • 初期化しなくてもOK
  • Unwrap(nilチェック)せずに使おうとするとコンパイルエラー
OptionalRules.swift
var name: String? = nil         // OK

var station: String?            // OK, 初期化しないと中身はnil
station.lowercaseString         // Unwrapしないで使おうとしたので、ここでコンパイルエラー

var lastStop:String? = station  // OptionalからOptionalへの代入はOK

Unwrap(nilチェック)

Optional型はUnwrapという作業を行うことで使用できる。事実上のnilチェック。
最も代表的な方法のみを2つ紹介する。
あまり詳しく書かないので、Unwrapに関しては他の資料の参照をおすすめする。

Optional Binding

ifの後に新しく変数を宣言して(以下の例ではunwrappedName)、その変数にunwrapしたいOptional型の値が入るかをチェック。

Optionalに値が入ってる場合は、unwrappedNameにOptionalの中身が入り、if文の中身が実行される。
Optionalに値がない場合(中身がnil)はif文の中身は実行されない。

elseを付け加えることも可能。

OptionalBinding.swift
var guest: String = ""
var name: String?

if let unwrappedName = name {
    guest = unwrappedName
}

Forced Unwrapping

Optional型の変数の後ろに"!"をつけると、強制的にunwrapされる。もし変数の中身がnilだった場合は、Forced Unwrapを行おうとした瞬間にエラーになる。基本非推奨。

ForcedUnwrapping.swift
var guest: String = ""
var name: String?

guest = name!          // nameの後に"!"をつけて強制unwrap,このケースは実行時エラーになる
name!.lowercaseString  // メソッドの呼び出し。このケースも同じく実行時エラー


// 以下のケースはForce Unwrap時にUnwrapする型に値が入っているので、実行時エラーにはならない
var leader: String = ""
var member: String?

member = "Obi-Wan"
leader = member!
20
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
14