这通常会提高自动化,代码生成和工具支持的水平。 它还会生成更稳定的代码。 开源社区 开源社区一直在努力使用Swift for Server构建库。 在撰写本文时,顶级服务器端Swift框架(在GitHub上按星标列出)是: 完美 (12271⭐) 蒸气 (11406⭐) Kitura ( 6019⭐ ) 泽沃 ( 1718⭐ ) Ryan Collins的这篇有用的文章测试了所有这些Framework的性能,并将它们与Node.js进行了比较。 他的结论是,所有这些框架的性能都非常好,并且在每次测试中,Node.js都被其中至少两个击败。 这意味着swift在发球方面表现非常出色。 汽 尽管每个框架都有其独特之处,但研讨会的主题是由纽约市的美国软件工程师Tanner Nelson(@ tanner0101)创建的Vapor 。 在2016年9月正式发布Vapor 1.0之后,团队一直在努力工作,当前可用的版本是Vapor 2.2.2。 他们已经在研究Vapor 3。 为什么要蒸气 ? 蒸气有许多优点: 巨大而活跃的社区 非常简单的语法 纯粹用Swift编写 易读易懂的API,不依赖第三方库 成为Swift可以使他们专注于保持API的简单性,可读性,并使其命名和其他约定与该语言保持一致。 唯一的缺点是:他们牺牲了一点速度和性能,以求成为纯Swift。 链接 https://github.com/vapor/vapor https://docs.vapor.codes/2.0/ http://vapor.university 在结束本文时,我同意Ryan Collins所说的话,即Server-Side Swift有望成为编程领域的一个有力竞争者。 谢谢你的时间! 希望本文对您有所帮助。 在Twitter上联系: stefanofrosoni
预习 资源 项目 https://github.com/calmone/iOS-UIKit-component 参考 UIAlertController https://developer.apple.com/reference/uikit/uialertcontroller UIAlertAction https://developer.apple.com/reference/uikit/uialertaction 快乐编码😄
还记得面试官要求您将代码优化为一行的时候吗? 我总是对我有这种感觉。 但是Apple的新语言(已经3年了,但仍然很新)Swift通过引入诸如map,reduce,filter,flatmap higher的高阶函数而获得了支持。 让我一一介绍。 地图 Map用于迭代一个集合,并返回一个数组,其中包含将给定闭包映射到序列元素上的结果。 使用地图,我们可以轻松更改任何元素的值。 假设我们想将美元转换为印度货币,并且有以下数组, 令USD = [10,20,30,40,50] 我真的不想向您展示我们已经遵循多年的常规惯例,您也不是为此而来,不是吗? 让我们开始潜水吧 要将USD转换为INR(印度卢比),我们可以编写一个神奇的代码,例如 令INR:[Float] = USD.map {Float($ 0)* 65.32} // [653.200012,1306.40002,1959.59998,2612.80005,3266.0] 瞧! 😇 输出将是Float数组,其中包含所有转换为INR(最大成就)的值。 有趣吗? 过滤 另一个可口的方法用于遍历集合并返回仅包含那些与条件匹配的元素的数组。 让我们考虑一下,我们只需要数组中的偶数, 让arrayOfNumbers = [1、2、3、4、5、6、7、8、9] 我们可以通过写得到偶数, let evenNumbers = arrayOfNumbers.filter {$ 0%2 == 0} // [2,4,6,8] 降低 Thanos手套的另一块无限石。😍 这将返回一个值,该值是通过合并集合中的所有值得到的。 让我们考虑另一个通用数组, 让itemPrice = [10、20、30、40、50] 减少功能将是 设total = itemPrice.reduce(0,+) […]
更新,2018年10月14日: 自撰写本文以来,这些博客文章中描述的概念已被分为两个开源框架,可以在这里找到: ka-ching-as / FireSwift-Database Firebase实时数据库的扩展,可以使用“ Codable” Swift类型。 … github.com ka-ching-as / RxFireSwift-Database Firebase实时数据库的RxSwift扩展-ka-ching-as / RxFireSwift-Database github.com 这篇文章是3部分系列文章的继续,该系列文章首先为Firebase API添加了Codable支持: 在这篇文章中,我们将讨论一个非常有趣且功能强大的主题,它受objc.io Swift Talk#71:带有幻影类型的类型安全文件路径的启发。 在Swift Talk中,Brandon Kase和Florian Kugler讨论了“幻影类型”,简而言之,这些类型永远不会实例化,而只会用作通用约束。 这些是将强类型添加到通常不是强类型的API的强大工具,就像Firebase RTDB Reference使用的路径一样。 请,请去观看关于objc.io的精彩演讲! 在这篇文章中,我们将混合Phantom Types和实际的Codable模型类型,以创建一个真正强大的API。 可以在第一篇博客文章中介绍的github仓库的typesafe_paths分支上找到该文章的示例代码: ka-ching-as / SwiftyFirebase SwiftyFirebase – Swift中Firebase API的简单包装 github.com 请注意,本文涉及Firebase,但是所描述的技术可以用于具有“字符串”定义的数据层次结构的任何类型的API。 我们将介绍一种Path类型,该类型基本上包装了一系列路径组件,但在此过程中增加了类型安全性。
后端工程师确切地知道他们的服务正在发生什么。 他们实时了解其QPS,内存占用量,错误率和CPU利用率。 如果出现严重错误,它们甚至会自动进行分页,因此他们可以快速响应。 不幸的是,iOS工程师通常只有崩溃报告以及一些产品指标。 通常,我们会在用户报告错误时或更糟地在用户发布不正确评论时了解错误。 我们可以做得更好。 断言是条件检查,可确保您的代码按预期运行。 可能,您的代码库中已经有一些。 他们检查永远不会失败的条件,如果失败,则表明代码中存在严重错误 。 但是,断言在生产中已被删除,在现实世界中没有任何影响。 在我从事的每个项目中,我都添加了一个自定义Log类型,该类型使断言报告生产中的错误。 大多数崩溃报告框架都有报告非致命错误的能力,因此实施此操作很简单。 这是使用Crashlytics的示例: 枚举 Log { 静态 函数断言 #if调试 Swift.assert(condition(),message(),file:file,line:line) #其他 如果 !condition(){ 让域= message() let error = NSError(domain:domain,code:domain.hashValue,userInfo: nil ) Crashlytics.sharedInstance()。recordError(错误) } #万一 } 静态 函数 assertFailure ( _消息: @autoclosure ()->字符串,文件:StaticString = #file ,行:UInt = #line ){ Log.assert( false ,message,file:file,line:line) } } 在DEBUG […]
(本文最初于2018年1月17日发布在这里) 在我的旅程的这一点上,我并没有真正理解学习Swift和学习UIKit以及Apple的各种框架和API(可以实际构建应用程序)之间的区别。 因此,当我浏览Swift编程书(在上一篇文章中提到)时,我有一个愚蠢的想法,即当我完成本书时,我将成为一名iOS高级开发人员,能够制作我梦dream以求的应用程序。 这是一本约400页的书,当我完成本书的一半时,我开始思考“我正成为iOS开发人员的一半! 我要到达那里,再走一点!”,但在我的脑后,我有些怀疑。 是的,我正在学习大量有关Swift的新材料,包括基本语法,流控制,集合和函数,结构与类,初始化等,但是这些都没有让我更接近于构建实际的应用程序。 我一直在想,这本书很快就会有一个具有启发性的里程碑,它将把所有东西联系在一起,并明确说明如何构建您能想到的任何应用程序。 我不想在这里给人留下错误的印象。 这本书非常了不起,它帮助我在Swift中打下了坚实的基础(尤其是作为一个几乎没有编程经验的人)。 但是,当然,到我完成本书时,还没有神奇的启示性经验。 是的,您将在上一章中构建一个简单的“待办事项”应用程序,但这并不是“恭喜! 您是iOS的高级程序员!”更多的是“这里有一种可能,现在您真正的学习之旅就开始了!” 再说一遍,这是一本很棒的书,我认为通过阅读,我绝对做对了。 它也可以很好地作为参考,在我处理项目时,我经常回到它上面。 第一次经历时,我只是抱有错误的期望,认为可以将iOS开发掌握在一本书中,而不了解编程语言和框架之间的区别。 当我完成这本书时,我想从事一些理论上少而又基于项目的工作。 经过研究后,我决定选择Paul Hudson的Swift黑客。 它收集了39个iOS项目,他将逐步指导您完成每个项目,并为您提供每行代码的详细说明。 本章从快速概述该目标开始,然后作者不花时间,直接进入代码。 整本书都可以在他的网站上免费获得,这很棒。 尽管在完成几个项目后,我还是决定购买该电子书,以:1)支持作者,2)获得一种可移植的格式,可以在任何地方使用。 此外,他定期更新书籍以涵盖Swift和iOS的新功能也没什么坏处(例如,项目已更新为包括Face ID和Codable) 从《 Swift编程》这本书开始,将我所学到的东西应用到可以在手机上实际测试的真实项目中,真是太好了。 当我开始阅读上一篇文章中提到的Udemy教程时,我真的很难理解大多数东西是如何工作的以及为什么。 但是现在,我终于可以开始看到API调用背后的逻辑了,事情开始变得更加有意义了。 这并不是说从现在开始一切都顺利。 UIKit是一个复杂的野兽,有些概念使我花了很长时间才理解。 不过,总的来说,这是我开始对自己的编程技能更有信心的时候。 在这一点上,我开始思考“毕竟我可以成为一名程序员”……除了一个小问题,就是动力。 在全职工作回家后的夜晚和周末,很难激发自己去学习编码。 我将在以后的文章中谈论所有这些!
中级是标签。 对不同的人意味着不同的事情。 这篇文章非常主观,但是这些对我进步到我认为是中级iOS开发人员有帮助。 它还假设您已经对UIKit,协议和泛型之类的基本知识已经有了足够的了解,因此我不介绍这些内容。 学习高级iOS技术 从本质上讲,这是非常主观的,但是我建议您理解或至少意识到的事情是: 何时(以及如何)使用线程 CI和自动化工具(Fastlane,Jenkins,Travis或类似工具) 测试—单元测试,集成测试,UI测试,快照测试 如果可以访问,则App Store可以连接。 分发到TestFlight和App Store,用户和角色,证书和密钥都是好东西 帮助您遵循SOLID原则的抽象,例如Coordinator模式,这些概念将迫使您更好地构建代码。 通过实验找到最适合您的方法很重要 可访问性是大多数人会忽略的东西,因此这是与众不同的好方法。 当然,这对于您的用户也是正确的做法。 动态类型是您最容易使用的一种,也许是最广泛使用的一种。 配音和色盲设计也是不错的起点。 何时使用框架。 框架是一种非常强大的工具,可以为您节省时间和金钱,但是知道何时(并且更重要的是何时不使用)是一种技能 我敢肯定还有更多,但这些都是我想到的 这里有很多东西,所以更多的是要了解外面的事物并知道何时使用它们,而不是详细地详细了解每个事物。 这样,当有人要求您做某事时,您将知道最佳的做事方式,而无需立即知道如何做。 您将能够回答“是的,这是可能的”或“我知道这个伟大的工具”,而不是“我不确定,让我研究一下”。 最好对可以实现的目标有一个大概的了解。 将来也可能会节省您的时间。 我曾经一起破解过自己的电池记录实用程序,然后发现iOS内置了该实用程序。几乎与我不了解Swiftlint自动更正功能的时间一样糟糕。 当然,在尝试做任何事情之前进行大量研究都是不可行的,但是如果您对许多有用的技术有一个全面的了解,那么您将会知道从什么开始或推荐什么。 习惯于架构模式并知道何时使用它们 习惯一种做事方式然后陷入其中是很常见的。 也许对我们第一个可行的解决方案的联系过于紧密感到不自在或感到骄傲。 MVC没什么错,但是它是最容易被滥用的,因此赢得了良好的声誉,这也许是因为它是我们大多数人开始学习的地方。 我认为在编程中很明显,知道一种以上的做某事的方法是一项有用的技能。 这不仅是了解适合该工作的工具,而且还有助于加深您对该领域的了解,并让您了解为什么以这种方式做事。 如果您想探索建筑的各种首字母缩写,那么一个很好的起点是objc.io的《 App Architecture》一书(但是我希望他们能涵盖VIPER)。 您不必在实践中使用它们。 了解通用模式及其相关的词汇表将使您更轻松地阅读他人的代码,并使选择具有比您更喜欢的架构模式不同的新代码库更为顺畅。 与设计师合作时要自以为是 您的工作是制造最好的产品。 如果您与设计师合作,很容易挑战自己完全按照规范构建应用。 但是该规范可能不适合您所了解的业务需求。 或者它可能具有一些令人愉悦的新颖工作流程,其中标准的iOS应用程序模式就足够了(Snapchat重新设计后劲)。 与设计师一起提出这些问题是您的责任,以便您可以迭代它们并最终为用户构建更好的产品。 始终确保遵循《人机界面指南》,您的设计人员可能对此一无所知。 帮助别人 您可能会骗自己以为,由于您不是该领域的专家,因此您不应该教导其他人,但这不是真的。 您不需要了解某个主题的所有知识,只需要了解比与之交谈的人更多的知识即可。 如果有机会指导其他人,则承担该责任。 您将被迫清楚地解释一些事情,从而学到很多东西,巩固自己已经知道的知识。 但是请确保知道有多少帮助。 如果仅在它们前面键入所有代码并希望他们以后再理解,那将无济于事。 这是为正确答案提供指导的问题,当它们迷路而不会故意模糊时提供正确提示。 […]
在我目前的工作中,我们需要改进代码库,并且从网络层开始。 我们想创建一个开源库,但提出了一个问题:开源库的结构如何? 介绍 去年八月,我开始为一家名为Jumbo的新公司工作(我们仍然有很多职位空缺)来改善他们的移动应用程序,该应用程序在荷兰经常使用。 该应用程序已经并且仍然有一些改进点,因此该团队决定制定一个长期计划以提供新功能,同时改善代码库。 我们要解决的第一件事是网络层,因为该应用程序没有一个:每个UIViewController当前都在扩展一个基本控制器,这是唯一负责在子类中配置并管理所有请求的控制器。逻辑(是的,不理想)。 这是我们结构的一个例子: 这种结构没有错,但是它迫使您每次更改基类时都要测试每个控制器,并且由于验证逻辑是集中式的,因此发生的次数很多。 对于我们的库,我们想要一些可扩展,可维护,开源并且最重要的是可测试的东西:这是JNetworkingKit诞生的那天。 在接下来的几周里,我将描述我们创建它所遵循的过程,所进行的讨论以及所做出的决策。 该库不是完美的,但是我们已经使用了几个月,没有出现任何重大问题,并且我们能够扩展它来解决我们面临的问题。 本文将重点介绍库结构的创建。 其他图书馆 我们想要开源,同时拥有模块化的应用程序。 我们花了一些时间潜入著名的图书馆以了解其结构。 通过分析Alamofire,SwiftyJSON和Realm,我们看到了有关文件夹结构的一些相似之处: 包含源代码的文件夹 文档文件夹 包含示例的文件夹 所有其他文件都与外部服务,CD / CI相关,或者是支持文件。 有时文件夹结构变得很大,以至于很难理解在哪里找到您需要的东西:我们不愿意将所有内容都显示在根文件夹中,因为它可能会变得一团糟(Alamofire那里有26个文件/文件夹),所以我们决定采用我们自己的结构。 JNetworkingKit结构 我们决定弄清楚文件夹包含的内容,因此我们要做的第一件事是在根级别仅创建2个文件夹: JNetworkingKit ,包含库本身 DemoApp ,包含一个用于测试库的演示应用程序(作为开发容器导入) 如果我要求您猜测这些文件夹中的内容,我相信您可以使用名称😉进行猜测。 我们开始将源代码添加到JNetworkingKit文件夹中,并在DemoApp中创建了一个演示应用程序,但是我们开始遇到一些问题。 主文件夹 我们很快就知道保持结构整洁很困难:您需要确定一个许可证 ,为用户添加一个自述文件以及.gitignore文件,以避免提交不必要的事情。 您是否想要CD / CI? 您需要一个文件。 您需要支持Cocopoads吗? 您需要另一个文件。 迦太基和Swift包管理器又如何呢? 将资源划分为多个子文件夹是保持所有内容整洁的唯一方法。 演示应用 由于我们想将该应用程序用作外部Pod,因此我们创建了一个演示应用程序,将其导入为开发 Pod。 我真的建议您做同样的事情:在创建应用程序时,您不必考虑访问修饰符,因为默认情况下所有内容都是internal的,这意味着您可以默认使用项目的每个组件。 创建库时,您只能访问public组件和变量,但是我可以保证您会忘记其中的一些组件,尤其是如果您是根据已在项目中使用的代码创建库的。 创建一个导入库的演示应用程序可以帮助您解决问题:您可以测试代码并直接对其进行修改✌🏻。 你猜怎么了? 发布库后,我们还注意到public关键字缺少some的问题。 子文件夹 子文件夹没有什么特别的:随时创建自己的结构。 我只建议您在库中只有几个文件夹: JNetworkingKit / […]
我决定深入研究Vapor,以及它是否真的是可行的选择。 早在2月份,我播了一段播客,概述了开发移动应用程序时不同的后端选项。 简而言之,当寻找正确的选项时,有很多选择。 例如,对于Swift开发人员而言,Vapor已成为越来越合适的选择。 因此,我决定深入研究Vapor,以及它是否真的是可行的选择。 选择的多样性 纵观后端选择的前景,可能会造成混乱。 最后, 这实际上取决于团队的技能水平 。 例如,如果您使用JavaScript来构建Web和移动应用程序,那么Node.JS就很有意义。 另一方面,如果您是.Net开发人员团队,则Web API很有意义。 此外,如果您特别精通PHP,Python,Ruby,Go等…,则应保持自己的舒适度。 但是,对于专注于Apple产品的单个开发人员和开发人员团队(例如我),没有专用于服务器端应用程序的框架。 因此,最接近的选项是CloudKit,它适合于数据存储,但缺少以下选项: Web和Apple设备外不支持 不支持完整备份 锁定到CloudKit数据模型中以建立关系 没有Cron工作 但是,还有其他选项可以在服务器上的Swift中继续开发。 蒸气—服务器快速处理 自Swift于2015年末开源以来,已添加了与其他操作系统的兼容性。 将Swift迁移到服务器的第一批团队之一是Vapor团队。 自2018年5月发布3.0版以来,人们的兴趣日益浓厚。 在本文中,我将回顾Vapor并介绍以下内容: 易于安装和部署 蒸气开发 数据库支持 事件驱动的异步API 因此,让我们从开始变得容易开始。 蒸气入门 在我最近发表的这篇文章中,我展示了如何在Mac和Ubuntu以及Heroku之类的服务上安装Vapor。 简而言之, 我发现该过程非常简单有效 。 也就是说,它没有其他任何Web框架那么复杂。 例如,在Mac上,开发人员可以使用相当普遍的Homebrew来点击Vapor存储库并进行安装。 有权使用Vapor CLI工具后,该工具包括一个子命令,用于使用Vapor buildpack设置Heroku应用程序。 同样在Ubuntu上,您为Vapor添加apt仓库,并通过apt命令安装。 完成此操作后,您可以轻松地使用进程监视器和http服务器的组合来代理服务器。 如果您对此过程的更多细节感兴趣, 请查看这篇文章,深入了解Vapor并设置macOS,Heroku和Ubuntu。 蒸气开发 安装了Vapor之后,该过程的下一部分将开发该应用程序。 因此,IDE非常重要。 带有蒸气的开发人员工具 尽管存在问题,我们仍然可以使用Xcode在Swift中进行开发。 但是,由于有用于构建Swift应用程序的命令行工具,开发人员可以选择自己的工具。 目前,真正的限制是Swift通常仅在macOS和Ubuntu上受支持。 也就是说, 不支持其他Linux或Unix操作系统,也不支持Windows。 但是,社区肯定会在这些领域提供更多支持来向前发展。 […]
测试驱动开发(TDD)是软件开发人员可以在软件开发中使用的方法之一。 在TDD中,开发人员计划要创建的软件功能,然后在编写功能实现之前,为软件的每个功能编写测试用例。 在开始时,测试用例显然会失败,因为代码尚未实现。 此阶段通常称为红色阶段。 然后,开发人员编写代码以确保测试用例成功通过,并且不会破坏任何组件或当前的测试用例,因此不必完全优化和高效地完成此阶段中的代码。 此阶段称为绿色阶段。 此后,开发人员应通过清理,维护代码库和优化代码效率来重构代码的实现。 然后,应在添加新的测试用例时重复此循环。 每个测试单元应做得尽可能小且隔离,以使其易于阅读和维护。 在本文中,我们将使用带有Xcode XCTest Framework的TDD构建一个简单的网络API单元测试。 Network API将对服务器的网络调用封装为以JSON格式获取电影列表,然后将其编码为Movie Swift类的数组。 网络测试需要在不发出实际网络请求的情况下快速执行,为此,我们将创建模拟对象和存根来模拟服务器调用和响应。 APIRepository类:此类封装了我们对服务器的网络请求调用,以获取电影列表 APIRepositoryTests类:XCTest子类,我们将使用该子类为APIRepository类编写测试用例 MockURLSession类:URLSession子类,充当模拟对象以测试传递的URL以及使用存根数据,URLResponse和Error对象创建的MockURLSessionDataTask MockURLSessionDataTask类:URLSessionDataTask子类,充当模拟对象,用于存储网络调用中的存根数据,URLResponse,Error,completionHandler对象,它覆盖恢复调用并调用传递存根对象的completionHandler存根。 测试用例1 —从API获取电影按预期设置URL主机和路径 我们将创建的第一个测试用例是测试get films方法是否在正确的期望范围内设置了URL Host和Path。 首先在“测试”模块内创建APIRepositoryTests单元测试类。 不要忘记添加“ @testable import project-name”以将项目模块包含在测试模块中。 要在Xcode中运行测试,可以使用快捷键Command + U。 在函数中,我们设置实例化APIRepository类对象,此方法中创建了一个名为testGetMoviesWithExpectedURLHostAndPath()的方法,因为我们尚未输入APIRepository类,所以我们键入了有关未解析标识符APIRepository的编译器投诉。 导入 XCTest @testable 导入 APITest 类 APIRepositoryTests:XCTestCase { func testGetMoviesWithExpectedURLHostAndPath(){ 让 apiRespository = APIRepository() } } 要编译测试,请创建一个包含APIRepository类的名为APIRepository.swift的新文件。 导入基础类 APIRepository {} 接下来,在testGetMoviesWithExpectedURLHostAndPath内部,我们将调用APIRepository方法,以从通过完成处理程序的网络中获取电影。 […]