Swift3 新特性指南(二)
原文zh.annas-archive.org/md5/c0f6221d9eaed9c721bfc5570e07d639译者飞龙协议CC BY-NC-SA 4.0第九章使用 Xcode 服务器和 LLDB 调试改进您的代码您可以通过学习如何测试代码来提高代码质量的最大技能之一。使用XCTest测试框架将单元测试添加到您的代码中将帮助您提高代码质量并提供了记录代码工作方式的额外好处。当您从个人开发者项目过渡到多成员团队时维护独立编写的测试变得更加困难。将自动化测试添加到服务器上的持续集成管道中可以帮助解决这些问题就像源代码库帮助管理大型项目中的代码一样。在本章的第一部分我们将介绍 Xcode 服务器作为持续集成服务器的能力以及如何将自动化测试包含进来以改进您的测试工作流程。在第二部分我们将描述如何使用 LLDB 在 Linux 上调试您的代码。使用 Xcode 服务器进行持续集成概述使用基于服务器的测试具有几个好处这些好处可能足以证明您团队在时间投资上的合理性。如果您对是否走这条路适合您的团队持怀疑态度请确保在评估时考虑以下因素将构建和单元测试移至服务器可以释放您的本地机器继续工作在功能开发和调试上同时您的构建和测试套件在远程运行。构建触发器可以在代码提交时运行测试并在测试失败导致意外变化时通知您的团队。服务器上的测试是一致的每次都以相同的方式运行这意味着个人开发环境和项目调整不会影响测试运行。您可以安排完整的测试套件在您方便的时候运行以及短运行测试在每次代码提交时执行例如。您可以让您的测试在多个开发环境和硬件上执行。例如您可以使用服务器环境轻松地在多个 iPad 模型和操作系统版本以及几部 iPhone 上运行测试。这将是手动执行耗时的工作。持续集成工作流程是一个从在开发机器上本地开发开始然后将您的代码提交到仓库的过程。接下来您将项目迁移到 Xcode 服务器进行处理。为了使 Xcode 服务器能够处理您的代码您必须以bots的形式提供一些指令。在您的开发机器上您创建带有在 Xcode 服务器上运行的规则bots。bot的执行称为integration可以手动运行或根据计划运行。一旦integration完成活动将报告回您的开发 Mac。机器人功能没有使用机器人您无法利用 Xcode 服务器做任何有用的事情。机器人构建您的代码并运行您的测试使用提供的 Xcode 项目方案。一个精心制作的机器人可以控制其运行的时间和如何与您和您的团队沟通其活动。例如您可以让机器人在发生新的提交时运行并通过电子邮件将集成状态例如成功或失败发送给您和/或您的开发团队。您还可以添加预集成和后集成触发器这些触发器可以执行脚本以与 Web 服务通信或基于初始集成输出运行额外的性能测试。监控和管理机器人一旦您创建了您的机器人您就可以在 Xcode Server 中管理和监控它们。Xcode 服务器可以被配置为将机器人的状态推送到您的开发 Mac提供一个 web 钩子以在浏览器或第三方应用程序例如Slack/HipChat中查看活动或者发送电子邮件报告。在您的开发 Mac 上您可以使用 Xcode 中的报告导航器查看非常详细的报告。配置 Xcode 服务器要使用 Xcode 服务器您必须从 Mac 的 App Store 下载并安装 macOS Server以前称为 OS X Server。注意安装过程简单您可以在developer.apple.com/library/prerelease/content/documentation/IDEs/Conceptual/xcode_guide-continuous_integration/adopt_continuous_integration.html - //apple_ref/doc/uid/TP40013292-CH3-SW1找到详细的说明。为 Xcode 服务器添加仓库Xcode Server 需要一个代码仓库来执行工作并且与 Git 或 Subversion 兼容。你创建的任何机器人都需要访问仓库。机器人会尝试通过 SSH 或 HTTPS 连接到仓库。苹果公司对您的仓库设置选项做了很好的描述。注意您可以参考他们设置指南的以下部分以获取如何配置您的仓库以供 Xcode Server 和您的机器人访问的逐步说明developer.apple.com/library/prerelease/content/documentation/IDEs/Conceptual/xcode_guide-continuous_integration/PublishYourCodetoaSourceRepository.html - //apple_ref/doc/uid/TP40013292-CH8-SW1。配置机器人“机器人”是由 Xcode Server 运行以从源代码库构建和测试代码的过程。每次你运行你的“机器人”实例时你都在执行所谓的“集成”。你创建一个“机器人”并将一个关联的方案添加到“机器人”中该方案引用你的开发机器。创建“机器人”向导会引导你选择要使用的方案、设置运行频率以及提供在集成前后运行的任何 shell 脚本。注意你可以在[如何设置机器人](https://developer.apple.com/library/tvos/documentation/IDEs/Conceptual/xcode_guide-continuous_integration/ConfigureBots.html - //apple_ref/doc/uid/TP40013292-CH9-SW1)中了解更多信息。去年Xcode Server 引入了一个新功能允许我们添加自定义环境变量我们的“机器人”可以访问。今年 Xcode Server 允许我们添加在每次“集成”前后运行的预和后脚本。此功能可能允许你在“机器人”构建和执行测试之前预先加载外部文件或数据以进行单元测试。另一个例子可能是后“集成”脚本与 Rest API 通信以发送成功或失败状态。管理和监控你的集成运行你可以在 Xcode 的“报告导航器”中访问每个“机器人”的详细报告视图|导航器|显示报告导航器。此视图还允许你创建额外的“机器人”或编辑现有的“机器人”。选择侧边栏中列出的任何“机器人”都会给你一个集成结果的摘要报告。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/B05719_09_01.jpg报告导航器使用 LLDB 进行调试LLDB是驱动 Xcode 的调试器。在 Xcode 的调试控制台中你可以找到一个控制台窗口它为你提供了访问LLDB提示符的权限。在 Linux 或从命令行中你可以从 SwiftREPL访问LLDB。让我们探索如何使用LLDB通过一些你可能已经知道或不知道的命令来调试我们的程序。注意你可以在 LLDB 调试指南中了解更多关于使用 LLDB 进行调试的信息[LLDB 调试指南](https://developer.apple.com/library/prerelease/content/documentation/General/Conceptual/lldb-guide/chapters/Introduction.html - //apple_ref/doc/uid/TP40016717-CH1-DontLinkElementID_42).LLDB 命令语法与LLDB交互就像在提示符中输入一个命令一样简单。命令结构包含零个或多个子命令后跟零个或多个选项或参数。command[subcommand...][--option[option-value]]...[argument]...子命令和参数是空格分隔的标记而选项也是空格分隔的但使用双横线有时是单横线作为前缀。一个示例LLDB命令是设置一个函数的断点。在以下示例中我们将为speakToMe()函数设置一个breakpoint(lldb)breakpointset-n speakToMe你可以通过在LLDB提示符下输入help来始终获得帮助。不带参数输入help将列出所有可用命令及其简短描述(lldb)help你可以通过输入help加上命令名称或命令名称和子命令名称来获取特定命令的帮助以获得更专业化的结果。(lldb)helpbreakpoint(lldb)help breakpointset管理断点断点是中断正在运行的程序以在特定点进行检查的主要方式。我们可以通过LLDB创建、修改、删除或列出断点。创建断点我们使用breakpoint set命令来创建断点4funcsayHello(){5\.print(Hi)6\.}7sayHello()Hi8:breakpointset--name sayHelloBreakpoint1:where$__lldb_expr5__lldb_expr_4.sayHello()-()4at repl.swift:5,address0x00000001005c6064列出断点我们使用breakpoint list命令来列出程序中断点的名称和位置(lldb)breakpoint listCurrentbreakpoints:1:namesayHello,locations1,resolved1,hit count11.1:where$__lldb_expr5__lldb_expr_4.sayHello()-()4at repl.swift:5,address0x00000001005c6064,resolved,hit count1修改断点你可以使用断点添加激活条件。使用breakpoint modify命令你可以使用以下任何选项来更改目标断点的行为。-D(--dummy-breakpoints):SetsDummybreakpoints-Tthread-name(--thread-namethread-name)Thebreakpoint stops onlyforthe thread whose thread name matches this argument.-cexpr(--conditionexpr)Thebreakpoint stops onlyifthis condition expression evaluates totrue.-d(--disable)Disablethe breakpoint.-e(--enable)Enablethe breakpoint.-icount(--ignore-countcount)Setthe number of times this breakpointisskipped before stopping.-oboolean(--one-shotboolean)Thebreakpointisdeleted the first time it stop causes a stop.-qqueue-name(--queue-namequeue-name)Thebreakpoint stops onlyforthreadsinthe queue whose nameisgiven by this argument.-tthread-id(--thread-idthread-id)Thebreakpoint stops onlyforthe thread whoseTIDmatches this argument.-xthread-index(--thread-indexthread-index)Thebreakpoint stops onlyforthe thread whose index matches this argument.启用和禁用断点你可以使用断点 ID 或位置来启用和禁用断点。你将 ID 传递给enable或disable子命令(lldb)breakpoint enable1.11breakpoint enabled.(lldb)breakpoint disable1.11breakpoint disabled.删除断点当你不再需要你的断点时你可以简单地使用带有断点 ID 或位置的删除子命令来移除它(lldb)breakpoint delete1.1命令别名命令别名允许你为常用命令创建更短的语法。你还可以提供帮助文本来伴随你的别名。你可以通过输入help command来查看如何管理命令别名的更多详细信息。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_09_002.jpg在以下示例中我们创建一个命令别名来执行我们传递给别名的命令使用 Unix shellhttps://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_09_003.jpg摘要在本章中我们介绍了使用 Xcode Server 的持续集成工作流程的基本知识。你学习了什么是机器人以及它们是如何在 Xcode Server 上构建和测试你的代码的。随着 Swift 在 Linux 上的加入我们需要探索 Xcode 之外的其他测试代码的选项。LLDB 功能非常强大甚至为你的调试会话提供了定制选项。在我们下一章和最后一章中我们将讨论在 Linux 服务器上编写 Swift。第十章. 在服务器上探索 Swift除非您正在制作一个非常基础的应用程序否则您很可能需要某种形式的后端服务器来使您的应用程序真正有用。Swift 在 Linux 上运行是一个大事件尤其是考虑到 Linux 在托管和运行服务器方面的普及。Swift 3 为开发者打开了使用与他们在 iOS、macOS、tvOS 和 watchOS 上创建应用程序相同的 Swift 创建服务器端应用程序的可能性。在本章结束时您将拥有一个完全使用 Swift 编写的服务器端应用程序它可以在 Linux 服务器上无缝运行。IBM Swift 包目录在 第二章 中我们介绍了在 Linux 上安装 Swift 工具链和配置环境的步骤。我们用 Swift 编写了第一个程序并利用 Swift 包管理器来管理我们的依赖项。在完成基础知识后我想提及 IBM 的 Swift 包目录。IBM Swift 包目录是一个托管 Swift 库和模块链接的网站您可以使用 Swift 包管理器使用这些库和模块。IBM 希望它成为一个社区资源让开发者能够找到并分享他们项目的代码。您可以在以下链接中找到该网站developer.ibm.com/swift/the-ibm-swift-package-catalog。您绝对应该保留这个链接因为它将是一个您经常使用的网站。您可以根据排名、受欢迎程度或关键词探索项目。介绍我们的服务器项目让我们以一场盛宴结束对于最后一章我们将创建一个小项目来测试使用 Swift 开发服务器应用程序。我们将使用 IBM Swift 包目录来查找网络服务器框架。我非常喜欢使用 Slack 进行团队沟通。如果您还没有尝试过您应该考虑评估它是否可以成为您团队的好工具。Slack 的一个强大功能是您有一系列集成选项可以自定义团队体验。Slack 已经向开发者开放了许多 API以便进行定制和集成。Slack 甚至为用户提供了一个应用商店让他们可以添加第三方应用程序以便团队共同使用。唯一的缺点是您的第三方应用程序或集成必须托管在外部服务器上。我们将创建一个 Slack 集成您稍后可以将其修改成您自己的完整 Slack 应用程序。我们的 Slack 集成将完全使用 Swift 编写并且可以托管在云中的 Linux 虚拟机上例如 Heroku、Digital Ocean 或亚马逊网络服务。注意您可以从www.packtpub.com/support下载此项目的代码。项目描述和依赖项我们的项目需要一个能够正常工作的网络服务器框架。我们可以从头开始编写一个或者查看可用的第三方框架。使用 IBM Swift 包目录我找到了几个高度评价且正在积极开发且深受开发者喜爱的网络应用框架。IBM 的 Kitura、Perfect by PerfectlySoft 和 Vapor by Vapor 都是可行的候选框架。如果你曾经接触过 Node.js 和 Express或者 Ruby on Rails那么这些项目对你来说都会感到熟悉。虽然这些框架中的任何一个都可以用于我们的项目但我选择了 Vapor 项目作为我们的应用程序因为它在我编写这一章的时候在“基本”类别中排名首位。根据 Vapor 的说法他们的项目是最常用的 Swift 编写的网络框架。你可以了解更多关于 Vapor 的信息包括它支持的 Swift 版本和文档链接请访问swiftpkgs.ng.bluemix.net/package/vapor/vapor。现在我们已经介绍了我们将要使用的库和框架让我给你描述一下我们将一起构建的服务器应用程序。Slack 为开发者提供了创建自定义集成或制作可供任何团队使用的 Slack 应用程序的选项。我们将为单个团队创建一个自定义集成。然而你可以轻松地将我们的定制转换为任何团队都可以发现的全功能应用程序。我们将构建一个用于销售小工具的店面网络应用程序。当用户从我们这里购买小工具时我们将处理订单并将订单发送到我们的 Slack 订单跟踪频道。为了保持这个应用程序的简单性我们将采取一些捷径。设置我们的环境和项目由于你在第二章中学习了如何安装 Swift我们将跳过这一步直接进入安装 Vapor 框架。我们将添加 Vapor 的命令行工具包以便访问快捷命令和常见任务的辅助功能。注意你可以在vapor.github.io/documentation/找到详细的文档链接和使用 Vapor 的示例。这就是如何做的要安装工具包请在终端中运行以下命令curl-sL toolbox.vapor.sh|bash你可以通过运行以下命令来验证命令是否成功vapor-help接下来让我们创建一个新的 Vapor 项目并将其命名为storefrontvapor new storefront我们新创建的项目将具有以下文件结构https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_10_001.jpg文件结构应该对你来说很熟悉因为它遵循 Swift Package Manager 所需的结构。在幕后vapor 使用swift package init--type executable创建一个新的项目。Vapor 脚本还将在Package.swift中将 vapor 框架作为依赖项添加。我们的main.swift是我们的入口点因为我们创建了一个可执行程序。我打算在我的 Mac 上开发我的代码然后将其部署到云中的 Linux 虚拟机。对我来说好处是我可以使用 Xcode 及其调试工具进行本地开发。实际上Vapor 框架通过提供工具包中的命令来生成用于开发的 Xcode 项目支持这一概念。让我们创建一个可以用于我们店面应用开发的 Xcode 项目vapor xcode当 Vapor 创建一个配套的 Xcode 项目时它首先检查你是否缺少在Package.swift文件中指定的任何依赖项。在创建 Xcode 项目之前Vapor 会为你下载任何缺少的依赖项。此外Vapor 将创建一个用于在 Xcode 中运行你的应用程序的方案。最后Vapor 将显示 Xcode 项目期望链接的哪个工具链$vapor xcodeNoPackagesfolder,fetch may take awhile...FetchingDependencies[Done]GeneratingXcodeProject[Done]Selectthe App scheme to run.MakesureXcodeToolchains3.0-GM-CANDIDATEisselected.OpenXcodeproject?y/nnz每次你为项目创建新的依赖项时你必须重新构建项目以便 Swift Package Manager 可以在尝试编译你的代码之前下载你的新依赖项vapor clean or vapor build--clean让我们快速查看Package.swift文件看看 Vapor 为我们创建了什么。我们可以使用更适合我们项目的名称来配置应用程序的名称。当前的默认名称是VaporApp但我们可以将其更改为Storefront。你也应该注意到vapor 框架已作为依赖项为我们添加。importPackageDescriptionletpackagePackage(name:VaporApp,dependencies:[.Package(url:https://github.com/vapor/vapor.git,majorVersion:0,minor:18)],exclude:[Config,Database,Localization,Public,Resources,Tests,])当你使用 Vapor CLI 创建新项目时Vapor 会在项目中添加带有文档的示例代码。打开main.swift并浏览包含的路由和注释。删除此文件中的所有内容我们将从头开始构建我们的应用程序。Vapor 框架在 Vapor 术语中Droplet 是一个服务容器充当 Vapor 服务提供的网关。使用 Droplet 注册路由并添加中间件以启动服务器。为了开始我们需要导入 Vapor 并创建一个 Droplet 实例。importVaporletdropDroplet()我们还可以通过属性来定制我们的 Droplet 实例的行为。你可以在 Vapor 的文档中了解更多关于选项的信息。路由现在我们已经有了 Droplet 实例我们需要讨论路由。路由是每个 Web 框架的基本功能。当接收到一个传入请求时我们需要有一种适当过滤和处理每个请求的方法。Vapor 为你提供了多种解决路由问题的选项。我们将为我们的应用程序创建两个路由一个用于服务我们的商店页面另一个用于当用户在我们的页面上购买商品时响应post请求。在 Vapor 中一个基本的路由由一个方法、路径和闭包组成。我们的两个路由属于这一类别。Vapor 路由支持标准的 RESTful HTTP 方法get、post、put、patch、delete 和 options。我们通过在 Droplet 实例上调用相应的方法来注册路由传递我们的路由路径并返回我们定义的闭包。drop.get(/){requestinreturntrydrop.view.make(shop.html)}drop.post(purchase){requestin// more stuff happening here but omittedvarresponsetryResponse(status:.ok,json:json)returnresponse}我们的第一条路由处理我们网站根目录的所有get请求。当请求此路由时我们返回shop.html视图。我们的第二条路由处理/purchase路由的post请求。一旦我们完成工作我们就向请求者返回一个带有状态和 JSON 有效负载的响应。Vapor 还支持嵌套路由和参数。创建一个嵌套路由就像在注册路由时将 URL 中的正斜杠替换为逗号一样简单。// Nested routedrop.get(products,vehicles,trucks){requestinreturnYou requested /products/vehicles/trucks}Vapor 通过使参数类型安全来处理参数。许多 Web 框架默认使用字符串作为路由参数和类型这可能导致错误。使用 Swift 的闭包允许更安全地访问路由参数。在以下示例中我们定义了一个接受Int参数的路由。我们的路由匹配artboard/:id其中我们的*id*参数必须是一个整数值。// Type Safe parametersdrop.get(artboard,Int.self){request,productIdinreturnYou requested Artboard #\(productId)}我们也可以不使用路由参数来编写这个然后通过请求对象访问我们的参数。drop.get(artboard,:id){requestinguardletproductIdrequest.parameters[id]?.intelse{throwAbort.badRequest}returnYou requested Artboard #\(productId)}创建视图当你想从你的应用程序发送 HTML 时你创建视图。你可以从一个 HTML 文档创建视图或者使用 Mustache 等渲染器构建你的视图。默认情况下视图存储在Resources/Views目录中。回到为我们根目录注册的第一个路由我们使用视图返回一个 HTML 文档shop.html。你通过在 Droplet 实例上调用view.make方法来创建视图的实例。drop.get(/){requestinreturntrydrop.view.make(shop.html)}更复杂的文档如 mustache 模板需要更多信息来处理和创建视图。这些附加信息作为第二个参数传递给view.make方法。drop.get(shop_template){requestinreturntrydrop.view.make(shop.template,[countdown:2 days left,shopper_count:1,000])}公共资源对于大部分情况我们希望我们的服务器代码和文件免受窥探的眼睛和网页爬虫的侵害。Vapor 为我们处理这个问题。当我们需要提供可以从我们的视图中访问的资源时我们使用在应用程序根目录下创建的Public文件夹。我们将我们的图片、脚本和样式存储在Public文件夹的嵌套目录中。定义我们的商店视图当我们在应用程序上提供根级文档时我们返回一个shop.html视图。我们的简单页面显示一条欢迎信息和三个产品的详细信息。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_10_002.jpg当用户点击“立即购买”按钮时我们执行一个 jQuery Ajax post 命令与我们的服务器通信。我们将我们想要购买的产品 ID 发送到我们的/purchase路由。在服务器上当我们收到与这个路由匹配的请求时我们会提取产品 ID 并在我们的本地商店中搜索匹配的产品。当然在一个生产应用中我们会使用数据库来存储我们的产品甚至填充我们的商店列表。在无法在我们的请求对象中找到有效的产品 ID 或无法为提供的产品 ID 找到匹配的产品的情况下我们会抛出一个错误并将其发送回客户端。最后我们创建一个包含我们产品的一些详细信息的 JSON 负载并带有成功的状态码将其返回给客户端。drop.post(purchase){requestindrop.log.info(purchase request made)guardletproduct_idrequest.data[product_id]?.intelse{throwAbort.badRequest}guardletproductproducts.filter({(prod)-Boolinreturnprod.idproduct_id}).firstelse{throwAbort.badRequest}letjsontryJSON(node:[Product:\(product.name),price:\(product.price),])// more work happening and omittedvarresponsetryResponse(status:.ok,json:json)returnresponse}当我们的客户端收到 post 响应时我们会显示一个感谢用户购买的提示对话框。我们还在控制台中显示返回的 JSON 数据。Slack 集成现在我们已经了解了我们网络应用的基础让我们通过集成 Slack 来让它变得更有趣。使用 Slack 的 API我们可以扩展 Slack使我们的工作流程更加完善。在我们的案例中我们希望通知我们的运营团队新的订单以便他们可以立即开始处理。我们将利用 incoming webhooks 从我们的 Swift 服务器向 Slack 发送消息。虽然这个 webhook 只会用于我们的团队但你可以在api.slack.com/的文档中阅读并轻松地将我们的自定义集成转换为任何团队都可以将其纳入其工作流程的 Slack 应用。创建自定义集成由于我们的自定义集成只与单个 Slack 团队一起工作如果你还没有你需要创建一个 Slack 账户和团队。一旦你这样做你可以导航到 Slack 应用目录的构建部分位于点击“创建自定义集成”按钮。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_10_003.jpg接下来选择“Incoming WebHooks”链接。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_10_004.jpg选择一个频道来发布你的消息或者创建一个新的频道。我选择将我的消息发送到我的订单频道。选择好你的频道后点击“添加 incoming WebHooks 集成”按钮。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_10_005.jpg在这个视图中你可以看到设置说明以及你可以为你的用例自定义的字段。你可以为这个集成提供一个可选的描述性标签以及用户名。默认名称是incoming-webhook但我将其改为了OrderUp。我还添加了一个表情符号作为我添加到这个频道的消息的图标。一旦你预览了你的设置你只需点击“保存设置”按钮你的更改就会生效。更新我们的服务器以向 Slack 发布在我们关闭这个视图之前我们需要将 Webhook URL 复制到我们的外部服务中。你可以点击复制 URL按钮它将被添加到你的剪贴板。让我们回到 Swift 并打开main.swift。更新你的购买路由以创建 Slack 发送 POST 请求到 Slack 服务器的 JSON 有效负载drop.post(purchase){requestin// omitted code aboveletslack_payloadtryJSON(node:[attachments:tryJSON(node:[tryJSON(node:[fallback:New purchase Request,pretext:New purchase Request,color:#D00000,fields:tryJSON(node:[tryJSON(node:[title:Product:\(product.name),value:Price:\(product.price),short:false])])])])])_trydrop.client.post(https://hooks.slack.com/services/your hook id,headers:[:],query:[:],body:slack_payload)varresponsetryResponse(status:.ok,json:json)returnresponse}我们格式化的消息有效负载发送了一条通用消息该消息将在你的桌面和移动端 Slack 通知中显示New purchase Request。我们还使用附件语法提供了有关产品订单的详细信息。我们传递了产品名称和价格。现在当你在这个网站上购买时你还会收到一条实时消息发送到 Slack 的订单频道。https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/swift3-nw-feat/img/image_10_007.jpg摘要在本章中我们探讨了服务器上的 Swift。我们开发了一个完全用 Swift 运行的 Web 应用程序。我们的应用程序还与 Slack 通信以发布消息。我们使用 Vapor Web 框架创建了一个 Swift Web 服务器并学习了如何从 Swift 调用 Slack Webhooks。虽然我们的例子相当简单但很容易看出我们可以如何利用 Swift 的力量将其扩展到更大、更复杂的应用程序。这就带我们来到了本书的结尾。我们涵盖了大量的内容并学习了 Swift 3 的新特性。我们讨论了苹果对 Swift 进化的动机和目标。我向你展示了如何找到关于该语言的文档以及如何参与 Swift 的未来方向。我们探讨了 Linux 上的 Swift 以及这为服务器端 Swift 应用程序带来的可能性。Swift 3 添加了新的语言特性这些特性改进了你将在日常编码项目中使用的许多库。我希望这本书能成为你在深入开发 Swift 3 时的参考。虽然我们已经探讨了该语言的大部分特性但全面覆盖语言的所有变化并不现实。虽然这本书为理解 Swift 3 的变化提供了良好的基础但你仍需要在代码中应用你所学的知识。此外你应该参考苹果的文档和 Swift 社区以保持对语言最新发展的了解。最优秀的开发者永远不会依赖他们当前的知识。他们积极寻求学习更多。如果你想掌握 Swift 3你必须利用你所能利用的所有资源来构建我们共同创建的基础。我知道你可以做到并祝愿你在旅程中一切顺利。