「Swift 2の新機能」例





Swift 2は、言語自体の改善、Objective-Cとの対話、およびコンパイルされたアプリケーションのパフォーマンスの改善に重点を置いていました。 Swift 2の新機能は、6つの異なる領域で提供されます。





Swift 2の新機能について、 Githubにコードが記載されているサンプルとともに紹介します。



1.基本的な言語構成



これ以上println()はありません



通常、コンソールにメッセージを出力するにはprintln()関数を使用しました。 Swift 2では、 print()のみを使用します 。 Appleはprintln()print()の両方を1つに結合しました。 print()関数は、デフォルトでは、「\ n」改行文字を使用してメッセージを印刷します。 必要に応じて、改行なしで行を印刷できます。







地図フィルター 、会社



Swift 1.2のコレクションを介してこれらの便利な関数とメソッドを定義することは、完全に一貫していませんでした。 Swift 1.2では、プロトコルでのデフォルトの実装は不可能であり、拡張はクラスに対してのみ行われたため、 CollectionTypeプロトコルのマップメソッドのデフォルトの実装はありませんでした。 したがって、部分的には、 mapArrayクラス( CollectionTypeプロトコルを実装する)のメソッドとして定義され、 Setクラス( CollectionTypeプロトコルを実装する)では定義されていません。 これに加えて、グローバルマップ関数が宣言されました。これは、最初のパラメーターとしてCollectionTypeのインスタンスを取りました。 これにより完全な混乱が生じました。



// Swift 1.2 let a: [Int] = [1,2,3] //    map   Array let b = a.map{ $0 + 1 } //      map  map([1,2,3]) { $0 + 1 } let set = Set([1,2,3]) //  ,    map   Set set.map{ $0 + 1 } //   map   Set map(set) { $0 + 1 }
      
      





コレクションのタイプに応じて、このコレクションのグローバルマップ関数またはマップメソッドのいずれかが使用されることが判明しました。 mapfilter、およびreduceメソッドと関数を使用して一連の変換を使用すると、一貫性がなく読みにくくなります。



Swift 2では、プロトコル拡張が許可されているため、 mapfilter &coはCollectionTypeのプロトコルレベルでプロトコル拡張として実装されています。 したがって、同じメソッドは、 ArraySet、またはCollectionTypeプロトコルを実装する他のコレクションで動作します。



 // Swift 2 let a: [Int] = [1,2,3] let b = a.map{ $0 + 1 } let set = Set([1,2,3]) let anotherSet = set.map{ $0 + 1 } let sum = (1...100) .filter { $0 % 2 != 0 } .map { $0 * 2 } .reduce(0) { $0 + $1 } print(sum) // prints out 5000
      
      





上記の例では、 フィルターRangeで機能することがわかります。 以前のバージョンでは、 RangeCollectionTypeプロトコルを確認しましたが、 フィルターメソッドは実装されていなかったため、これは機能しませんでした。 これで、あらゆるコレクションに対して、これらのメソッドの構文がはるかに理解しやすくなりました。



列挙型列挙



Swift 2では、 enumには印刷を可能にするのに十分な反射情報があります。







print(an)句はDragonを正しく印刷するようになりましたが、Swiftの以前のバージョンでは、出力は完全に有益ではありませんでした(Enum Value)



enumに関するもう1つの改善点は、Swiftがenumのさまざまなタイプの関連する値の表現を許可するようになったことです。 例として、Eightのタイプを合法的に想像できるようになりました。







これで、 enumは再帰的になります。つまり、 enumを使用してツリーを構築できます。 この例を見てみましょう:







ケースNodeの前に間接キーワードを使用する必要があります。 これにより、ツリーを作成できました。







これは次のようなものです。







これで、ツリー全体を再帰的にトラバースし、数値を追加する関数を作成できます。







21の結果が印刷されます。



診断



これに加えて、Swift 2は、不変のstructメソッドを使用してvarを変更しようとする開発者の試みを正しく検出する、初期化後にvarプロパティが変更されない、または関数呼び出しの結果が無視されたときなど、など



最も単純な変更の1つにより、コードが読みやすくなります。 ご存知のように、Swift開発者はvarを使用する変数としてではなく、 letを使用する定数として多くのものを宣言することを好みます。 しかし、誤ってvarキーワードを使用した場合はどうなりますか? または、変更する必要があると思いましたが、変更しませんでしたか? Xcode 7とSwift 2はどちらも、コードのどこでもこの変数を変更しないという警告を表示します。Xcodeは、変数の使用方法を文字通り調べ、変更したかどうかを確実に把握します。



複数のオプション



多くのオプションは多くのブール値を表す方法であり、Swift 1.xでは次のようになりました。



 viewAnimationOptions = nil viewAnimationOptions = .Repeat | .CurveEaseIn | .TransitionCurlUp if viewAnimationOptions & .TransitionCurlUp != nil { ...
      
      





このタイプの構文はCocoaで広く使用されていましたが、実際にはC言語の「遺物」に過ぎないため、Swift 2では削除され、多くのオプションに対する独自のタイプが提示されます。これはOptionSetTypeプロトコルです。







そのため、多くのオプションは、 Setまたはstructの任意のタイプになり、 OptionSetTypeプロトコルを確認できます。 これにより、多くのオプションを使用する場合の構文がより理解しやすくなります。







構文は、以前のバージョンのようにビット演算に依存せず、空のオプションセットを表すためにnilを使用しません。



現在、多くのOptionSetTypeオプションは、プロトコル拡張のデフォルト実装と呼ばれるSwift 2の別の機能に依存しているため、 OptionSetTypeプロトコルを確認するだけで、たとえばcontainsメソッドのデフォルト実装を取得できます。 minusInPlaceunionInPlaceおよびその他の集合演算。 プロトコル拡張については、後で説明します。



関数とメソッド



関数とメソッドを宣言するためのSwift 1.x構文は、関数への引数にラベルがないCと、メソッドの引数にラベルを付けるObjective-Cからそれぞれ派生した2つの異なる規則から継承されました。 あなたはそのような宣言を持っていました:



 func save(name: String, encrypt: Bool) { ... } class Widget { func save(name: String, encrypt: Bool) { ... } save("thing", false) widget.save("thing", encrypt: false)
      
      





Swift 2では、上記のコードは次のようになります。







したがって、関数はメソッドと同じ規則を取得しました。





ただし、これらの変更は、CおよびObjective-C APIからインポートされた関数には適用されません。



さらに、Swift 1.xで同じ内部と外部を持つパラメーターを指定するために使用されていた#optionオプションが削除されたため、パラメーターラベルを宣言するモデルがより便利になりました。



スコープ演算子



新しいdo句により、開発者は変数と定数のスコープを明示的に定義できます。 これは、すでに宣言されている名前を再利用する場合や、一部のリソースの早期リリースに役立つ場合があります。 do句は次のようになります。







Swift 1.xの以前のバージョンで導入されたdo ... while節とのあいまいさを避けるために、Swift 2では後者がrepeat ... whileに名前が変更されました。



ユニットテスト



Swift 1.xの単体テストコードの問題は、Swift 1.xを使用すると、単体テストで確認したいすべてのタグを公開することになります。 その結果、 パブリックマークは本来あるべきでない場所に残ります。 これはすべて、 テストターゲットアプリケーション ターゲットと異なり、 内部のアプリケーションのファイルがテストターゲットで使用できないためです。



Swift 2は、単体テストの大幅な軽減を達成しました。 Xcode 7は、特別な「テスト」モードでSwift 2コードを自動的にコンパイルします







すべての内部定義がpublicとして定義されているかのようにアクセスします。 これは、モジュールをインポートするときに@testable属性を使用して行われます。







それだけで十分です。「 パブリック」という言葉でラベルを付ける必要はありません。



さらに、これらの変更はアプリケーションのメインリリースには影響しませんが、パフォーマンスとアクセス制御の両方の点で正しい動作を維持します。



2.計算の順序の管理



Swift 2では、計算順序の管理と既存の設計の改善のための新しい概念が導入されています。



ガードオファー



ガード句は、 if句と同様に、条件式のブール値に応じてコードを実行します。 ブール値がtrueの場合ガード句に続くコードの実行を継続するように、 ガード句を使用します。



guard句は、本質的にif句の逆です。 私たちが書く場合



 if condition { // true  } else { // false  }
      
      





guardの場合、 trueブランチはfalseブランチよりも高いレベルに上昇します



 guard condition else { // false  } // true 
      
      





falseブランチは、閉じたコンテキストで実行を終了し、値を返すかエラーをスローすることに注意してください。 条件が満たされた場合にのみ、 真のブランチのコードが実行されることを保証します。



これにより、ネストされたif文によって形成される「スメトリピラミッド」を使用せずに、条件を反転せずに、致命的でない前提条件をチェックする自然な方法がガードになります。



従来のif句を使用した場合の典型的なコード実行パスがどのようになるかを見てみましょう。







jsonDictディクショナリはcreatePersonFromJSON関数入力に提供され、関連情報がディクショナリで提供されている場合はPerson構造の正しいインスタンスが出力で作成され、そうでない場合はnilが返されます。 この関数は、Swift 1.2で見られるように書かれています-if let構文を使用します。 このコードにはいくつかの問題点があります。 まず、メインコードからの正しい計算の方向を「オフにする」、つまり、「成功」(条件の観点から)計算の方向がif let句に「埋め込まれる」ことが判明しました。 第二に、 createPersonFromJSON関数 、必要なときに常にPersonのインスタンスを返すとは限りません。 Person構造には3つのプロパティが含まれており、そのうちの1つはOptionalです 。ただし、3つのキーすべてについて辞書から非nil値を取得した場合にのみ、関数は有効なPersonインスタンスを返します。 この関数を次のように書き換えましょう。アドレスが欠落している場合、つまりアドレスキーがnilを返す場合にPersonのインスタンスを返すことができるようにします。







機能をわずかに改善しました。 このバージョンのcreatePersonFromJSON2関数は、アドレスがnilであってもPersonのインスタンスを作成できるようになりました。 これはPersonの構造をよりよく反映していますが、現在では多くのif句があり、 nameageに割り当てられた最終値を拡張する必要があります。 新しいガードオファーでこれをどのように改善できるか見てみましょう。







guard句の場合、およびif let句の場合 、値の存在を確認し、値を「展開」して定数に割り当てることができます。 ただし、 guard let構文を使用すると、条件式の評価がtrueの場合、中括弧{}の後にコードの実行が継続されます 。 これは、追加の分岐コードを使用して値を展開することなく、関数の通常のスコープ内にPersonのインスタンスを作成できることを意味します。 nameまたはageの値のいずれかがnilである場合、コードはelse節にジャンプし、 nilを早く返します。



guardを簡単に見てみましょう。





延期条項





defer句は、 try句に関連付けられておらず、どこでも使用できることを除いて、 最終的に他のプログラミング言語に似ています。 defer {...}とコード内のどこかに書くと、計算制御がこの囲みスコープを離れるとこのブロックが実行され、コードが終了するか、リターンを受け取るか「スロー」するかは関係ありません「ミス。 deferステートメントは、 ガードおよびエラー処理(後述)でうまく機能します。



 guard let file1 = Open(...) else { //   file1 return } defer { file1.close() } guard let file2 = Open(...) else { //   file2 return } defer { file2.close() } //  file1  file2 . . . . . . . //      ,   
      
      





deferは、計算プロセスの通常の過程とfile2でエラーが発生した場合の両方でfile1に対して機能することに注意してください。 これにより、コードから多数の繰り返しが削除され、計算ブランチで何かを「クリア」することを忘れないようになります。 エラー処理も同じ問題に直面しており、この目的にはdefer句が最適です。



繰り返し-しばらく



Swift 2.0は、以前に使用されてdo-while節に構文上の変更を加えました。 do-whileの代わりに、 repeat-whileを取得ます。







これらの変更には2つの理由があります。



do-whileループを使用する場合、これが繰り返しの構成であることはすぐにはわかりません。 これは、 do句内のコードブロックが大きく、 while条件が画面外にある場合に特に当てはまります。 これを軽減するために、 doキーワードはrepeatに置き換えられました。これにより、これはコードの繰り返しブロックであることがユーザーに明確になります。



doキーワードには、Swift 2の新しいエラー処理モデルに新しい目的があります。これについては後で調査します。



パターンマッチング



Swiftは常に強力なパターンマッチング機能を備えていましたが、これはスイッチコンストラクトのみです。 スイッチコンストラクトは値valueを調べ、いくつかの可能なパターンと比較しました。 switch句の欠点の1つは、 valueのすべての可能なオプションを提供する必要があることです 。つまり、 switchステートメントは網羅的である必要があり、これは使用するのに不便です。 そのため、Swift 2は、以前はスイッチ/ケースのみが持っていたパターンマッチング機能を、計算の流れを制御する他の提案に移植しました。 ケースがそれらの1つである場合スイッチを使用してコードをより簡単に書き換えることができます。 他の提案は、ケースwhileケース用です。



ケースの場合のパターンマッチング



Swift 2の新機能は、 if (およびguard )句内でのパターンマッチングのサポートです。 最初に最も単純な列挙体Numberを定義してから、その使用方法を示しましょう。







1.特定のケース(ケース)の確認



ケースを使用します。値が特定のケースに一致するかどうかを確認します。 これは、このケースに関連付けられているかどうかにかかわらず機能しますが、値は復元されません(存在する場合)。







サンプルはcase .IntegerValueで始まり、このサンプルと一致する値である変数myNumberは等号の後に来ます。 これは直観に反するように思えるかもしれませんが、 if let a = a1構成のオプションa1を「拡張」するときに同じことがわかります。チェックされるa1の値は等号の後に来ます。



スイッチを使用した同等のSwift 1.2バージョンを次に示します。







2.関連する値を取得する



caseを使用します。値が特定のcaseに一致するかどうかを確認し、関連する値を抽出します。







「パターン」は、 ケースlet .IntegerValue(theInt)に変わりました 。 「パターン」に一致する値は、前の例と同じです。



以下は同じ概念を反映する例ですが、 guardを参照しています。 guardifの述語セマンティクス同一であるため、 パターンマッチングは同じように機能します。







3. where句を使用した選択



guard節のどの場合でも、追加の制限を提供するために(オプションの) where節を追加できます。 前の例のgetObjectInArray:atIndex:関数を変更してみましょう。







4.マッチング範囲







5.タプルタプルを使用する







6.述語が複雑な場合



Swift 2のif句は驚くほど機能していました。 カンマで区切られた多くの述語を持つことができます。 述語は、次の3つのカテゴリのいずれかに分類されます。





述語は定義された順序で評価され、述語を実行しないと、残りは評価されません。



ケースのパターンマッチング



パターン 一致は、 for -inループと組み合わせて使用​​できます。 この場合、私たちの意図は、シーケンスの要素を通過することですが、特定の「パターン」に対応する要素のみを通過することです。 以下に例を示します。







switch句の「パターン」と同様に、多くの関連する値を抽出でき、この関連する値に関心がない場合は_を使用できます。 必要に応じて、 where句を使用して制限を追加することもできます。



パターンマッチング



パターン マッチングは、 whileループでも使用できます。 この場合、述部の特定の値が「パターン」に対応するまで、ループの本体を繰り返します。 以下に例を示します。







セクション「6.」で説明されている複雑な述語に注意してください。 where ifの使用を含む、述語もwhileループでサポートされている場合は複雑です。



複数のラップを解除するためのパターン



Swift 1.2では、1つのシンプルなif let句で複数のオプションを「デプロイ」するための素敵でコンパクトな構文がありました。



 var optional1: String? var optional2: String? if let optional1 = optional1, let optional2 = optional2 { print("Success") } else { print("Failure") }
      
      





わあ!



ただし、既存の/欠落しているオプションのティーチングのさまざまな組み合わせを本当に管理する必要がある状況に直面しています。 そのような例の1つは、 ユーザー名パスワードのフィールドに入力するためのフォームであり、ユーザーはそれらのいずれかを入力せず、「送信」ボタンをクリックしました。 この場合、特別なエラーを表示して、特にスキップされたものをユーザーに通知します。 これを行うために、Swift 1.xでパターンスワッピングを使用できます!



 var username: String? var password: String? switch (username, password) { case let (.Some(username), .Some(password)): print("Success!") case let (.Some(username), .None): print("Password is missing") case let (.None, .Some(password)): print("Username is missing") case (.None, .None): print("Both username and password are missing") }
      
      





少し厄介ですが、最初から使用していました。



Swift 2では、構文はより明確に見えます。







一見、疑問符の使用はわかりにくいですか? 値が存在することを示すために(特に、値が存在する場合と存在しない場合にOptionalsのアイデアに関連付けられている場合)、この例は不器用な.Some(ユーザー名)構文とは対照的に非常に理解しやすいことを認める必要があります。



エラー処理



エラー処理に関連するSwiftの新機能を理解するには、関数が異常終了する可能性がある3つの方法があることを覚えておくと便利です(以降、簡潔にするために、専門用語に切り替えて「フォール」と言います)。





状況に関連したエラーの第三のタイプの加工-スウィフト2.を改善しようとしている



関数は、引数を受信したとき、我々はスウィフト1.xおよびObjective-Cの中の典型的な制御方式このようなエラーを考慮した場合、我々は、スキームを見つけるNSError inoutの?操作の成功またはエラー完了を表すBool返します



 //  error  ,    var error: NSError? // success  Bool: let success = someString.writeToURL(someURL, atomically: true, encoding: NSUTF8StringEncoding, error: &error) if !success { //     error: println("Error writing to URL: \(error!)") }
      
      





このアプローチには多くの「ダーク」な側面があり、メソッド自体が何をするのかを明確にしませんが、さらに重要なことには、返されたBoolの背後にあるものについては手動で規約を実装する必要があります。メソッドがオブジェクトを返し、エラーを受け取った場合、nilを返します。ブール値の場合、falseが返されます。どのメソッドを扱っているか、メソッドにNSErrorエラーオブジェクトが含まれている場合、結果がnilまたはfalseどうかを確認する必要がありますか?非常にわかりにくい構文。これらの困難はすべて、Objective-Cが関数またはメソッドから多くの値を返すことができなかったという事実に関連しています。エラーについてユーザーに通知する必要がある場合は、そのような処理方法を提供します。



Swift 2には新しいバグ管理が追加されました。NSErrorを置き換えるdo-try-catch構文を使用ます。この新しい構文の使用方法を見てみましょう。このようなエラーを処理する非常に簡単な例を考えてみましょう。これらのエラーは、オプションの返品によって返されます。値、および新しい構文は実際には意図されていません。しかし、この例の単純さにより、セマンティックコンテンツの複雑さではなく、「スローアウト」および「キャッチ」エラーのメカニズムに正確に注意を向けることができます。最後に、ネットワークからのデータを処理する実際の例を示します。



エラーをスローまたはキャッチする前に、エラーを特定する必要があります。あなたがでスウィフト2でそれを定義することができます列挙新しいプロトコルの実装、ERRORTYPEを







関数に







「»(スロー)エラーを投げることができ、あなたは、関数ヘッダのキーワードで広告を掲載する必要があるのthrows節







今、この機能は、キーワードを使用して、エラーをスローすることができます投げるそして、エラーの特定の種類へのリンク:





この関数を呼び出すしようとした場合、コンパイラはエラーを生成します。「と呼ばれる関数がエラーをスローし、それを参照するには、キーワードマークされていない試みをして何のエラー処理はありません。」







の機能は、エラーをスローすることが可能であることを発表しましたので、潜在的なエラーを「キャッチ」する必要があります。レッツ・キーワードを使用しようと試して







それは十分ではなかった、コンパイラは、構文を使用して製造される必要なエラーハンドリング、ということを教えてくれるん-のtry-catchを





また、ブロックで行う-のtry-catchあなたは「キャッチ」する機会を持っているいくつかのエラー:







エラーのセマンティック部分に興味がない場合、do-try-catchコンストラクトを使用する代わりに、関心のある値をオプションとして扱うことができます







aTryaTrySuccessオプションです。



特定の状況でのみ「落ちる」ことができるメソッドが存在する場合がありますが、使用方法によって「落ちる」ことはないことは確かです。その後、tryを使用できます



関数がエラーを「スロー」すると、すぐに戻ります。ただし、関数が戻る前にリソースを解放したりファイルを閉じたりするなど、何らかのアクションを実行する必要がある場合があります。この状況では、すでにおなじみのキーワードdeferが正常に機能します。キーワードで延期関数が返す常に実行されるコードのブロックを定義すると、エラーにより正常か戻っているかどうかは関係ありません可能。関数のどこにでもdeferブロック



を定義できます。さらに、複数の遅延ブロックを定義することもできます。この場合、それらは逆の順序で実行されます。例を見てみましょう:







Natasha Murashevの記事で紹介されている実際の例を検討します。 Swift 2.0:やってみましょうか?一部のAPIからのデータを考慮します(逆シリアル化後):







このデータは、アプリケーションで後で使用するためにモデルに変換する必要があります:TodoItemParser







パーサーは、APIからの混合データを処理し、アプリケーションで後で安全に使用できるように理解可能なモデルに変換し、エラーを検出すると「スロー」エラー:do-try-catchコンストラクトを使用して「良い」データをモデルに解析し、「悪い」データ解析します。do-try-catchコンストラクトを使用する代わりにtryステートメントで興味のある値をオプションとして扱うことができますか?































最初の部分では、Swift 2の新しい機能の一部のみを検討しました。- (スコープ)、引数構文



などの基本的な言語構造-パターンマッチング(パターンマッチング-エラー処理(エラー処理第二部では、我々は残りの部分を見ていきます:-アベイラビリティ(可用性利用可能なチェック-拡張機能(エクステンションを)プロトコル-対話をObjective-Cのと参考文献中古品:新スウィフトに特徴2 スウィフト2で私のようスウィフト2のA初心者のためのガイドスウィフト2.0でのエラー処理enum



scoping



































Swift 2.0: Let's try?

Video Tutorial: What's New in Swift 2 Part 4: Pattern Matching

Throw What Don't Throw

The Best of What's New in Swift



All Articles