Swift 3の新機胜

長い間知っおいるように、AppleはSwift 3をXcode 8に統合したした。これは、macOSずLinuxの䞡方で動䜜するオヌプン゜ヌス蚀語の最初のバヌゞョンです。 昚幎12月以降、Swift Evolutionで蚀語開発プロセスを実行し、IBMサンドボックスでそれを詊しおみた堎合、おそらく倚くの倉曎がそこに珟れおいるこずに気付いたでしょう。 Xcode 8で既存のプロゞェクトをコンパむルするずき、間違いなくコヌドが驚くこずでしょう。 しかし、それは修正可胜です。 新しい蚀語バヌゞョンでのいく぀かの倉曎に぀いお知りたしょう。
画像

新しいバヌゞョンの倉曎点は、䞻に2぀のカテゎリに分類できたす。


Xcodeバヌゞョン7.3で譊告を受け取ったずきに理解しやすく、おそらくこれらの機胜を満たしおいるため、リモヌト機胜のカテゎリから始めたしょう。

++および-挔算子


C蚀語の遺産の増分および枛分挔算子ずその機胜は単玔です-特定の倉数に1を加算たたは枛算したす。

var i = 0 i++ ++i i-- --i 

ただし、どちらを遞択するかを決定するこずになるず、事態はより耇雑になりたす。 これらはそれぞれ、プレフィックスずポストフィックスの2぀の可胜なオプションで衚すこずができたす。これらはすべお、゚ンゞンのおかげで機胜し、挔算子のリロヌドにより䜿甚たたは拒吊できる倀を返したす。

これは初心者には削陀されおいるので十分です-代わりに代入挔算子ず加算+ =および枛算-=を䜿甚しおください

 var i = 0 i += 1 i -= 1 

もちろん、加算+挔算子ず枛算-挔算子を䜿甚できるほか、代入挔算子も䞀緒に䜿甚できるため、コヌドを蚘述するずきの時間を節玄できたすが、

 i = i + 1 i = i - 1 

慣れる この倉曎の理由に぀いお詳しく知りたい堎合は、 Chris Latnerの提案を参照しおください 。

ルヌプを蚘述するためのC蚀語スタむルは歎史


むンクリメント挔算子ずデクリメント挔算子を䜿甚する最も䞀般的な䟋は、ルヌプを蚘述するためのC蚀語スタむルです。 挔算子を削陀するず、それらに関連するすべおのものが削陀されたす。これは、匏や挔算子を䜿甚しお範囲を指定した堎合ずは異なり、これらすべおを行うこずはできないためです。

たずえば、ある皋床の知識がある堎合は、おそらくforルヌプを䜿甚しお1から10たでの数字を衚瀺したす。

 for (i = 1; i <= 10; i++) { print(i) } 

Swift 3では、これは䞍可胜です。 これは圌のSwift 3のプロトタむプです-動䜜䞭の閉範囲挔算子...を芋おみたしょう

 for i in 1...10 { print(i) } 

あるいは、閉じた匏ず省略された匕数でfor-eachルヌプを䜿甚するこずもできたす 。詳现に぀いおは、 こちらを参照しおください 。

 (1...10).forEach {  print($0) } 

慣れる この倉曎の動機に぀いお詳しく知りたい堎合は、 Erica Sadunの提案を参照しおください 。

関数パラメヌタヌから倉数を削陀したした


関数パラメヌタヌは、関数内で倉曎する必芁がないため、通垞定数ずしお定矩されたす。 ただし、倉数ずしお宣蚀するず䟿利な堎合がありたす。 Swift 2では、 varキヌワヌドを䜿甚しお関数パラメヌタヌを倉数ずしおマヌクできたす。 パラメヌタヌをvarずしお指定するず、倀のロヌカルコピヌが䜜成されるため、関数の本䜓で倀を倉曎できたす。

䟋ずしお、次の関数は、䞎えられた2぀の数倀の最倧公玄数を決定したす。高校で数孊のコヌスを逃した堎合は、ここで詳现をお読みください。

 func gcd(var a: Int, var b: Int) -> Int { if (a == b) { return a } repeat { if (a > b) { a = a - b } else { b = b - a } } while (a != b) return a } 

アルゎリズムは単玔です。䞡方の数倀が既に等しい堎合、どちらかが返されたす。 それ以倖の堎合は、それらを比范し、倧きい方から小さい方を枛算し、結果が等しくなるたで倧きい方に割り圓おお、いずれかを返したす。 ご芧のずおり、aずbを倉数ずしおマヌクするこずにより、関数内の倀を倉曎できたす。

Swift 3開発者は関数パラメヌタヌを倉数ずしお蚭定できなくなりたした。Swift開発者はvarずinoutを混同する可胜性があるためです。 したがっお、Swiftの最新バヌゞョンでは、関数パラメヌタヌからvarが削陀されたす。

したがっお、Swift 3で同じgcd関数を䜜成するには、異なるアプロヌチが必芁です。 ロヌカル倉数の関数パラメヌタヌ倀を保存する必芁がありたす。

 func gcd(a: Int, b: Int) -> Int {  if (a == b) {    return a  }  var c = a  var d = b  repeat {    if (c > d) {      c = c - d    } else {      d = d - c    }  } while (c != d)  return c } 

この決定の理由に぀いお詳しく知りたい堎合は、元の文を読むこずができたす 。

関数パラメヌタヌのシヌケンシャルラベルの動䜜


関数パラメヌタヌリストはタプルです。そのため、タプル構造が関数プロトタむプず䞀臎する限り、それらを䜿甚しお関数を呌び出すこずができたす。 䟋ずしおgcd関数を取り䞊げたす。 次のように電話をかけるこずができたす。

 gcd(8, b: 12) 

たたは、次のように関数を呌び出すこずもできたす。

 let number = (8, b: 12) gcd(number) 

Swift 2でわかるように、最初のパラメヌタヌのラベルを指定する必芁はありたせん。 ただし、関数を呌び出すずきは、2番目およびその他のパラメヌタヌのラベルを指定する必芁がありたす。

この構文は初心者の開発者にずっおわかりにくいため、ラベルの動䜜を暙準化するように蚭蚈されおいたす。 Swiftの新しいバヌゞョンでは、次のように関数を呌び出すこずができたす。

 gcd(a: 8, b: 12) 

最初のパラメヌタヌのラベルを明瀺的に指定する必芁がありたす。 そうしないず、Xcode 8ぱラヌメッセヌゞを衚瀺したす。

この倉曎に察する最初の反応は、「OMG 既存のコヌドに倚くの倉曎を加える必芁がありたす。」 あなたは正しい。 これらはたくさんの倉曎です。 したがっお、Appleは、関数呌び出しパラメヌタヌの最初のラベルを抑制する方法を提䟛しおいたす。 以䞋に瀺すように、最初のパラメヌタヌに䞋線を远加できたす。

 func gcd(_ a: Int, b: Int) -> Int { ... } 

これにより、最初のラベルを指定せずに、叀いメ゜ッドを䜿甚しお関数を呌び出すこずができたす。 これにより、Swift 2からSwift 3ぞのコヌドの移行がはるかに簡単になりたす。

この倉曎の動機ず意図に぀いおは、 この文を読むこずができたす 。

文字列ずしおのセレクタヌは䜿甚されなくなりたした


ボタンをクリックしおアクションを実行しおみたしょう。ストヌリヌボヌドではなく、プレむグラりンドのみを䜿甚したす。

 // 1 import UIKit import XCPlayground // 2 class Responder: NSObject { func tap() { print("Button pressed") } } let responder = Responder() // 3 let button = UIButton(type: .System) button.setTitle("Button", forState: .Normal) button.addTarget(responder, action: "tap", forControlEvents: .TouchUpInside) button.sizeToFit() button.center = CGPoint(x: 50, y: 25) // 4 let frame = CGRect(x: 0, y: 0, width: 100, height: 50) let view = UIView(frame: frame) view.addSubview(button) XCPlaygroundPage.currentPage.liveView = view 

かなり倚くのむベントがそこで発生するので、それらを段階に分けたしょう。

  1. UIKitおよびXCPlaygroundフレヌムワヌクをむンポヌトしたす-ボタンを䜜成し、プレむグラりンド゚ディタヌで衚瀺する必芁がありたす。
  2. ナヌザヌがボタンをクリックしおタヌゲットを䜜成するずきに実行されるクリック方法を決定したすか セレクタはObjective-Cメ゜ッドでのみ機胜するため、ボタンの論理オブゞェクトはその基本クラスNSObjectです。
  3. ボタンの宣蚀ずプロパティの蚭定。
  4. 特定のサむズのビュヌを䜜成し、ビュヌにボタンを远加しお、プレむグラりンド゚ディタヌのアシスタントに衚瀺したす。

ハむラむトされたコヌドを芋おください。 ボタンセレクタヌは文字列です。 間違っお入力するず、コヌドはコンパむルされたすが、察応するメ゜ッドが芋぀からない可胜性があるため、実行䞭に倱敗したす。

朜圚的なコンパむル時の問題を修正するために、Swift 3はセレクタヌ文字列を#selectorキヌワヌドに眮き換えたした。 これにより、メ゜ッド名を正しく指定しないず、コンパむラヌが問題を早期に怜出できたす。

 button.addTarget(responder, action: #selector(Responder.tap), for: .touchUpInside) 

この倉曎の理由を理解するには、 Doug Gregorの提案を読んでください。

これはリモヌト機胜甚です。 次に、蚀語の近代化の䞻芁なポむントに移りたしょう。

文字列ずしおのキヌパス


この関数は前の関数ず䌌おいたすが、 キヌ倀コヌディング KVCおよびキヌ倀監芖KVOに関連しおいたす。

 class Person: NSObject { var name: String = "" init(name: String) { self.name = name } } let me = Person(name: "Cosmin") me.valueForKeyPath("name") 

゚ンコヌドのKey-Valueず䞀臎するPersonクラスを䜜成し、むニシャラむザヌによっお指定されたクラスで自分のIDを䜜成し、 KVCを䜿甚しお名前を蚭定したす。

繰り返したすが、間違った操䜜をするず、すべおが爆発したす

幞いなこずに、これはSwift 3では発生しなくなりたした。キヌパスは#keyPath匏に眮き換えられたした。

 class Person: NSObject { var name: String = "" init(name: String) { self.name = name } } let me = Person(name: "Cosmin") me.value(forKeyPath: #keyPath(Person.name)) 

この倉曎の理由を理解するには、David Heartsの提案を読んでください。

NSベヌスタむププレフィックスを削陀


基本タむプのNSプレフィックスを削陀したした。 仕組みを芋おみたしょう。 兞型的な䟋はJSONでの䜜業です

 let file = NSBundle.mainBundle().pathForResource("tutorials", ofType: "json") let url = NSURL(fileURLWithPath: file!) let data = NSData(contentsOfURL: url) let json = try! NSJSONSerialization.JSONObjectWithData(data!, options: []) print(json) 

基本クラスを䜿甚しお、ファむルに接続し、それに応じおJSON圢匏でデヌタを抜出できたす。NSBundle-> NSURL-> NSData-> NSJSONSerialization。

NSプレフィックスはSwift 3では䜿甚されないため、すべおバンドル-> URL->デヌタ-> JSONSerializationになりたす。

 let file = Bundle.main().pathForResource("tutorials", ofType: "json") let url = URL(fileURLWithPath: file!) let data = try! Data(contentsOf: url) let json = try! JSONSerialization.jsonObject(with: data) print(json) 

この呜名倉曎手順に぀いおは、 Tony ParkerずPhilip Hauslerによっお曞かれたこの文を確認できたす。

M_PI察.pi


䞎えられた半埄の円ず円の面積を蚈算したしょう

 let r = 3.0 let circumference = 2 * M_PI * r let area = M_PI * r * r 

Swiftの叀いバヌゞョンでは、 M_PIを䜿甚しおpi定数を瀺したす。 Swift 3は、定数piをFloat 、 Double 、およびCGFloat型に統合したす 。

 Float.pi Double.pi CGFloat.pi 

䞊蚘のコヌドスニペットは、Swift 3で次のように蚘述されたす。

 let r = 3.0 let circumference = 2 * Double.pi * r let area = Double.pi * r * r 

型掚論を䜿甚するず、型を省略するこずもできたす。 これが短いバヌゞョンです

 let r = 3.0 let circumference = 2 * .pi * r let area = .pi * r * r 

グランドセントラル掟遣


Grand Central Dispatchは、メむンスレッドのナヌザヌむンタヌフェむスをブロックしないネットワヌク操䜜に䜿甚されたす。 C蚀語で曞かれおおり、そのAPIは、非同期キュヌの䜜成や操䜜の実行などの単玔なタスクを実行するこずすら、初心者の開発者にずっお非垞に困難です。

 let queue = dispatch_queue_create("Swift 2.2", nil) dispatch_async(queue) { print("Swift 2.2 queue") } 

Swift 3は、オブゞェクト指向のアプロヌチを採甚するこずにより、すべおの定型コヌドず冗長な資料を排陀したす。

 let queue = DispatchQueue(label: "Swift 3") queue.async { print("Swift 3 queue") } 

この倉曎の詳现に぀いおは、 Matt Wrightをご芧ください。

コアグラフィックスがより迅速になりたした


Core Graphicsは匷力なグラフィックフレヌムワヌクですが、GCDに䌌たCスタむルのむンタヌフェむスを䜿甚したす。

 let frame = CGRect(x: 0, y: 0, width: 100, height: 50) class View: UIView { override func drawRect(rect: CGRect) { let context = UIGraphicsGetCurrentContext() let blue = UIColor.blueColor().CGColor CGContextSetFillColorWithColor(context, blue) let red = UIColor.redColor().CGColor CGContextSetStrokeColorWithColor(context, red) CGContextSetLineWidth(context, 10) CGContextAddRect(context, frame) CGContextDrawPath(context, .FillStroke) } } let aView = View(frame: frame) 

DrawRectメ゜ッドをオヌバヌラむドしおUIViewクラスを拡匵するこずにより、ビュヌフレヌムを䜜成したす。

Swift 3は完党に異なるアプロヌチを取りたす-最初に珟圚のグラフィックコンテキストを展開し、すべおの描画操䜜を実行しおから、それに関連付けられたす。

 let frame = CGRect(x: 0, y: 0, width: 100, height: 50) class View: UIView { override func draw(_ rect: CGRect) { guard let context = UIGraphicsGetCurrentContext() else { return } let blue = UIColor.blue().cgColor context.setFillColor(blue) let red = UIColor.red().cgColor context.setStrokeColor(red) context.setLineWidth(10) context.addRect(frame) context.drawPath(using: .fillStroke) } } let aView = View(frame: frame) 

泚 DrawRectを呌び出す前にコンテキストはれロになるため、ガヌド匏を䜿甚しおコンテキストを展開する必芁がありたす 。詳现はこちらをご芧ください 。

動詞ず名詞の呜名芏玄


文法の時間 Swift 3のメ゜ッドのグルヌプは、2぀のカテゎリに分類されたす。特定の意味を返すメ゜ッド-名詞を意味したす-ず特定のタむプのアクションを実行するメ゜ッド-動詞を意味したす。

10から1ぞの出力はここで実行されたす

 for i in (1...10).reverse() { print(i) } 

範囲を倉曎するには、 reverseメ゜ッドを䜿甚したす。 Swift 3は元の範囲を逆順で返すため、この操䜜を名詞ずしお扱いたす。 圌はメ゜ッドに接尟蟞「ed」を远加したす。

 for i in (1...10).reversed() { print(i) } 

配列の内容を衚瀺するためのタプル/タプルの最も䞀般的な䜿甚法

 var array = [1, 5, 3, 2, 4] for (index, value) in array.enumerate() { print("\(index + 1) \(value)") } 

Swift 3は、この配列の珟圚のむンデックスず倀を含むタプルを返し、それにサフィックス「ed」を远加するため、このメ゜ッドを名詞ずしお扱いたす。

 var array = [1, 5, 3, 2, 4] for (index, value) in array.enumerated() { print("\(index + 1) \(value)") } 

別の䟋は配列の゜ヌトです。 配列を昇順で䞊べ替える方法の䟋を次に瀺したす。

 var array = [1, 5, 3, 2, 4] let sortedArray = array.sort() print(sortedArray) 

Swift 3は゜ヌトされた配列を返すため、この操䜜を名詞ずしお扱いたす。 sortメ゜ッドは、 sortedず呌ばれるようになりたした 

 var array = [1, 5, 3, 2, 4] let sortedArray = array.sorted() print(sortedArray) 

䞭間定数を䜿甚せずに配列を゜ヌトしたしょう。 Swift 2では、次のように関数を呌び出すこずができたす。

 var array = [1, 5, 3, 2, 4] array.sortInPlace() print(array) 

sortInPlaceを䜿甚しお、可倉配列を゜ヌトしたす。 Swift 3は、倀を返さずに実際の゜ヌトを行うため、このメ゜ッドを動詞ずしお扱いたす。 アクションを説明する基本語のみを䜿甚したす。 したがっお、 sortInPlaceは sortず呌ばれるようになりたした 。

 var array = [1, 5, 3, 2, 4] array.sort() print(array) 

呜名芏則の詳现に぀いおは、 API Design Guidelinesをご芧ください。

Swift API


Swift 3はそのAPIに察しお単玔な哲孊を採甚しおいたす-䞍芁な単語を省略するために、䜕かが冗長であるかコンテキストから取り出せる堎合は削陀したす


列挙型


Swift 3は列挙をプロパティずしお扱うため、 upperCamelCaseではなくlowerCamelCaseを䜿甚したす。


@discardableResult


Swift 3では、関数たたはメ゜ッドの戻り倀を䜿甚しおいない堎合、Xcodeは譊告を衚瀺したす。 以䞋に䟋を瀺したす。

画像

䞊蚘のコヌドでは、 printMessageメ゜ッドは呌び出し元の受信メッセヌゞを返したす。 ただし、戻り倀は䜿甚されたせん。 これは朜圚的な問題になる可胜性があるため、Swift 3のコンパむラは譊告を衚瀺したす。

この堎合、凊理された戻り倀でない堎合。 メ゜ッド宣蚀に@discardableResultを远加するず、譊告を抑制するこずができたす。

 override func viewDidLoad() { super.viewDidLoad() printMessage(message: "Hello Swift 3!") } @discardableResult func printMessage(message: String) -> String { let outputMessage = "Output : \(message)" print(outputMessage) return outputMessage } 

おわりに


Swift 3がすべおです。Swiftの新しいバヌゞョンは、メゞャヌリリヌスの1぀であり、蚀語がさらに改善されおいたす。 既存のコヌドに確かに圱響を䞎える可胜性のある倚くの基本的な倉曎が含たれおいたす。 この蚘事が倉曎をよりよく理解するのに圹立぀こずを願っおいたす。たた、プロゞェクトをSwiftに移行する時間を節玄できるこずを願っおいたす。

Source: https://habr.com/ru/post/J312942/


All Articles