我们期待的 Swift 3.0 将会是什么样?

我们期待的 Swift 3.0 将会是什么样? —— 此调查来自官方的 Swift 社区

【编者按】2015年6月,一年一度的苹果 WWDC
大会如期而至,在大会上苹果发布了 Swift
2.0,引入了很多新的特性,以帮助开发者更快、更简单地构建应用。本篇文章作者是
Maxime defauw ,本文中 Maxime 向大家简要介绍 Swift 2.0
中值得注意的新特性。本文系
OneAPM
工程师编译整理。

随着诸如协议扩展、错误处理等 Swift 2.0
新引入的强大特性发布,这都意味着苹果已经明确表示,它们非常积极地听取来自开发者社区的意见来帮助完善和改进这门语言。我们调查了几位使用
Swift 的开发者朋友,询问他们对下一个版本的 Swift
有何希冀,因此他们将在类型系统、协议以及工具等方面和我们一起分享他们的想法。

一年前,苹果推出了面向 iOS 和 OS X 的全新编程语言——
Swift。当听到它发布的时候,像千千万万 iOS
开发者那样,笔者的内心激动无比。正如宣传所说的那样,作为一门快速、安全的编程语言,Swift
已经成长为最流行的编程语言之一。一年之后,苹果不负众望,在2015年的 WWDC
会议中推出了 Swift 2.0。作者有幸去了现场,所以在这里向大家介绍一下 Swift
2.0 的新特性。

Sash Zats 

Labgoo、Wondermall 的
iOS 工程师、用户体验设计师及 API 架构师

「今年,我们将借助 Swift 2.0 乘风破浪。我们认为 Swift
即将成为最大的编程语言,并且成为下个二十年最不可或缺的应用和系统编程语言。任何人在任何地方都能使用
Swift 」,苹果公司软件工程副总裁 Craig Federighi 说道。

类型化的错误

我第一个期望就是类型化的错误(typed
error),虽然这个想法还很不成熟,但是却能给错误处理带来极大地改善。Swift
2
 引入了新的错误处理机制,但是遗憾的是,和语言中其他结构不同,错误结构并不是类型安全的。这样做的好处就是错误处理成为了函数签名(function
 signature)的一部分,比如说 do something()
do something() throws的类型并不相同,前者无法代替后者来使用;坏处就是
dosomething() throws
无法指明它能够抛出的错误类型(就像协议列表一样:throws<IOTypes, NetworkingError>)。

澳门新葡亰8455下载app 1

依赖类型

我的第二个期望是提供“依赖类型”(dependent
type)的支持。这个想法同样仍未完全在我的脑海中成型,不过我确信它将给现有的类型系统中带来全新的绝妙体验!它将给值类型本身加入限制,类型系统的解析方式为:未定类型的数组
-> 字符串数组 ->
只含有2个元素的字符串数组
。这对现有语言来说是一个极其有用的补充。下面的例子阐述了这个功能在什么地方比较有用:

class Car {
  var wheels: [Wheel]<4> = [Wheel(), Wheel()] 
  // 编译错误,类型不匹配,需要 4 个Wheel 类型
}

在 WWDC
大会上,苹果测量了分贝的新功能普及性。会议中两次最大的掌声,一次是苹果宣布
Xcode 7 支持 UI 测试,另一次则是 Swift 的开源。如果你错过 WWDC
的主题演讲,或者最近生活得压力山大,那么请你再确认一下,你没有看错:Swift
真的开源了。这可是件大事!下半年,苹果还将公开发布在 OSI 标准许可下的
Swift 的源代码,包括编译器和标准库。苹果也将开放 Linux
的源代码端口,开发者将能够促进语言的发展,并在 Linux 上编写 Swift
程序。由此看出,苹果鼓励开发者进一步推动 Swift 的发展。

Cocoa 的 Swift 分支

最后,我希望看到(不过很可能不会实现)Cocoa 的 Swift 分支版本。虽然
Cocoa
是一个很棒的框架集合,但是它自身携带的内容实在过于庞大,有可能会影响到
Swift 的开发方式。

我很想看到无需进行引用的结构体能够普遍应用到新的分支上来(在我的想象中,我认为诸如
 UIBarButtonItem、UINavigationItem
 之类的类应该不需要让你来累积它们的状态,因此它们可以被替换为结构体)。因此,我们就可以重新设计
 API,尽可能地使用枚举中关联值的优势。在某些情况下,枚举能够更精确地描述其作用:例如
UIDatePicker
 可以在一个属性中使用关联枚举,来同时表示其日期值和创建值所使用的模式。

class UIDatePicker {
  enum Value {
    case Date(date: NSDate)
    case CountDownTimer(period: NSTimeInterval)
  }
  var value: Value?
}

虽然这不大可能会发生,因为这种变化需要一个独立的团队为现有和新的 API
建立一个全新的版本,这个过程中需要耗费极大的努力。

我知道,我的这些想法和 Swift
团队正面临的实际问题和长期目标而言是非常的幼稚的,因为整个社区都知道他们所做的一切棒极了!

随着这一令人振奋的消息的发布,Swift 2.0
涵盖了更多新的功能,如升级的错误处理、协议扩展和可用性检查。下面我们就来看看这些新特性。

Jorge Ortiz

PoWWaU 创始人,移动开发开发者及教师

##错误处理

更好的辅助工具

我希望有一套比较成熟的辅助工具。比如说,我希望有一个我可以永远信赖的调试器,而不是时不时出错的玩意儿。这个调试器能够在当前的堆栈帧显示某个
符号的实际值。此外,我还希望有一个能够对 Swift 进行重构的编辑器,就像在
Objective-C
中所做的那样,这样我就可以在它的帮助下改善我的代码,比如说将一些语句提取到方法中,或者重命名项目中某个类或方法的名称。

这个编辑器需要能够生成代码,将我从代码套路中拯救出来(我的意思不是指代码片段)。例如,如果编译器发现我的类或者结构没有完全实现某个协议,那么我希望有一个选项能够让编辑器自动将定义中所缺少的方法创建出来。

程序总会出错。当函数出现问题时,如果能找出哪里出错,便能理解为什么会出现异常。Swift
1.0 版本缺乏有效的错误处理机制。在 Swift 2.0 中,开发者可以利用 try /
throw / catch 关键字,建立异常处理模式。

完善的测试

第二个愿望非常简单,但是却能够让进行测试的人们感到由衷的高兴。我希望运行测试时无需使用模拟器,这样能够提升使用体验。如果某个类只基于
Foundation,那么对其的测试应该可以无需模拟器就可以进行。这将减少需要运行的测试套件,使测试花费的时间更短。

假设你正在加入汽车引擎模型。引擎可能由于某些原因导致失败:

内省机制

第三个愿望就涉及到语言本身了。我希望 Swift
拥有更好的内省(Introspection)能力,如果你愿意的话也可以称之为反射(reflection)。此外,还希望其拥有更加动态化的调度机
制。没有了这些特性,诸如 Mocking 框架之类的工具将无法被创建出来。

  • 没油;
  • 漏油;
  • 低电量。

Sam Giddins

UChicago 2018. CocoaPods. Bundler.

在 Swift 中,错误可以看做符合 ErrorType
协议的类型值。在这种情况下,你可以创建立一个符合 ErrorType
的枚举模型来表示错误情形:

高阶泛型类型

澳门新葡亰8455下载app,首先我需要向大家道个歉,因为你可能会很反感我们这些骄傲的开发者需要向
Swift 团队乞求我们所希望的 Swift 3
新特性。不过我觉得实现这个特性是最为重要的,因此无论怎样我都在所不辞。

由于高阶泛型类型(High-Kinded
Type)是一个难以理解的东西,因此我打算用我们最喜欢的函数式编程比喻——卷饼,来为大家解释。我们知道,我们可以用同样的方式吃各种各样的卷饼,无
论里面的内容如何,因为卷饼本身只是内部填充物的一个包装而已。但是,如果我们有这样一个方法告诉
Swift,“这里是一个对象,我唯一关心的事情只是它是一个卷饼,无论里面卷了牛排还是蔬菜还是虾,我都只关心它是一个卷饼。”然而
Swift
并不能让你轻易做到,如果你要吃某个卷饼的话,你首先需要这么做:“拥有相同填充物的卷饼是相同的”。这样的话,你会发现你能使用的卷饼为数甚少……

我们勉为其难地说目前 Swift
的上层结构类型并不能让我们这样表示。并没有任何办法写出关于 Monad 或者
Functor
的定义,这些定义可以用在该类型的所有实例当中,举个例子,这意味着我们所添加的每个全新的
SequenceType,都必须表示为 S: Equatable when S.Element: Equatable
的形式。这让代码重复量十分可怕,这意味着我们不能将我们的真实目的编码到类型系统中,导致我们程序员有更多犯错和制造
bug 的情况发生。

enum CarEngineErrors: ErrorType {
    case NoFuel
    case OilLeak
    case LowBattery
}

Jacob Schwartz

Glint 首席工程师

构造一个可以抛出异常的函数,在声明中使用 throws 关键字,如下例所示:

取消 Xcode 和 Swift 版本的关联

我很高兴能够看到 Swift
语言演变至今,我认为它的团队正在做一个十分了不起的工作,并且他们能预测到我们的需要,并且对大众反馈做出反应。

对于 Swift 3.0 来说,我很希望能够从不同版本的 Xcode
中使用这门语言。我并没能够完全深入地研究 Swift 2.0,因为它只能够在 Xcode
7上面使用,而 Xcode 7 取消了支持 iOS7 。将 Xcode(以及 iOS SDK)和 Swift
版本关联起来会造成不必要的惰性,阻碍开发者们迁移到新的语法当中。

所以不要让我们难以取舍,让我们在任何时候都能够用上最新的语言!

func checkEngine() throws {
}

Viktor Belenyesi

Prezi 首席 iOS/Mac 开发者

函数中抛出错误,你可以使用 throw
声明。下例代码演示了如何对引擎错误进行简单检查:

扩展中的存储属性

就像 Scala
的特性一样,如果我们能够给既有类中通过扩展添加新的存储属性的话,这将会是巨大的改进。我们可以用
ObjC
运行时来实现此功能,但是这种代码给我的感觉很不好,因为我每次都必须输入这样的鬼东西:

extension UIView {
  var myTag: String? {
    get {
      return objc_getAssociatedObject(self, "myTag") as? String
    }
    set(newValue) {
      objc_setAssociatedObject(self, "myTag", newValue, UInt(OBJC_ASSOCIATION_RETAIN))
    }
  }
}
let fuelReserve = 20.0
let oilOk = true
let batteryReserve = 0.0

func checkEngine() throws {
    guard fuelReserve > 0.0 else {
        throw CarEngineErrors.NoFuel
    }

    guard oilOk else {
        throw CarEngineErrors.OilLeak
    }

    guard batteryReserve > 0.0 else {
        throw CarEngineErrors.LowBattery
    }
}

Agnes Vasarhelyi

Prezi iOS/Mac 开发者

guard 关键词是 Swift 2.0 为了增强控制流首次引用的。当执行到 guard
语句时,首先会检查条件语句。如果条件为 false,则 else
部分会被执行。以上代码中,如果没有条件符合,函数将会抛出异常。

自定义泛型类型中的协变机制

Swift 中内置的类型已经是协变(covariant)的了,但是当涉及到自己创建的
Party
的时候,一般情况下就必须要给来宾名单中加入不同的人,不然的话这个设计就是失败的。

澳门新葡亰8455下载app 2

为了调用抛出函数,需要把 try 关键字放在函数调用之前。

Sam Ritchie

CodeSplice首席Codesplicer

func startEngine() {
    try checkEngine()
}

约束泛型的协议一致性

Swift 扩展有两个非常有用的功能,一个是能够增加协议的一致性(protocol
conformance),比如说在 Swift 1 中:

extension String: JSONEncodable {
  func toJSON() -> JSON { return .String(self)
   }}

另一个就是能够给协议增加泛型约束(generic constraints),比如说在 Swift 2
中:

extension Array where Element: JSONEncodable {
  func toJSON() -> JSON {
    return .Array(self.map { $0.toJSON() })
  }
}

很遗憾的是,你不能将这两者结合起来(即给约束泛型类型添加协议一致性),比如说:extension Array: JSONEncodable where Element: JSONEncodable
这种写法是无法通过编译的。这意味着如果你在尝试使用“面向协议编程”的话,你不仅需要避免使用泛型,还要花费大量的时间和精力来写重载函数。如果这项特性能够在
Swift 3 中实现的话,那么我相信它能拯救很多代码,让协议以及泛型更加有用。

如果在 Playgrounds 中写入以上代码,在处理异常之前已经出现错误。Swift
里的错误处理机制,需要使用 do-catch 语句来抓取异常并进行恰当处理。

Tony Arnold

Itty Bitty Apps 以及 The
CocoaBots 的首席开发者

我对语言本身其实没有太大的期望,不过如果能有类似 C#
之类的语言的异步风格函数(Async-Style
Function)的话,那就再好不过了。不过我最想看到的还是更好的辅助工具。在
Xcode 中使用 Swift
仍然是一件很痛苦的事情,比如说我无法使用重构,这让我感觉好像在使用几十年前的
IDE一般。如果能有更好的工具,并且有更清晰的错误提示的话,那无疑再好不过了。

同样我希望在明确需要使用 Optional.None
的地方让nil被禁用掉,不过这听起来像是我喝多了才会提出这个建议的。

说句实话,我并没有实实在在地思考过 Swift 3.0
的模样。标准库就已经很好很简洁了,如果它缺少什么东西的话,你实际上可以自己搭建出来。

下面的函数指定了捕获异常后的响应:

Benji Encz

Make School 工程师,即将入职
PlanGrid

func startEngine() {
    do {
        try checkEngine()
        print("Engine started", appendNewline: true)
    } catch CarEngineErrors.NoFuel {
        print("No Fuel!")
    } catch CarEngineErrors.OilLeak {
        print("Oil Leak!")
    } catch CarEngineErrors.LowBattery {
        print("Low Battery!")
    } catch {
        // Default
        print("Unknown reason!")
    }
}

类型化的错误处理

我最想看到的就是函数可以抛出他们能够产生的错误类型。目前苹果的建议是在函数的文档中写出这些错误类型,但是如果编译器也知晓这些错误类型的话那是不是
更好一些呢?这样就可以实现一个精确的错误处理,而不是使用一个 catch-all
的错误捕获。这同样可以让 API 中可产生错误的函数能更好地表述自己。

每个 catch
从句都匹配特定的错误,并且指定相关错误的响应机制。在上面的例子中,batteryReserve
变量被置为0,这种情况下调用 startEngine()将会抛出 .LowBattery 异常。

那么,你期望中的 Swift 3.0 是什么样子的呢?

转载自 realm.io

假如把 batteryReserve 重置为 1.0,这样就没有异常抛出,窗口打印「Engine
started」的提示信息。

类似于 switch 语句,Swift 2
的错误处理机制是完备的,你需要考虑到所有可能的错误情况。所以我们需要包含一个不指定类型的
catch 从句。

如果需要了解更多 Swift 的错误处理机制,推荐大家参考 Apple
Documentation。

##println()函数缺席

在作者写这篇介绍时,他注意到 println()函数的缺席。在 Swift 2.0
中,我们只需 print()函数便能打印到输出窗口。苹果公司将 println()和
print()函数合二为一。如果你想隔行输出,可以将 appendNewline 参数设为
true。如下面代码所示:

网站地图xml地图