`Swift 3.0 几乎改变了一切,如果直接拿Swift 2.2的代码在3.0的环境下构建则一定会报错,我们一定要做出相应的改变。
在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备。Swift 3.0的改变不仅仅是我下面的这个列表,但是列表中的每一项都是对你的一个巨大的打击。
预先警告#1:Swift 3.0 仍处于开发阶段。
预先警告#2:Swift 3.0 会有很多很多的变化,其中一些可能会在细微之处。然而,我们希望这些变化是一次性的。为了使Swift可以在未来几年更好的发展,在以后的版本更新中改变应该的显著变小。
预先警告#3:有些Swift 2.2的东西已经过时了,并且被删除了。这包括++,--,C风格的for循环,元组语法等等。
所有函数参数都有标签,除非你坚持
在Swift 2.0 中调用函数和方法已经做出了改变,在3.0中又发生了变化,而这一次的改变则是彻底的、抛弃旧我的!在Swift 2.0及以前的方法名是不需要为第一个参数设置标签的,所以第一个参数名称通常会内置到方法名称的最后,比如:
names.indexOf("Taylor")
"Taylor".writeToFile("filename", atomically:true, encoding:NSUTF8StringEncoding)
SKAction.rotateByAngle(CGFloat(M_PI_2), duration:10)
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
overridefuncnumberOfSectionsInTableView(tableView:UITableView) ->IntfuncviewForZoomingInScrollView(scrollView:UIScrollView) ->UIView?
NSTimer.scheduledTimerWithTimeInterval(0.35, target:self, selector:#selector(createEnemy), userInfo:nil, repeats:true)
在Swift 3.0中所有的所有的标签都是必须的,这也就代表着方法名不再含有参数的部分。在实际操作中,就是方法名的最后一部分被移入到了括号之中。
names.indexOf("Taylor")
names.index(of:"Taylor")
"Taylor".writeToFile("filename", atomically:true, encoding:NSUTF8StringEncoding)
"Taylor".write(toFile:"somefile", atomically:true, encoding:NSUTF8StringEncoding)
SKAction.rotateByAngle(CGFloat(M_PI_2), duration:10)
SKAction.rotate(byAngle:CGFloat(M_PI_2), duration:10)
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline)
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)
NSTimer.scheduledTimer(timeInterval:0.35, target:self, selector:#selector(createEnemy), userInfo:nil, repeats:true)
但,还是有一些连锁反应的方法:当我们连接到框架的时候,比如UIKit,这些方法希望在 Swift 3.0 中还是沿用旧有的“无第一参数名”的规则。在Swift 2.2 中:
override func viewWillAppear(animated:Bool)
override func tableView(tableView:UITableView, numberOfRowsInSection section:Int) ->IntoverridefuncdidMoveToView(view:SKView)
override func traitCollectionDidChange(previousTraitCollection:UITraitCollection?)
func textFieldShouldReturn(textField:UITextField) ->Bool
在 Swift 3.0中,他们都需要在第一参数前使用下划线标识它们使用ObjC代码,而不使用参数标签。
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 3.0 中另一个巨大的改变,因为在方法名中那些根本没有必要出现的词语将被移去。让我们看下面的这些swift 2.2中的代码:
letblue = UIColor.blueColor()
letmin = numbers.minElement()
attributedString.appendAttributedString(anotherString)
names.insert("Jane", atIndex:0)
UIDevice.currentDevice()
能看出代码中的问题吗?当我们使用UIColor的时候,blue当然是一个颜色,所以使用blueColor是多余的。当我们添加一个属性字符串到另一个的时候,这两个东东一定都是字符串,而不可能另一个是“大象”对吧!所以,相同的代码在Swift 3.0中就是:
letblue = UIColor.blue()
letmin = numbers.min()
attributedString.append(anotherString)
names.insert("Jane", at:0)
UIDevice.current()
正如你看到的,这个改变让方法名称更短了。
这种改变在字符串的操作上效果显著,对比下面的代码,你会发现Swift 2.2和Swift 3.0之间,我们写入的代码真是少了。
" Hello ".stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
" Hello ".trimmingCharacters(in: .whitespacesAndNewlines())
"Taylor".containsString("ayl")
"Taylor".contains("ayl")
"1,2,3,4,5".componentsSeparatedByString(",")
"1,2,3,4,5".componentsSeparated(by:",")
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 3.0的方法是下面这样:
dismiss(animated:true, completion:nil)
你可能会想,我们要dismiss什么呢?Swift 3.0是既要添加第一参数的标签,又要删除不必要的词,所以上面的代码实际是Swift 2.2中的
dismissViewControllerAnimated(true, completion:nil)
具有同样效果的还有prepareForSegue方法,在Swift 3.0 中它变成了这样:
overridefuncprepare(forsegue:UIStoryboardSegue, sender:AnyObject?)
对于枚举和属性,驼峰大写前缀被替换成了驼峰小写前缀
虽然与语法没有什么关系,但是我们对于类、结构、属性和枚举,始终遵循着一个约定:类、结构和枚举使用驼峰大写前缀,属性和参数名称使用驼峰小写前缀。这个约定也有例外,使用NSURLRequest(URL: someURL)
创建NSURLRequest对象的时候,参数就是大写URL。Swift 3重写了该方法为NSURLRequest(url: someURL)
,也意味着我们将会使用webView.request?.url?.absoluteString
方式来读取web view的URL。
还有一些是在属性部分,比如说CGColor
或CIColor
。是的,现在它将会变成cgColor
和ciColor
。
letred = UIColor.red().cgColor
这种变化确实提高了编码的一致性:所有的属性和参数应该都是以小写开始,没有例外!
同时,枚举也在发生着改变,从驼峰大写前缀改为驼峰小写前缀。这意味着:枚举是一个数据类型,但是枚举值更接近属性。然而,这意味着苹果的枚举现在都是小写了。
UIInterfaceOrientationMask.Portrait// old
UIInterfaceOrientationMask.portrait// new
NSTextAlignment.Left// old
NSTextAlignment.left// new
SKBlendMode.Replace// old
SKBlendMode.replace// new
Swift 引入 C 函数
Swift 3引入C函数的属性。比如,所有以CGContext开头的函数现在都被映射为CGContext对象上的属性方法,这样我们就可以不再使用令我们非常痛苦的CGContextSetFillColorWithColor()函数了。
swift 2.2中的代码:
let ctx = UIGraphicsGetCurrentContext()
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()
在Swift 3.0中CGContext被作为对象处理,我们可以直接调用方法了。
if let ctx = UIGraphicsGetCurrentContext() {
letrectangle = 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()
}
注意:不管是Swift 2.2还是Swift 3.0 UIGraphicsGetCurrentContext()返回的是可选CGContext,所以在Swift 3.0中使用CGContext对象的方法,必须先拆包。
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))
动词和名次
先让我们看一段代码
myArray.enumerate()
myArray.enumerated()
myArray.reverse()
myArray.reversed()
每个Swift 3的修改方法都添加了d,代表这个值正被返回。还有就是在数组排序的情况下。swift 2.2 使用 sort()
返回一个排序还的数组,而 sortInPlace()
则实现内部排序。在Swift 3.0中 sort()
变成了sorted()
,sortInPlace()
变成了sort()
。这也就意味这Swift 2.2中sort()
会返回数组,而在Swift 3.0中直接内部排序。