Swift 4で私たちを待っているのは何ですか?

目次







  1. 一方向の範囲
  2. プライベート広告は、同じファイルの拡張子に表示されます。
  3. スマートウェイキー
  4. アーカイブとシリアル化
  5. 辞書とセットの改善
  6. MutableCollection.swapAtメソッド
  7. inoutサポートで削減
  8. 下付き文字のジェネリック
  9. NSNumberのブリッジ
  10. クラスとサブタイプのインスタンス


すべてを自宅で開始する方法は?



  1. サイトから最新のSwift 4スナップショットをダウンロードします
  2. インストーラーを実行する
  3. Xcode> Toolchains> Manage Toolchainsに移動し、スナップショットを選択します








一方向の範囲



SE-0172は、新しいRangeExpression



プロトコルと、下限または上限が定義されていない一方向範囲を定義するためのプレフィックス/ポストフィックス演算子のセットを追加します。







無限のシーケンス



一方向シーケンスを使用して、無限シーケンスを作成できます。 番号付けをゼロから開始したくない場合、これはenumerated()



より柔軟な代替です。







 let letters = ["a","b","c","d"] let numberedLetters = zip(1..., letters) Array(numberedLetters)
      
      





コレクションの添字



コレクションの添字で一方向のシーケンスが使用される場合、 startIndex



またはendIndex



は、それぞれコレクション内の欠落している上部または下部の境界を個別に「埋める」。







 let numbers = [1,2,3,4,5,6,7,8,9,10] numbers[5...] //  numbers[5..<numbers.endIndex]
      
      





パターン比較



パターン比較とは、一方向シーケンスがパターン比較構造で使用されるcase



です。たとえば、 case



switch



です。 ここでは、コンパイラがswitch



が冗長であることをまだ判断できないことに注意してください







 let value = 5 switch value { case 1...: print("greater than zero") case 0: print("zero") case ..<0: print("less than zero") default: fatalError("unreachable") }
      
      







複数行の文字列リテラル



SE-0168は、複数行の文字列リテラル( """



)の簡単な構文を導入します。複数行のリテラルでは、単一引用符をエスケープする必要がないため、JSONやHTMLなどの形式をエスケープせずに挿入できます。各行の先頭から削除されるスペースの数。







 let multilineString = """ This is a multi-line string. You don't have to escape "quotes" in here. The position of the closing delimiter controls whitespace stripping. """ print(multilineString)
      
      





print



の結果を確認するには、( 表示>デバッグ領域>コンソールのアクティブ化 )をクリックしてコンソールを表示できます。







行今コレクション



SE-0163は、Swift 4の改訂された文字列モデルの最初の部分です。最大の変更点は、文字列が(Swift 1.xで使用されていたように)コレクションであるということです。 (他のビュー、 UnicodeScalarView



UTF8View



、およびUTF16View



がまだ存在しています。)







SE-0163はまだ完全には実装されていないことに注意してください。今後さらに厳しい変更が加えられる予定です。







 let greeting = "Hello, !" //      .characters greeting.count for char in greeting { print(char) }
      
      





部分文字列-ラインスライスの新しいタイプ



行スライスインスタンスは、 Substring



タイプになりました。 String



StringProtocol



両方がStringProtocol



プロトコルを実装します。 ほとんどすべての文字列APIはStringProtocol



に存在するため、 String



StringProtocol



基本的に同じように動作します。







 let comma = greeting.index(of: ",")! let substring = greeting[..<comma] type(of: substring) // API  String    Substring print(substring.uppercased())
      
      





Unicode 9



Swift 4はUnicode 9をサポートし、現代の絵文字の適切な書記素クラスタリングの問題を修正します。 以下はすべて単一の文字になりました。







 "".count // person + skin tone "‍‍‍".count // family with four members "\u{200D}\u{200D}\u{200D}".count // family + skin tones "‍".count // person + skin tone + profession
      
      





Habraparserはすべての絵文字を飲み込んだのでこちらください







Character.unicodeScalars



プロパティ



これで、 Character



ポイントを文字列に変換せずに、文字ポイントに直接アクセスできます( SE-0178 )。







 let c: Character = "" Array(c.unicodeScalars)
      
      





プライベート広告は、同じファイルの拡張子に表示されます。



SE-0169はアクセス制御ルールを変更して、同じファイル内の親タイプの拡張子でプライベートアナウンスが表示されるようにしました。 これにより、タイプ定義をいくつかの拡張子に分割し、ほとんどの「プライベート」なものにプライベートアクセスを使用して、 fileprivate



アクセスfileprivate



必要性を減らすことができfileprivate









 struct SortedArray<Element: Comparable> { private var storage: [Element] = [] init(unsorted: [Element]) { storage = unsorted.sorted() } } extension SortedArray { mutating func insert(_ element: Element) { // storage   storage.append(element) storage.sort() } } let array = SortedArray(unsorted: [3,1,2]) // storage __   (   fileprivate) //array.storage // error: 'storage' is inaccessible due to 'private' protection level
      
      





スマートウェイキー



おそらくSwift 4の主な機能の1つは、 SE-0161で説明されている新しいキーパスモデルです。 Cocoa文字列パスキーとは異なり、Swiftパスキーは厳密に入力されます。







 struct Person { var name: String } struct Book { var title: String var authors: [Person] var primaryAuthor: Person { return authors.first! } } let abelson = Person(name: "Harold Abelson") let sussman = Person(name: "Gerald Jay Sussman") let sicp = Book(title: "Structure and Interpretation of Computer Programs", authors: [abelson, sussman])
      
      





パスキーは、ルートタイプから指定して、プロパティと名前の任意の組み合わせにドロップできます。







\Book.title



は、バックスラッシュで始まります: \Book.title



。 Swiftのすべての型は、 [keyPath: …]



- [keyPath: …]



の値を取得または設定するための添え字を受け入れます。







 sicp[keyPath: \Book.title] //        sicp[keyPath: \Book.primaryAuthor.name]
      
      





KeyPath



は、格納および操作できるKeyPath



オブジェクトです。 たとえば、パスキーにセグメントを追加して、さらに深くすることができます。







 let authorKeyPath = \Book.primaryAuthor type(of: authorKeyPath) let nameKeyPath = authorKeyPath.appending(path: \.name) //          sicp[keyPath: nameKeyPath]
      
      





パスキーの添え字



パスキーで添え字表記を使用することもできます。 コレクション、配列、または辞書を操作する非常に便利な方法。 この機能は、現在のスナップショットにはまだ実装されていません。







 //sicp[keyPath: \Book.authors[0].name] // INTERNAL ERROR: feature not implemented: non-property key path component
      
      





アーカイブとシリアル化



SE-0166:Swift Archival&Serializationは、Swiftの型(クラス、構造体、および列挙)がシリアル化およびアーカイブする方法を定義します。 Codable



プロトコルを実装することにより、型は(一度)アーカイブされるようにCodable



ます。







ほとんどの場合、必要なのはCodable



プロトコルの実装だけです。 コンパイラは、型のすべてのメンバーがCodable



実装する場合にのみ、実装自体の残りを生成できます。 型のシリアル化方法を変更する必要がある場合は、標準の動作をオーバーライドすることもできます。 このトピックには多くのニュアンスがあります-詳細については、オファーを確認してください。







 //     (   )   Codable struct Card: Codable { enum Suit: String, Codable { case clubs, spades, hearts, diamonds } enum Rank: Int, Codable { case ace = 1, two, three, four, five, six, seven, eight, nine, ten, jack, queen, king } var suit: Suit var rank: Rank } let hand = [Card(suit: .clubs, rank: .ace), Card(suit: .hearts, rank: .queen)]
      
      





コーディング



Codable



を実装する値がある場合、アーカイブするためにエンコーダーに渡す必要があります。







Codable



のインフラストラクチャを使用する独自のエンコーダーおよびデコーダーを作成できますが、SwiftはJSON( JSONEncoder



およびJSONDecoder



)およびプロパティのリスト( PropertyListEncoder



およびPropertyListDecoder



)の組み込みを提供します。 それらはSE-0167で定義されています。 NSKeyedArchiver



は、すべてのCodable



タイプもサポートします。







 import Foundation var encoder = JSONEncoder() //   JSONEncoder    encoder.dataEncodingStrategy encoder.dateEncodingStrategy encoder.nonConformingFloatEncodingStrategy encoder.outputFormatting encoder.userInfo let jsonData = try encoder.encode(hand) String(data: jsonData, encoding: .utf8)
      
      





デコード



 let decoder = JSONDecoder() let decoded = try decoder.decode([Card].self, from: jsonData)
      
      





Dictionary



Set



改善



SE-0165は、 Dictionary



およびSet



いくつかの機能強化を追加します。







シーケンス初期化子



キーと値のペアのシーケンスから辞書を作成します。







 let names = ["Cagney", "Lacey", "Bensen"] let dict = Dictionary(uniqueKeysWithValues: zip(1..., names)) dict[2]
      
      





Merge InitializerとMergeメソッド



これで、シーケンスからディクショナリが作成されるとき、またはシーケンスが現在のディクショナリにマージされるときに、重複キーがどのように処理されるかを決定できます。







 let duplicates = [("a", 1), ("b", 2), ("a", 3), ("b", 4)] let letters = Dictionary(duplicates, uniquingKeysWith: { (first, _) in first }) letters let defaults = ["foo": false, "bar": false, "baz": false] var options = ["foo": true, "bar": false] //      : error: generic parameter 'S' could not be inferred //       https://bugs.swift.org/browse/SR-922 //options.merge(defaults) { (old, _) in old }
      
      





デフォルト値の添え字



存在しないキーのデフォルト値を添え字の引数として定義して、戻り値のタイプをオプションにできません。







 dict[4, default: "(unknown)"] //      
      
      





これは、添え字を使用して値を変更する必要がある場合に特に重要です。







 let source = "how now brown cow" var frequencies: [Character: Int] = [:] for c in source { frequencies[c, default: 0] += 1 } frequencies
      
      





辞書固有のmap



filter





filter



Array



ではなくDictionary



を返します。 同様に、新しいmapValues



メソッドは、構造mapValues



維持しmapValues



mapValues



変換します







 let filtered = dict.filter { $0.key % 2 == 0 } type(of: filtered) let mapped = dict.mapValues { value in value.uppercased() } mapped
      
      





Set.filter



は、 Array



ではなくSet



も返します。







 let set: Set = [1,2,3,4,5] let filteredSet = set.filter { $0 % 2 == 0 } type(of: filteredSet)
      
      





シーケンスのグループ化



値のシーケンスを花束にグループ化します。 リスト内の単語を最初の文字で区切ります。







 let contacts = ["Julia", "Susan", "John", "Alice", "Alex"] let grouped = Dictionary(grouping: contacts, by: { $0.first! }) grouped
      
      





MutableCollection.swapAt



メソッド



SE-0173は、コレクション内の2つのアイテムを交換する新しい方法を導入しています。 既存のswap(_:_:)



とは異なり、 swapAt(_:_:)



メソッドは、( inout



引数を介して)要素自体ではなく、交換される要素のインデックスを受け入れます。







このメソッドを追加する理由は、2つのinout



引数との共有には互換性がないためです。

新しいSE-0176メモリアクセスルール。 既存のswap(_:_:)



関数swap(_:_:)



は、同じコレクションの2つの要素を交換するために機能しなくなります。







 var numbers = [1,2,3,4,5] numbers.swapAt(0,1) // Will be illegal in Swift 4 (not implemented yet) swap(&numbers[3], &numbers[4]) numbers
      
      





inout



サポートでreduce





SE-0171は、結果が入力関数としてcombine



関数に渡されるreduce



メソッドオプションを追加します。 これは、 reduce



と中間結果を排除することで、 reduce



を使用してシーケンスをインクリメンタルに構築reduce



アルゴリズムの大幅な加速になります。







SE-0171はまだ実装されていません







 //     extension Sequence where Iterator.Element: Equatable { func uniq() -> [Iterator.Element] { return reduce(into: []) { (result: inout [Iterator.Element], element) in if result.last != element { result.append(element) } } } } [1,1,1,2,3,3,4].uniq()
      
      





下付き文字のジェネリック



SE-0148に示されているように、添え字はジェネリックの形式で引数を受け入れて返すことができるようになりました。







正規の例は、 JSON



データを表す型です。一般的な添え字を定義して、呼び出し元のコードのコンテキストが期待される戻り値の型を決定できるようにすることができます。







 struct JSON { fileprivate var storage: [String:Any] init(dictionary: [String:Any]) { self.storage = dictionary } subscript<T>(key: String) -> T? { return storage[key] as? T } } let json = JSON(dictionary: [ "name": "Berlin", "country": "de", "population": 3_500_500 ]) //     as? Int let population: Int? = json["population"]
      
      





別の例: Collection



添字。一連のインデックスを受け取り、これらのインデックスの値の配列を返します。







 extension Collection { subscript<Indices: Sequence>(indices indices: Indices) -> [Iterator.Element] where Indices.Iterator.Element == Index { var result: [Element] = [] for index in indices { result.append(self[index]) } return result } } let words = "Lorem ipsum dolor sit amet".split(separator: " ") words[indices: [1,2]]
      
      





NSNumber



ブリッジ



SE-0170は、Swiftの数値型とNSNumber



間のブリッジに関するいくつかの危険な動作を修正します。







 import Foundation let n = NSNumber(value: UInt32(543)) let v = n as? Int8 // nil in Swift 4. This would be 31 in Swift 3 (try it!).
      
      





クラスとサブタイプのインスタンス



これで、SwiftのObjective-C UIViewController <SomeProtocol> *



に同等のコードを記述できます。

たとえば、特定のタイプの変数を宣言し、1つ以上のプロトコルに同時にバインドします( SE-0156 )。 構文let variable: SomeClass & SomeProtocol1 & SomeProtocol2









 import Cocoa protocol HeaderView {} class ViewController: NSViewController { let header: NSView & HeaderView init(header: NSView & HeaderView) { self.header = header super.init(nibName: nil, bundle: nil)! } required init(coder decoder: NSCoder) { fatalError("not implemented") } } //    NSView     // ViewController(header: NSView()) // error: argument type 'NSView' does not conform to expected type 'NSView & HeaderView' //    NSView ()      extension NSImageView: HeaderView {} ViewController(header: NSImageView()) // 
      
      






All Articles