简述Swift3.0开发者预览版(部分)

前言

对于开发人员来说,Swift3.0的变化会令你的程序几乎处处报错,目前Swift还在发展阶段并不能向下兼容,但是试想一下如果Apple没有追求更好的精神又怎么会作出如此多的更改。今天的重点就是带翻译的介绍Swift3.0的变化。

Swift3.0的变化( 部分)

SE-0002: 删除currying的func声明语法
柯里化函数声明语法func foo(x: Int)(y: Int) 的用处有限,实现复杂,所以说我们应该删除它。

  // Current:
  func curried(x: Int)(y: String) -> Float {
    return Float(x) + Float(y)!
  }

  // Proposed:
  func curried(x: Int) -> (String) -> Float {
    return {(y: String) -> Float in
      return Float(x) + Float(y)!
    }
  }

SE-0003: 函数参数中不再使用var关键字
对于函数参数来说,var和inout修饰方法会产生很多语义上的混淆。虽然这两者都可以让这个参数变成可修改的,但是只有inout方法才能让这个参数修改后真正的写会原始地址中。为了避免出现这个语义的混淆,swift3.0里函数参数中不再使用var关键字。
(ps:Swift新特性元组(Tuple)和其关键字inout之前写的笔记里面有介绍inout的功能)

func foo(var i: Int) {
    i += 1 // illegal
}
//上面方法会报错,可换成下面这种
func foo( i: Int) {
    var i = i
    i += 1
}

SE-0004: 移除自增运算符++和自减运算符—
Swift发展的早期,自增自减运算符就被引进了,它是从C语言搬过来的。当时增加这两个运算符的时候并没有太多的考虑。这份文件提供了一个新的外观,并最终建议我们完全移除它们,是因为它们自增自减运算符在运用的时候容易造成混淆。比如说 ++i,i++,--i,i--

// Current
x++

// Proposed
x += 1

SE-0005: 将Objective-C的API更好地接入到Swift中
SE-0006: 将API指南应用于标准库中
SE-0023: Swift API设计指南
大家都知道Swift诞生在Objective-C已经发展的比较成熟的情况下,为了保证oc开发人员能够比较成功的过渡到Swift,所以说在Swift的初期,很多的库名和方法名都尽量和oc的保持一致。Swift3.0做了很大的改变,有种在摆脱oc影子的趋势。举个🌰,Swift 2里面UIBezierPath API的一部分:

   class UIBezierPath : NSObject, NSCopying, NSCoding {
      convenience init(ovalInRect: CGRect)
      func moveToPoint(_: CGPoint)
      func addLineToPoint(_: CGPoint)
      func addCurveToPoint(_: CGPoint, controlPoint1: CGPoint, controlPoint2: CGPoint)
      func addQuadCurveToPoint(_: CGPoint, controlPoint: CGPoint)
      func appendPath(_: UIBezierPath)
      func bezierPathByReversingPath() -> UIBezierPath
      func applyTransform(_: CGAffineTransform)
      var empty: Bool { get }
      func containsPoint(_: CGPoint) -> Bool
      func fillWithBlendMode(_: CGBlendMode, alpha: CGFloat)
      func strokeWithBlendMode(_: CGBlendMode, alpha: CGFloat)
      func copyWithZone(_: NSZone) -> AnyObject
      func encodeWithCoder(_: NSCoder)
    }

Swift3.0里面相同的部分变成了:

 class UIBezierPath : NSObject, NSCopying, NSCoding {
      convenience init(ovalIn rect: CGRect)
      func move(to point: CGPoint)
      func addLine(to point: CGPoint)
      func addCurve(to endPoint: CGPoint, controlPoint1 controlPoint1: CGPoint, controlPoint2 controlPoint2: CGPoint)
      func addQuadCurve(to endPoint: CGPoint, controlPoint controlPoint: CGPoint)
      func append(_ bezierPath: UIBezierPath)
      func reversing() -> UIBezierPath
      func apply(_ transform: CGAffineTransform)
      var isEmpty: Bool { get }
      func contains(_ point: CGPoint) -> Bool
      func fill(_ blendMode: CGBlendMode, alpha alpha: CGFloat)
      func stroke(_ blendMode: CGBlendMode, alpha alpha: CGFloat)
      func copy(with zone: NSZone = nil) -> AnyObject
      func encode(with aCoder: NSCoder)
    }

SE-0007: 移除C语言风格的for循环(条件与增量下)

// Current
for var i = 0 ; i < 10 ; i++ {
    print(i)
}

// Proposed
for i in 0  ..< 10  {
    print(i)
}

SE-0008: 为可选序列增加一个Lazy的flatMap
已经被Swift 2.2接受!

SE-0016: 添加构造函数Int和UInt进行UnsafePointer和UnsafeMutablePointer之间的转换

图1.png

图2.png

SE-0017: 使用UnsafePointer去修改Unmanaged
标准库Unmanaged<Instance> struct 提供了一个类型安全的包装对象,这个对象不参与在ARC里面,它允许用户进行手动的retain或者release。

  • 下面的方法就是用于Unmanaged和UnsafePointer之间的转换
图3.png

SE-0019: Swift增加Testing
测试是现代软件开发的一个重要组成部分。集成的测试加入到Swift的Package Manager,将有助于确保一个稳定可靠的系统。

SE-0028: 更新Swift的debug标识符(例如:FILE等)
这一项建议重命名以下标示符:

图4.png

SE-0029: 从函数应用中,移除“tuple splat”表达形式
Swift3.0之前,除了可以使用典型的方法调用函数之外,我们还可以通过传入N个作为函数参数列表。不过这个鲜为人知的特性正在swift3.0中被移除,因为它仅是纯粹的语法糖而已。

图4.png

SE-0031: 调整inout声明的类型修饰

// Current
func swapMe<T>(inout a: T, inout b: T) {
    let temp = a
    a=b
    b = temp
}

// Proposed
func swapMe<T>( a: inout T, b: inout T) {
    let temp = a
    a=b
    b = temp
}

SE-0032: SequenceType添加first(where:)方法

图5 .png

SE-0033: 导入Objective-C的常量作为Swift类型
给出一个Objective-C文件的常量列表,添加一个属性,这个属性在Swift里面将作为一个枚举值或者一个结构体导入。使用RawRepresentable转换为原始类型。我们就可以使用更多类型安全的对象,这样也可以使我们的Swift(Objective-C)代码可读性更强,更容易上手。

SE-0034: 消除行控制的Debug标识符声明的歧义
在Swift的SE-0028改变被接受后,#line标识符指的是一个标识符映射到调用点的行数在文件中作为一个控制语句的一部分使用。这一项建议提议#setline去代替#line,为了符合这个要求:“一旦名称和语法是固定的,我们可以重命名指令和删除空格的规则”。

  • Swift使用下面的语法来定义行控制语句:
line-control-statement → #line
line-control-statement → #line line-number file-name
line-number → A decimal integer greater than zero
file-name → static-string-literal
  • 这项建议的具体设计如下:
line-control-statement → #setline
line-control-statement → #setline line-number file-name
line-number → A decimal integer greater than zero
file-name → static-string-literal­

SE-0037: 注释和操作符之间的交互
在确定一个操作者是否有前缀、后缀、或者中缀的处理上这里有一些不一致的意见。他们有时被视为空白,有时为非空白,这取决于他们对操作者的左或右,和注视本身的内容。这项建议提出了一套统一的规则,如何在这些情况下,加以分析。

SE-0039: 使Playground字面量现代化(Modernizing Playground Literals)

  • Color, image, and file的字面量目前表示为:
[#Color(colorLiteralRed: red, green: green, blue: blue, alpha: alpha)#]
[#Image(imageLiteral: localResourceNameAsString)#]
[#FileReference(fileReferenceLiteral: localResourceNameAsString)#]
  • 简化构造函数,消除潜在的语法冲突,并遵循Swift其他标识符的先例,提议了标识符:#colorLiteral, #imageLiteral, and #fileLiteral.
color-literal → #colorLiteral(red: unit-floating-point-literal, green: unit-floating-point-literal, blue: unit-floating-point-literal, alpha: unit-floating-point-literal)
unit-floating-point-literal → floating point number greater or equal to zero, less than or equal to one

image-literal → #imageLiteral(resourceName: image-resource-name)
image-resource-name → static-string-literal referring to image resource name

file-literal → #fileLiteral(resourceName: file-resource-name)
file-resource-name → static-string-literal referring to local resource name

然而这些参数的标签不适合实际的初始化,所以说使用以下相应的初始化:

protocol _ColorLiteralConvertible {
  init(colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float)
}

protocol _ImageLiteralConvertible {
  init(imageLiteralResourceName path: String)
}

protocol _FileReferenceLiteralConvertible {
  init(fileReferenceLiteralResourceName path: String)
}

SE-0040: 用冒号属性参数替换等号

// Current
@available(*, unavailable, renamed="MyRenamedProtocol")

// Proposed, using : instead of =
@available(*, unavailable, renamed: "MyRenamedProtocol")

SE-0043: 具有多个模式的“case”中的声明变量
当一个模式声明具有相同名字和类型的多个变量的时候,在Swift 2是会报错的(case labels with multiple patterns cannot declare variables. ),Swift 3.0将移除错误。这种改变减少了重复的代码,因此减少了错误。当变量没有定义时,它与多模式匹配是一致的。

SE-0044: 导入成员
Swift导入C的声明,允许Swift的代码和C语言的库和框架进行交互。但是这样导入APIs 会觉得交互方面不是那么自然。这项建议旨在提供一种机制为C API作者指定导入的函数和变量作为导入Swift类型成员的能力。

  • 举个🌰,Core Graphics C API
// Current
override func drawRect(rect: CGRect) {
    let context: CGContext = UIGraphicsGetCurrentContext()!
    let toCenter = CGPoint(x: bounds.width/2.0, y: bounds.height/2.0)
    let angle = CGFloat(M_PI / 16)

    var transform = CGAffineTransformIdentity
    for _ in 0..<32 {
        triangulateRect(bounds, inputTransform: transform, context: context)
        transform = CGAffineTransformTranslate(transform, toCenter.x, toCenter.y)
        transform = CGAffineTransformRotate(transform, angle)
        transform = CGAffineTransformTranslate(transform, -toCenter.x, -toCenter.y)
    }
    CGContextSetLineWidth(context, bounds.size.width / 100)
    CGContextSetGrayStrokeColor(context, 0.5, 1.0)
    CGContextDrawPath(context, .Stroke)
}

func triangulateRect(bounds: CGRect, inputTransform: CGAffineTransform,
        context: CGContext) {
    var transform = inputTransform

    // Triangle from top left corner, to bottom middle, to top right, and then
    // draw the boundary
    let topLeft = bounds.origin
    let bottomRight = CGPoint(x: bounds.size.width, y: bounds.size.height)
    let path = CGPathCreateMutable()
    CGPathMoveToPoint(path, &transform, topLeft.x, topLeft.y)
    CGPathAddLineToPoint(path, &transform, CGRectGetMidX(bounds), bottomRight.y)
    CGPathAddLineToPoint(path, &transform, bottomRight.x, topLeft.y)
    CGPathAddLineToPoint(path, &transform, topLeft.x, topLeft.y)
    CGPathAddLineToPoint(path, &transform, topLeft.x, bottomRight.y)
    CGPathAddLineToPoint(path, &transform, bottomRight.x, bottomRight.y)
    CGPathAddLineToPoint(path, &transform, bottomRight.x, topLeft.y)
    CGContextAddPath(context, path)
}
// Proposed
override func drawRect(rect: CGRect) {
    let context: CGContext = UIGraphicsGetCurrentContext()!
    let toCenter = CGPoint(x: bounds.width/2.0, y: bounds.height/2.0)
    let angle = CGFloat(M_PI / 16)

    var transform = CGAffineTransform.identity
    for _ in 0..<32 {
        triangulateRect(bounds, inputTransform: transform, context: context)
        transform = transform.translate(toX: toCenter.x, toY: toCenter.y)
                             .rotate(angle: angle)
                             .translate(toX: -toCenter.x, toY: -toCenter.y)
    }

    context.lineWidth = bounds.size.width / 100
    context.strokeColor = CGColor(gray: 0.5, alpha: 1.0)
    context.drawPath(mode: .Stroke)
}

func triangulateRect(bounds: CGRect, inputTransform: CGAffineTransform,
        context: CGContext) {
    var transform = inputTransform

    // Triangle from top left corner, to bottom middle, to top right, and then
    // draw the boundary
    let topLeft = bounds.origin
    let bottomRight = CGPoint(x: bounds.size.width, y: bounds.size.height)
    let path = CGMutablePath()
    path.move(transform: &transform, x: topLeft.x, y: topLeft.y)
    path.addLine(transform: &transform, x: bounds.midX, y: bottomRight.y)
    path.addLine(transform: &transform, x: bottomRight.x, y: topLeft.y)
    path.addLine(transform: &transform, x: topLeft.x, y: topLeft.y)
    path.addLine(transform: &transform, x: topLeft.x, y: bottomRight.y)
    path.addLine(transform: &transform, x: bottomRight.x, y: bottomRight.y)
    path.addLine(transform: &transform, x: bottomRight.x, y: topLeft.y)
    context.addPath(path)
}

SE-0046: 函数的所有参数声明方式要一致性,包括第一个参数声明方式

// 从第一个参数就必须指定参数名,除非使用"_"明确指出省略参数
func sum(num1:Int,num2:Int)->Int{
    return num1 + num2
}

sum(num1: 1, num2: 2) // old: sum(1,2)或者sum(1, num2: 2)

SE-0047: 默认在非Void函数返回类型下,返回结果未使用时会有警告
Swift3.0 中方法的返回值必须有接收不然会报警告,为了避免开发人员忘记接收返回值的情况,但是有些情况下确实不需要返回值可以使用"_"接收来忽略返回值。也可以增加@discardableResult声明,告诉编译器我这个方法是可以不用接收返回值的。

SE-0048: 泛型类型别名
Swift3.0提议之前,typealias是单一的,这也就限制了它,只能将某个特定的类型,通过typealias来定义成新的名字,而不能将整个泛型类型进行重命名。举个🌰:

class Person<T> {}
typealias WorkId = String
typealias Worker = Person<WorkId>

Swift3.0提议了可以将整个泛型类型进行重命名:

class Person<T> {}
typealias Worker1<T> = Person<T>

SE-0049: 将声明式@noescape与@autoclosure改为类型属性
这一项提议的意义和SE-0031的提议一样:提高一致性和减少冗余的语言。

 // Current
 // declaration attribute
func f(@noescape fn : () -> ()) {} 
func f2(@autoclosure a : () -> ()) {}

 //Proposed
//type attribute.
func f(fn : @noescape () -> ()) {}
func f2(a : @autoclosure () -> ()) {}

SE-0053: 从函数参数中移除let
默认情况下函数参数是不可变的,显示的声明函数参数是let,显得语法冗余了,所以说提议从函数参数中移除let。

// Current
func foo(let x: Int) { ... }

// Proposed
func foo(x: Int) { ... }

SE-0054: 废弃ImplicitlyUnwrappedOptional类型
这项提议我们要减少隐式解包可选类型(ImplicitlyUnwrappedOptional)的使用,因为Swift的类型设计是十分安全的,隐式解包可选类型破坏了这种安全性,所以说我们要减少使用隐式解包可选类型。只可以在以下几个地方使用:

  • 属性和变量声明
  • 构造器声明
  • 方法声明
  • 角标声明
  • 参数声明

未完待续……

推荐一篇文章:Swift3
本文所写的内容是看文档之后自己的理解,又不对的地方,欢迎指出。

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

推荐阅读更多精彩内容