Swift-Mapall the thingsすべてをマッピング

4034 ワード

私のブログhttp://zyden.vicp.cc/mapallthething/転載を歓迎して、出典を明記して下さい、ありがとうございます
前回の記事では配列にmap()とflatMap()を導入し、彼らの使い方と利点を詳しく説明しましたが、実際にmapとflatMapもOptionalsタイプや他の多くのタイプに適用されています.今日は彼らの使い方を探ってみましょう.
対照的にArrayとOptional
思い出してみると、私たちが前に学んだArrayでmapとflatMapの使い方はこうです.
// Method on Array
    map( transform: T ->          U  ) -> Array
flatMap( transform: T ->    Array ) -> Array

これは、T->Uの変換方法を提供すれば、Tを含むArrayをUを含むArrayに変換することができることを意味します.すなわち,Arrayを単純な呼び出しmap(transform:T−>U)に通すと,Arrayが返される.
同様に、mapおよびflatMapのOptionalでの使用は、次のようになります.
// Method on Optional
    map( transform: T ->          U  ) -> Optional
flatMap( transform: T -> Optional ) -> Optional

map() on Optionals
OK、map()がOptionalタイプで何をしたか見てみましょう.同じ理屈でArrayで、まずOptional(Array)のすべての内容=(Arrayの内容は配列内のすべてのT、Optionalのすべての内容はこのOptionalの真実値とnil)==を手に入れ、それから私たちが提供した変換方式(transform:T->U)に基づいて変換した後、結果を新しいOptional(Array)に包装します.彼らのしたことは実は同じだ.
私たちの例を見てみましょう
私たちの前のコードで私たちが言った方法をどのように使うかを見てみましょう.
前回のサンプルコードでは、itemDesc["icon"]String?を返しますが、UIImageではなくUIImage(name:)のパラメータを受信する必要があります.このOptional String値がnilではない場合、Optionalの本当のStringを手に入れてこのUIImageの構造関数を呼び出します.
もちろん以前はOptional Bindingを使って
let icon: UIImage?
if let iconName = itemDesc["icon"] as? String {
  icon = UIImage(named: iconName)
} else {
  icon = nil
}

コード行数をより簡単に節約するために、nil結合オペレータStringも使用できます.
let iconName = itemDesc["icon"] as? String
let icon = UIImage(named: iconName ?? "")

iconNameがnilの場合、iconNameにUIImgeコンストラクション関数のパラメータとして「」を割り当てます:String?、nilのimage(UIImage?)を返し、プログラムがcrashしないことを保証しますが、これはコンストラクション関数??を少し歪めているようです.
mapでやってみよう
実際に必要なのは、Optionalがnilでない場合にそれを解包し、彼の真の値をパラメータとしてUIImage(named: "")に渡してUIimageを返すことであるため、これは非常に適切な使い方である.上のコード:
let iconName = itemDesc["icon"] as? String
item.icon = iconName.map { imageName in UIImage(named: imageName) }

考えは正しいが、上のコードはコンパイルできない必要がある!問題はどこですか.まず、上記のコードを説明します.IConNameというOptional値にmap()メソッドを呼び出し、nil以外の値(真の値){換言すると、iconNameがnil以外の場合にmap閉パケット内の変換ルールを実行する}がパラメータimageNameとして閉パケットに入力され、UIImageオブジェクトが構築されます.問題は、imageNameが有効なピクチャ名ではない場合、または何らかの理由で取れない場合、UIIMageはnilであるため、UIImage(named:)の戻り値自体がUIImage(named: )であり、map()の定義を見てみると、T->Uを変換してUIImage(named: )に戻る.では、私たちの例を見てみましょう.UIImage?UIImage?に相当しますが、map全体が終わったら戻ってくるU?は何ですか?-----U .はははこれはいわゆるDouble-Optionalです!
救星faltMap
flatMapはどんな変換をしましたか?U?、結果をフラット化(flattens)することから名付けられた...これらを紹介するのはもう言わないで、振り返って前の文章を見ることができます.ここでflatMapはoptionalを取り除くことができます.
let iconName = itemDesc["icon"] as? String
item.icon = iconName.flatMap { imageName in UIImage(named: imageName) }

そのため、このアプリケーションではflatMapがこれらのことをしました.-iconNameがnilであれば、UIImageではなくnilに直接戻りますか?戻る-iconNameに値がある場合、flatMapはiconNameを使用してUIImageを作成しようとします.この場合、UIImageのコンストラクション関数が失敗した場合にのみnilが返されます.したがって、flatMapの戻り値はUIImageですか?要するに、UIImage??の結果がnilでなく、T->U?が成功した場合にのみ、itemDesc["icon"] as? Stringに非空の値がある.これは、UIImage(named: )を用いて構造方法をだまし取るよりも規則的である.
魔法:initを使用してクローズドパッケージを簡略化
Xcode 7の後にコンストラクタはitem.iconというpropertyによって露出することができるので,コードをより簡略化し,よりコンパクトにすることができる.つまり??はStringの戻り値UIImageのパラメータですか?この方法では、直接flatMapのパラメータにすることができ、閉パッケージを簡略化することができます.
let iconName = itemDesc["icon"] as? String
item.icon = iconName.flatMap(UIImage.init)

....この使い方はまだよく理解できていませんが、IOS 8以上でしか効かないようで、最後にありがとうございました!