Menu

Category

Archive

logo


The Swift Programming Language ~ The Basics [Tuples, Optionals, Assertions]

2014-06-05 10:30:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

前回に続き、The Basics 章。今回は、Tuples, Optionals, Assertions に関して。

The Basics

10. Tuples

Tuples は、複数の値を 1 つにまとめるためのもの。これにより、関数から複数の値を返してもらうことができる。

1
let http404Err = (404, "Not Found")

これは、(Int, String) 型の tuple と言うこともできる。どんな組み合わせでも作成することができる。

1
2
3
let (statusCode, statusMsg) = http404Err
println("The status code is \(statusCode)") // 404
println("The status msg is \(statusMsg)")  // Not Found

このように、各値へアクセスできる。

1
2
let (justCode, _) = http404Err
println("The status code is \(statusCode)")  // 404

興味がない値に関しては、_ を使用することで名前をつける必要がない。

1
2
println("The status code \(http404Err.0)") // 404
println("The status code \(http404Err.1)") // Not Found

配列の index のように、数字でアクセスすることもできる。0 スタート。

1
2
3
let http404Err = (statusCode: 404, statusMsg: "Not Found")
println("The status code \(http404Err.statusCode)") // 404
println("The status code \(http404Err.statusMsg)") // Not Found

宣言時に各値に名前をつけることもできる

tuples は基本的に、関数からの返り値等の一時的な値のグループ分に使う。データがずっと保持される場合には構造体やクラスを使用。

11. Optionals

Swift には、Optionals という概念がある。名詞ぽい。これはある変数がある型の値を持つか、それとも全く持たないか、ということを明示的に示すもの。Optionals は型に ? を付けて宣言する。例えば、Int? といった感じ。Objective-C で nil にメッセージを送ってよくランタイムエラーを起こしてたので、堅牢に書くためのものだと思います。

1
2
3
// let possibleNum = "234"
let possibleNum = "234dsdfa"
let convertedNum = possibleNum.toInt()

この例では、convertedNum は、Int? と推論されている。toInt() メソッドは、String を Int に変換することができれば、Int を返し、そうでなければ、nil を返す。つまり、Optionals です。Optionals は if statement で値を持っているか確認することができる。ただの Int は、上記でみたように、if のような条件分岐で使用することができないが、Optionals (Int?) は使用可能。

1
2
3
4
5
6
7
8
9
10
if convertedNum {
    /* we can access either ways, the ! means forced unwrapping */
    println("\(possibleNum) has an integer value of \(convertedNum!)") // ok
    println("\(possibleNum) has an integer value of \(convertedNum)")  // ok?
} else { // optional is nil
    println("\(possibleNum) could not be converted to an integer \(convertedNum)") // print nil
    // println("\(possibleNum) could not be converted to an integer \(convertedNum!)")
    // run time error,
    // because it is trying to "forced" unwraping even it doesnt have anything
}

Optionals の値にアクセスする際には、! を optional の最後に付けて unwrap する。これは、forced unwrap と呼ばれる、無理やり剥きとる。なので、nil に対して使用するとエラーになる。上のコードで if-true ケースにおいて ! を使っても、使わなくても値にアクセスできる。ドキュメントには、! を使用するように書いてあるけど、なんでだろう。とにかく、! を使用する際には、run-time error になる可能性があるので、しっかりと if で確認。

12. Optional Binding

Optional Binding は、Optional が値を持っているか確認し、もし持っているなら、その値を一時的な変数かコンスタントに保存して利用するというもの。if か while で使われる。

1
2
3
4
5
6
7
let possibleNum  = "234"

if let actualValue = possibleNum.toInt() {
    println("\(possibleNum) has an integer value of \(actualValue)")
} else {
    println("\(possibleNum) could not be converted to an integer")
}      

もし、possibleNum.toInt() が値を返せば actualValue に保存し、if-true が実行される。actualValue のスコープは、最初の if-true ブロックまで。この Optional Binding を使用すれば、forced unwrap を使用する必要がない。

13. nil について

Objective-C の nil と Swift の nil は異なるもの。前者は、存在しないオブジェクトへのポインターですが、Swift では、ポインターではなく、ある型の値が欠落しているしてるということを表す。Optionals でないデータに nil をセットすることはできないので、ある変数/コンスタントが nil になることがある場合には、Optionals として宣言する必要がある。Optionals には、値が存在しない場合には、nil を明示的に代入してもよいし、特に指定しなければ、nil がセットされる。

1
2
3
4
5
var NotOptional: Int  = 30
NotOptional           = nil // error, because NotOptional is not optional
var YesOptional: Int? = 30
YesOptional           = nil // no problem, indicating explicitly the lack of value
var AutoOptional: Int?      // AutoOptional is set to nil

14. Implicitly unwrapped optionals

Optionals に対して、一度値がセットされた後は、常に値を持つと仮定することができる場合には、Implicitly unwrapped optionals というものが使える。これは、Optionals に対しても、自動的に unwrap (値にアクセス) する権限を与えるという風に考えることができる。つまり、値にアクセスする際に、! を付与する必要がない。Implicitly unwrapped optionals を使用するには、? の代わりに ! を宣言時にタイプする。

1
2
3
4
5
6
7
let possibleStr: String? = "A optional String"
println(possibleStr!); // this is good
println(possibleStr);  // this works too...

let assumedStr: String! = "An implicitly unwrapped optional String"
println(assumedStr);  // no !
println(assumedStr!); // don’t have to put ! anyway, works tho

二つ目の宣言が、Implicitly unwrapped optionals です。やっぱり疑問なのが、Optional の値に、! を付けないでアクセスしても普通に動くという点です。とりあえず、Optinal にアクセスする際には、if 文で値があるかチェックして、! で値にアクセスする。値があるか不明だが、ある時点で一度値がセットされた後は、ずっと値があると仮定できる時には 宣言時に ! を付けて、Implicitly unwrapped optionals を使用して、アクセスする際には、! を付けないでただアクセスする、ということかな。Implicitly unwrapped optionals に対しても、if を値をチェックしたり、Optional Binding も変わらず使用可。

15. Assertions

Assertions は、値がある条件を満たしているかをチェックするもの。もし、その条件を満たしていなかったら、プログラムは終了する。デバック時に役に立つ。assert() 関数を使用する。

1
2
3
4
5
6
let age = -1;
assert(age > 0, "Age should be positive value")

/* console output:
   assertion failed: Age should be positive value: file /Users/kobayashikazuya/Swift/MyFirstSwiftProject/MyFirstSwiftProject/ViewController.swift, line 17
*/

第一引数に条件、二つ目にエラー時に表示される内容を渡しておく。