Swift2.2更新内容

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309

What's new in Swift 2.2

Swift 2.2 is almost here, and cleans up a number of quirks, adds some missing features, and deprecates – perhaps controversially – some language features. This article goes over all the major changes, along with several minor ones, and gives you practical code examples so you can get up and running straight away.

If you liked this article, you might also want to read:

What's new in Swift 2.0?

What's new in iOS 9?

My free Swift tutorial series

Pre-order Pro Swift for just $20!

Watch my Swift 2.2 video

I made a video going over the key new features in Swift 2.2. You can read the original article below, or watch this video for my lightning summary. Feedback? Find me on Twitter @twostraws.

++ and -- are deprecated

Swift 2.2 formally deprecates the ++ and -- operators, which means they still work but you'll get a warning when you use them. Deprecation is usually a first step towards removing something entirely, and in this case both of these operators will be removed in Swift 3.0.

In their place, you need to use += 1 and -= 1 instead. These operators have been there all along, and are not going away.

You might wonder why two long-standing operators are being removed, particularly when they exist in C, C#, Java, and – critically to its "joke" – C++. There are several answers, not least:

Writing ++ rather than += 1 is hardly a dramatic time saving

Although it's easy once you know it, ++ doesn't have an obvious meaning to people learning Swift, whereas += at least reads as "add and assign."

C-style loops – one of the most common situations where ++ and -- were used – have also been deprecated, which brings me on to my next point…

Traditional C-style for loops are deprecated

Yes, you read that correctly: loops like the below will soon be removed entirely from Swift:

for var i = 1; i <= 10; i += 1 {

print("\(i) green bottles")

}

These are called C-style for loops because they have long been a feature of C-like languages, and conceptually even pre-date C by quite a long way.

Although Swift is (just about!) a C-like language, it has a number of newer, smarter alternatives to the traditional for loop. The result: this construct has been deprecated in Swift 2.2 and will be removed "in a future version of Swift."

Note: the current deprecation warning does not say it's removed in Swift 3.0, although I suspect it will be.

To replace these old for loops, use one of the many alternatives. For example, the "green bottles" code above could be rewritten to loop over a range, like this:

for i in 1...10 {

print("\(i) green bottles")

}

Remember, though, that it's a bad idea to create a range where the start is higher than the end: your code will compile, but it will crash at runtime. So, rather than writing this:

for i in 10...1 {

print("\(i) green bottles")

}

…you should write this instead:

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

print("\(i) green bottles")

}

Another alternative is just to use regular fast enumeration over an array of items, like this:

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for number in array {

print("\(number) green bottles")

}

Although if you want to be technically correct (also known as "the best kind of correct") you would write such a beast like this:

var array = Array(1...10)

for number in array {

print("\(number) green bottles")

}

Arrays and other slice types now have removeFirst()

The removeLast() method has always been helpful when working with arrays, but until now it's been missing a counterpart to remove items from the start of an array.

Well, Swift 2.2 is here to rescue you with the addition of the removeFirst() method. This removes the first element in an array, and returns it to you.

Looking back to the green bottles code above, you'll notice two quirks: first, I was using var rather than let, and second it was printing the grammatically incorrect message "1 green bottles".

Neither of these are a mistake, because I'm going to use them to demonstrate removeFirst():

var array = Array(1...10)

array.removeFirst()

for number in array {

print("\(number) green bottles")

}

Warning: whereas removeLast() has an optional equivalent, popLast(), there is no optional equivalent for removeFirst(). This means if you call it on an empty array, your code will crash.

You can now compare tuples (within reason)

A tuple is simply a comma-separated list of values, where each value may or may not be named. For example:

let singer = ("Taylor", "Swift")

let alien = ("Justin", "Bieber")

In older versions of Swift, you couldn't compare two tuples without writing some unwieldy code like this:

func ==  (t1: (T, T), t2: (T, T)) -> Bool {

return t1.0 == t2.0 && t1.1 == t2.1

}

It's not very user-friendly to require that kind of boilerplate code, and of course it would only work for tuples that have exactly two elements. In Swift 2.2, you no longer need to write that code because tuples can be compared directly:

let singer = ("Taylor", "Swift")

let alien = ("Justin", "Bieber")

if singer == alien {

print("Matching tuples!")

} else {

print("Non-matching tuples!")

}

Swift 2.2's automatic tuple comparison works with tuples with two elements just like the function we wrote, but it also works with tuples of other sizes – up to arity 6, which means a tuple that contains six elements.

(In case you were wondering: "arity" is pronounced like "arrity", but "tuple" is pronounced any number of ways: "toople", "tyoople" and "tupple" are all common.)

There are two reasons why Swift's tuple comparisons work only up to arity 6 (rather than arity 6 million). First, each extra comparison requires more code inside the Swift standard library. Second, using tuples that big is probably a code smell – switch to a struct instead.

You can see how tuple comparison works by changing our two tuples like this:

let singer = ("Taylor", 26)

let alien = ("Justin", "Bieber")

Be prepared for a very long error message from Xcode, but the interesting part comes near the end:

note: overloads for '==' exist with these partially matching parameter lists: ......

((A, B), (A, B)), ((A, B, C), (A, B, C)), ((A, B, C, D), (A, B, C, D)), ((A, B, C, D, E), (A, B, C, D, E)), ((A, B, C, D, E, F), (A, B, C, D, E, F))

As you can see, Swift literally has functions to compare tuples all the way up to (A, B, C, D, E, F), which ought to be more than enough.

Tuple splat syntax is deprecated

Staying with tuples for a moment longer: another feature that has been deprecated is one that has been part of Swift since 2010 (yes, years before it launched). It's been named "the tuple splat", and not many people were using it. It's partly for that reason – although mainly because it introduces all sorts of ambiguities when reading code – that this syntax is being deprecated.

In case you were curious – and let's face it, you probably are – here's an example of tuple splat syntax in action:

func describePerson(name: String, age: Int) {

print("\(name) is \(age) years old")

}

let person = ("Taylor Swift", age: 26)

describePerson(person)

But remember: don't grow too fond of your new knowledge, because tuple splats are deprecated in Swift 2.2 and will be removed entirely in a later version.

More keywords can be used as argument labels

Argument labels are a core feature of Swift, and let us write code like this:

for i in 1.stride(through: 9, by: 2) {

print(i)

}

Without the through or by labels, this code would lose its self-documenting nature: what do the 9 and 2 do in 1.stride(9, 2)? In this example, Swift also uses the argument labels to distinguish 1.stride(through: 9, by: 2) from 1.stride(to: 9, by: 2), which produces different results.

As of Swift 2.2, you can now use a variety of language keywords as these argument labels. You might wonder why this would be a good thing, but consider this code:

func printGreeting(name: String, repeat repeatCount: Int) {

for _ in 0 ..< repeatCount {

print(name)

}

}

printGreeting("Taylor", repeat: 5)

That uses repeat as an argument label, which makes sense because the function will print a string a number of times. Because repeat is a keyword, this code would not work before Swift 2.2 – you would need to write repeat instead, which is unpleasant.

Note that there are still some keywords that may not be used, specifically var, let and inout.

var parameters have been deprecated

Another deprecation, but again with good reason: var parameters are deprecated because they offer only marginal usefulness, and are frequently confused with inout. These things are so sneaky I couldn't resist adding one to my Swift language tests, although I will probably have removed them by the time you read this!

To give you an example, here is the printGreeting() function modified to use var:

func printGreeting(var name: String, repeat repeatCount: Int) {

name = name.uppercaseString

for _ in 0 ..< repeatCount {

print(name)

}

}

printGreeting("Taylor", repeat: 5)

The differences there are in the first two lines: name is now var name, and name gets converted to uppercase so that "TAYLOR" is printed out five times.

Without the var keyword, name would have been a constant and so the uppercaseString line would have failed.

The difference between var and inout is subtle: using var lets you modify a parameter inside the function, whereas inout causes your changes to persist even after the function ends.

As of Swift 2.2, var is deprecated, and it's slated for removal in Swift 3.0. If this is something you were using, just create a variable copy of the parameter inside the method, like this:

func printGreeting(name: String, repeat repeatCount: Int) {

let upperName = name.uppercaseString

for _ in 0 ..< repeatCount {

print(upperName)

}

}

printGreeting("Taylor", repeat: 5)

Renamed debug identifiers: #line, #function, #file

Swift 2.1 and earlier used the "screaming snake case" symbols FILE, LINE, COLUMN, and FUNCTION, which automatically get replaced the compiler by the filename, line number, column number and function name where they appear.

In Swift 2.2, those old symbols have been replaced with #file, #line, #column and #function, which will be familiar to you if you've already used Swift 2.0's #available to check for iOS features. As the official Swift review says, it also introduces "a convention where # means invoke compiler substitution logic here."

Below I've modified the printGreeting() function so you can see both the old and new debug identifiers in action:

func printGreeting(name: String, repeat repeatCount: Int) {

// old - deprecated!

print("This is on line \(__LINE__) of \(__FUNCTION__)")

// new - shiny!

print("This is on line \(#line) of \(#function)")

let upperName = name.uppercaseString

for _ in 0 ..< repeatCount {

print(upperName)

}

}

printGreeting("Taylor", repeat: 5)

For the sake of completion, I should add that you can also use #dsohandle, but if you know what dynamic shared object handles are you probably already spotted this change yourself!

Stringified selectors are deprecated

One unwelcome quirk of Swift before 2.2 was that selectors could be written as strings, like this:

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Tap!", style: .Plain, target: self, action: "buttonTaped")

If you look closely, I wrote "buttonTaped" rather than "buttonTapped", but Xcode wasn't able to notify me of my mistake if either of those methods didn't exist.

This has been resolved as of Swift 2.2: using strings for selectors has been deprecated, and you should now write #selector(buttonTapped) in that code above. If the buttonTapped() method doesn't exist, you'll get a compile error – another whole class of bugs eliminated at compile time!

Compile-time Swift version checking

Swift 2.2 adds a new build configuration option that makes it easy to combine code code written in versions of Swift into a single file. This might seem unnecessary, but spare a thought to people who write libraries in Swift: do they target Swift 2.2 and hope everyone is using it, or target Swift 2.0 and hope users can upgrade using Xcode?

Using the new build option lets you write two different flavours of Swift, and the correct one will be compiled depending on the version of the Swift compiler.

For example:

#if swift(>=2.2)

print("Running Swift 2.2 or later")

#else

print("Running Swift 2.1 or earlier")

#endif

Just like the existing #if os() build option, this adjusts what code is produced by the compiler: if you're using a Swift 2.2 compiler, the second print() line won't even be seen. This means you can use utter gibberish if you want:

#if swift(>=2.2)

print("Running Swift 2.2 or later")

#else

THIS WILL COMPILE JUST FINE IF YOU'RE

USING A SWIFT 2.2 COMPILER BECAUSE

THIS BIT IS COMPLETELY IGNORED!

#endif

New documentation keywords: recommended, recommendedover, and keyword

Swift supports Markdown-formatted comments to add metadata to your code, so you can write things like this:

/**

Say hello to a specific person

- parameters:

- name: The name of the person to greet

- returns: Absolutely nothing

- authors:

Paul Hudson

Bilbo Baggins

- bug: This is a deeply dull function

*/

func sayHello(name: String) {

print("Hello, \(name)!")

}

sayHello("Bob")

This metadata gets used in code completion ("Say hello to a specific person" gets shown as you type) and also in the quick help pane, which is where the other data is shown.

In Swift 2.2, three new keywords have been added: recommended, recommendedover, and keyword. These appear to be designed to make code completion more useful by letting you specify which properties and methods should return matches inside Xcode, but right now it doesn't appear to be working so that's only a hunch.

When things do suddenly spring into life – soon, I hope! – you can use them like this:

/**

Greets a named person

- keyword: greeting

- recommendedover: sayHelloToPaul

*/

func sayHello(name: String) { }

/**

Always greets the same person

- recommended: sayHello

*/

func sayHelloToPaul() { }

As you can see, recommended lets you say "prefer this other method instead", whereas recommendedover lets you say "prefer me over this other method."

Like I said, these don't appear to be functional in the current Xcode 7.3, but I filed a bug with Apple in the hope of getting some clarity around what these do, and will update this page when I find out more.

On the plus side, Xcode 7.3 does feature all-new code completion: you can now type something like "strapp" to have "stringByAppendingString" highlighted in the code completion, or "uitavc" to have "UITableViewCell" highlighted. It will take a little thinking to rewire your brain to use these text shortcuts, but it does promise a significant speed up for your coding.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,423评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,339评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,241评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,503评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,824评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,262评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,615评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,337评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,989评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,300评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,829评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,193评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,753评论 3 230
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,970评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,708评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,295评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,207评论 2 258

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 8,530评论 0 23
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的阅读 13,293评论 5 6
  • 学医。 -----------为什么要写这个文章:我的一个侄儿,现在高二,想要当医生。因为我和我堂妹经常抱怨医疗行...
    一条明阅读 228评论 0 1
  • 不知道从什么时候起,爱上了棉麻,亦或是是身体爱上了自由。它的简洁舒适,让我想起了返璞归真,人生最华丽的转身,莫过于...
    舒眉弯阅读 622评论 1 2
  • 你说你想一个人去尝尽世界美食 何时何地归期你也未曾留下笔迹 贝加尔湖畔餐馆传来筷子嘀嗒的音调 从我耳边略过 巴黎红...
    顺子叔叔阅读 272评论 0 0