オプショナル型のアンラップについて Swift4

オプショナル型=変数にnilの代入を許すデータ型
宣言方法:変数のデータ型の最後に”?”か”!”をつける

var name: String?
var age: Int!

※オプショナル型の変数は宣言をしただけで初期化をしなかった場合、nilが入っている

暗黙的アンラップ型”!” =使用する際に自動でアンラップされる
オプショナル型の宣言には”?”か”!”を用いますが、”!”を用いて宣言したオプショナル型(暗黙的アンラップ型)は下記のように使用する際に自動でアンラップされます。

"?"で宣言したオプショナル型の場合、非オプショナル型とは計算できない
var x: Int  = 5 // 非オプショナル型
var y: Int? = 10 // "?"で宣言したオプショナル型
x + y
# => エラー

"!"で宣言したオプショナル型の場合、自動でアンラップされるため非オプショナル型と計算できる
var x: Int  = 5 // 非オプショナル型
var y: Int! = 10 // "!"で宣言したオプショナル型(暗黙的アンラップ型)
x + y
# => 15

暗黙的アンラップ型は、

最初はnilで宣言⇒使用時には絶対に値が入っている(nilではない)

という使い方の際に使用します。
そのため、使用するときに変数の値がnilのときにはエラーとなりますので要注意です。

 

アンラップ=オプショナル型から値を取りだす

アンラップの方法は下記3通り

1. Forced Unwrapping (強制的アンラップ)
オプショナル型を強制的にアンラップする方法で、
オプショナル型の後ろに”!”をつける

2. Optional Binding (オプショナルバインディング)
オプショナル型の変数に値が入ってる⇒アンラップ⇒処理{}を実行
オプショナル型の変数に値がない(=nil)⇒処理{}を行わない、もしくはelse{}の処理を実行

var test: String? // オプショナル型

if let testUnwrapped = test {
println(testUnwrapped)
}
else {
println("テストはありません")
}

if let 変数2 = 変数1{} はSwiftでよく使われるnilチェックの方法
if let hogehoge = hogehogeValue {
//nilでない場合実行される処理
}

※他にもあるエラーハンドリング
if let 変数2 = try? 変数1 {}
try?はエラーが発生するとnilを返すオプショナル型変数、この組み合わせでエラーにならないようにしています

3. Optional Chaining(オプショナルチェイニング)
オプショナル型の変数に続けてプロパティを取得したり、メソッドを呼び出す場合に使用する、戻り値はオプショナル型になる
戻り値がオプショナル型となるため、オプショナル型の変数の中身がnilの可能性があってもプロパティを取得したり、メソッドを呼び出せる。

使用方法:オプショナル型の変数のあとに”?”をつける
オプショナル型の変数?.プロパティ
オプショナル型の変数?.メソッド()

【例1】

var animal1: Animal? = Animal()
var animal2: Animal?

// nilでないためプロパティが取得できる
animal1?.type
// => "Optional(ねこ)"

// nilでないためメソッドを呼び出せる
animal2?.call()
// => "Optional(わんわん)"
var animal1: Animal? = Animal()
var animal2: Animal?

// animal1がnilの場合、nilが返る
animal1?.type
// => nil

// animal2がnilの場合、nilが返る
animal2?.call()
// => nil

【例2】

var x: String?
Var y = x?.uppercased()
// => nil

 

メソッドのラベル 名前付き引数 Swift4

ラベル:名前付き引数

メソッドの呼び出し側で、引数をよりわかりやすくするためにラベルを使います。

例えば、引数名が”ct” だったとして、意味するものが国だったとしたら、ラベルに”country”をつけるとメソッドの呼び出し側でコード書く際に分かりやすい、という感じです。

// 総重量:数量×重さ
func calcSum(quantity qt: Int, weight wt: Int) -> Int {
    return qt * wt //メソッド内では引数名を使う
}

//メソッドを呼び出す際は第一引数にquantity、第二引数にweightとして呼び出す
calcSum(quantity: 20, weight: 100)

引数の前に”_”(アンダースコア)を付けてラベルを省略する場合もある

String(describing: Subject) について Swift4

Swift3 ⇒ Swift4 で同じプログラムでもprint()にオプショナル型を放り込むと下記エラーが出るようになったみたい、swift3では自動解釈してくれていたような。。←未確認

expression implicitly coerced from ‘string ‘ to any

これはアンラップすればだいたいが解決する

アンラップはデータ型の最後に「!」をつける ⇒  (String!)

 

次にStringのinit(describing instance: Subject)について

string interpolation produces a debug description for an optional value

これはStringのイニシャライザについてのエラー

String(describing:)と書き直せば解消する。ちなみに意味は
String(describing:)にインスタンスを渡すことで、そのインスタンスの情報を文字列で取得することができる
というもの。

これもprint文にオプショナル型で入れてしまった際によくでるエラー

Swift3⇒Swift4で@objc推論が廃止

Swift3⇒Swift4で@objc推論が廃止になり、

Objective-CのクラスとかをSwiftで扱う時には、メソッドの頭に「@objc」と明示しなくてはいけなくなりました。

#selectorを使用した例

timer = Timer.scheduledTimer(timeInterval: 1.0,
                target: self,
                selector: #selector(self.timeInterrupt(_:)),
                userInfo: nil,
                repeats: true)

@objc func timerInterrupt(_ timer:Timer) {
    ・・・・・・・
}

 

 

Swift3.0からは今までのようなfor文が使えない

Swift3.0から今まで使用していたC言語スタイルのfor文が使えません。

なかなか大きな変更で衝撃を受けたのでメモ

例.

【従来のfor文】
for (var i = 0; i < 10; i++) {
print("現在\(i + 1)回目の繰り返し!")
}

↓これが下記のようなスタイルで書くようになりました

【for-inを使用】
for i in 0..<10 {            //範囲の表記方法は0...9 でもOK
    print("現在\(i + 1)回目の繰り返し!")
}
【forEachを使用】
Array(0..<10).forEach {
    print("現在\($0 + 1)回目の繰り返し!")
}

ちなみにfor-in文の文法は下記

for 変数 in 範囲演算 {
    繰り返しを記述したステートメント
}

i++のようなインクリメントの書き方ができなくなっているので

while文などでインクリメントを書く際には下記のように書く

i+=1

i=i+1

i–のようなデクリメントについては

i-=1

i=i-1

 

ここまで全部Swift version4.0.3で確認済み