Swift3 改变了很多大量的内容,如果你的代码中不作出必要的改变肯定会被拒绝.如果你认为Swift从1.2和2.0的改变的是很大,那是因为你还没有看到3的改变.
本文中会尽可能通过代码来讲解Swift3的重要变化,更新代码的时刻已经到来了.
警告# 1:有很多的变化,其中一些看起来小。然而这些变化是一个一次性的事件,使语言更好地来,同时意味着在以后版本的变化是显着更小。
所有的函数参数标签
Swift2.0中的原有的函数和方法调用方式发生了彻底的改变.在Swift2.x及更早版本中,方法名称不需要设置第一个参数标签,现在调用方式必须显示显示设置第一个参数的标签,例如:
names.indexOf("Taylor")
"Taylor".writeToFile("filename", atomically: true, encoding: NSUTF8StringEncoding)
SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 10)
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
NSTimer.scheduledTimerWithTimeInterval(0.35, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
Swift3 要求所有的参数必须要设置标签,除非特别设置,通过方法名中的关于第一个参数的说明已经取去除.Swift2和Swift3对比:
names.indexOf("Taylor")
names.index(of: "Taylor")
"Taylor".writeToFile("filename", atomically: true, encoding: NSUTF8StringEncoding)
"Taylor".write(toFile: "somefile", atomically: true, encoding: String.Encoding.utf8)
SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 10)
SKAction.rotate(byAngle: CGFloat(M_PI_2), duration: 10)
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
UIFont.preferredFont(forTextStyle: UIFontTextStyle.subheadline)
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
override func numberOfSections(in tableView: UITableView) -> Int
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
func viewForZooming(in scrollView: UIScrollView) -> UIView?
NSTimer.scheduledTimerWithTimeInterval(0.35, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
Timer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
回调中,NSTimer的调用方式发生的改变,我们可以在FileManager
, Data, Date, URLRequest, UUID,NotificationCenter, 同样的我们会发现一些基础数据类型去除了“NS”前缀~
关于第一个标签的设置会导致一些连锁反应,当使用其他的框架如UIKit,他们期待原有的 "no first parameter name"规则在Swift 3.
这些是在Swift 2.2的签名:
override func viewWillAppear(animated: Bool)
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
override func didMoveToView(view: SKView)
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?)
func textFieldShouldReturn(textField: UITextField) -> Bool
Swift3中,第一个参数标签,通过下划线来设置,如下:
override func viewWillAppear(_ animated: Bool)
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
override func didMoveToView(_ view: SKView)
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
func textFieldShouldReturn(_ textField: UITextField) -> Bool
省略不必要的字符
当Swift在2015年12月开放源代码的时候,新的API标准包含三个决定性的话:“省略不必要的字。其中的变化,会使代码调用更加简洁.
Swift 2.2 例子:
let blue = UIColor.blueColor()
let min = numbers.minElement()
attributedString.appendAttributedString(anotherString)
names.insert("Jane", atIndex: 0)
UIDevice.currentDevice()
你能辨认出不必要的字符吗?当使用UIColor定义蓝色blue是必要的,blueColor是不必要的,Swift3中上面的代码:
let blue = UIColor.blue
let min = numbers.min()
attributedString.append(anotherString)
names.insert("Jane", at: 0)
UIDevice.current
对比之下,代码较之前更精简.
Swift2.2 和 Swift3 代码中字符串对比如下:
" Hello ".stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
" Hello ".trimmingCharacters(in: .whitespacesAndNewlines)
"Taylor".containsString("ayl")
"Taylor".contains("ayl")
"1,2,3,4,5".componentsSeparatedByString(",")
"1,2,3,4,5".components(separatedBy: ",")
myPath.stringByAppendingPathComponent("file.txt")
myPath.appendingPathComponent("file.txt")
"Hello, world".stringByReplacingOccurrencesOfString("Hello", withString: "Goodbye")
"Hello, world".replacingOccurrences(of: "Hello", with: "Goodbye")
"Hello, world".substringFromIndex(7)
"Hello, world".substring(from: 7)
"Hello, world".capitalizedString
"Hello, world".capitalized
警告: capitalized始终是一个属性,但是lowercaseString和uppercaseString已经被转换成lowercased()和uppercased()替换.
关于Swift的变化有很多,以上的对比并不是变化最大的,有些地方变化不是特别明显:
dismiss(animated: true, completion: nil)
第一眼看到dismiss时候,是不是想到 "dismiss what?" Swift 2.2中代码如下:
dismissViewControllerAnimated(true, completion: nil)
现在甚至是complete都是可选参数:
dismiss(animated: true)
同样的改变发生在 prepareForSegue() 方法中,现在如下:
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)
枚举和属性中的大小字母替换成小写字母
我们在使用类和结构体,枚举一直遵守着参数名称以大写字母开头,虽然大写字母与参数无关,Swift3中开始使用小写字母.Swift 2.2创建 NSURLRequest对象使用NSURLRequest(URL: someURL)
,注意大写字母"URL". Swift 3重写URLRequest(url: someURL)
,同时意味着将使用webView.request?.url?.absoluteString
来读取webview的返回参数.
当属性的名称的一部分是大写的时候就不是那么和谐,例如cgcolor
或cicolor
,Swift3中的调用方式如下:
let red = UIColor.red.cgColor
这种变化有利于驱动一致性,所有的属性和参数都应该以小写字母开头,也没有例外.
枚举同样在发生变化,从大写改变为小写,枚举是一个数据类型,意味着无论你使用的任何苹果的枚举都将小写:
UIInterfaceOrientationMask.Portrait // old
UIInterfaceOrientationMask.portrait // new
NSTextAlignment.Left // old
NSTextAlignment.left // new
SKBlendMode.Replace // old
SKBlendMode.replace // new
这种微小的改变涉及到了可选数据类型,原有的可选类型在枚举中:
enum Optional { case None case Some(Wrapped)}
如果项目中原有用到了Some,需要切换到度对应的some,当然也可以通过不使用some,以下代码供参考:
for case let .some(datum) in data {
print(datum)
}
for case let datum? in data {
print(datum)
}
Swift形式的C函数导入
Swift3中介绍了C函数的属性,允许开发者通过新的和简洁的方式导入C函数.例如,从“CGContext”映射属性的方式至一个CGContext对象.是的,这意味着原来类似CGContextSetFillColorWithColor()这种可怕的方法被移除.
为了证明这一点,以下是Swift2.2中的例子:
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
CGContextSetFillColorWithColor(ctx, UIColor.redColor().CGColor)
CGContextSetStrokeColorWithColor(ctx, UIColor.blackColor().CGColor)
CGContextSetLineWidth(ctx, 10)
CGContextAddRect(ctx, rectangle)
CGContextDrawPath(ctx, .FillStroke)
UIGraphicsEndImageContext()
在Swift3中CGContex可以被视作一个对象,你可以调用方式,而不是重复的使用CGContext,所有代码重写如下:
if let ctx = UIGraphicsGetCurrentContext() {
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
ctx.setFillColor(UIColor.red.cgColor)
ctx.setStrokeColor(UIColor.black.cgColor)
ctx.setLineWidth(10)
ctx.addRect(rectangle)
ctx.drawPath(using: .fillStroke)
UIGraphicsEndImageContext()
}
提示:在Swift2.2和Swift3.0中UIGraphicsGetCurrentContext()
返回了可空的CGContext,但是因为Swift3中方式的形式调用所以使用之前需要判空.
C函数的映射无处不在,比如说CGPDFDocument
的numberOfPages
属性,CGAffineTransform
如果写起来也是非常惊人的,以下是一些新老代码对比:
CGAffineTransformIdentity
CGAffineTransform.identity
CGAffineTransformMakeScale(2, 2)
CGAffineTransform(scaleX: 2, y: 2)
CGAffineTransformMakeTranslation(128, 128)
CGAffineTransform(translationX: 128, y: 128)
CGAffineTransformMakeRotation(CGFloat(M_PI))
CGAffineTransform(rotationAngle: CGFloat(M_PI))
动词和名词
Swift3中的动词和名词让人比较弄混,下面是比较重要的Swift3 API指南,读取来有点绕:
"When the operation is naturally described by a verb, use the verb’s imperative for the mutating method and apply the “ed” or “ing” suffix to name its nonmutating counterpart"
"Prefer to name the nonmutating variant using the verb’s past participle"
"When adding “ed” is not grammatical because the verb has a direct object, name the nonmutating variant using the verb’s present participle"
"When the operation is naturally des
Swift3相当于给我们上了一堂英语语法课,方法的改变很微妙,有时候会让人感到困惑。看一些简单的代码:
myArray.enumerate()
myArray.enumerated()
myArray.reverse()
myArray.reversed()
Swift3中在每个方法的最后都加入一个“d”,返回一个值.
当涉及到数组排序的时候这些规则有时候会导致混乱。Swift2.2中用sort()返回排序后的数组,并sortinplace()到位数组排序。Swift3,sort()更名sorted()(上述例子),和sortinplace()更名sort()。
Swift3的这些变化很容易阅读,其中一些是微小的,但是会引入大量的破坏,苹果让工程师的生活更加的建安,同时也会促进工程师的技能提升.
[https://www.hackingwithswift.com/swift3]