Tag: swift

骆驼风格和Xcode扩展挑战

在本文中,我将展示如何为Xcode创建扩展,这并不困难。 想象一下,您想对代码使用骆驼样式(使用快捷方式)。 为Mac创建一个项目。 添加扩展名:File-> New-> Target-> Xcode Source Editor Extension 不错! 首先,我们需要实现将简单文本转换为代码的功能🙂它可以是String的扩展: 我希望本文能帮助您创建自己的扩展程序🚀 在此处查看最终项目: 伊斯特里/ XCamelize 通过在GitHub上创建一个帐户为XCamelize开发做出贡献。 github.com 谢谢阅读!

使用TDD构建JSON解析器

最近,一个朋友需要解析具有自定义格式的文件,并问我如何实现该文件。 我的脑海立刻被我上大学的记忆所淹没。 因此,我回答了他,我首先将制作一个词法分析器,该词法分析器将使用文本文件并生成令牌,然后创建一个状态机,该状态机会将令牌作为状态转换的事件,并且每个转换都会建立一点点解析的结果,直到达到终端状态为止。 我对TDD感兴趣已经有一段时间了,但是没有机会尝试一下,因此这看起来像是一个制作东西的好机会。 在本系列文章中,我将尝试使用TDD创建JSON解析器,并尝试在每个步骤中共享我的尽管流程。 让我们一起学习🙂 在我们开始之前,有一些想法: 我将生产代码和测试代码都写在一个文件中,以便于在它们之间进行切换。 我们将从仅解析没有空格和换行符的JSON文件开始。 我们稍后会处理。 我知道Foundation库有一个非常优化的JSON解析库,我们在Swift 4中添加了Codable协议,涵盖了JSON解析,但是我主要是作为练习来做的。 对于那些不熟悉的人,我将尝试遵循TDD的三个规则: 除非要通过失败的单元测试,否则不允许编写任何生产代码。 您不能编写任何足以使单元测试失败的单元测试。 而编译失败就是失败。 您不能编写任何足以通过一项失败的单元测试的生产代码。 我们首先创建带有单元测试的可可触摸框架项目,然后删除默认测试 对于最退化的情况,第一个测试应该始终是。 因为我们没有在任何地方传递可选参数,所以我们可以创建的最简陋的字符串是空字符串。 现在,我们只说如果解析失败,则返回nil。 现在我们处于红色阶段,我们必须通过此测试通过以使其再次变为绿色。 第一个错误是JSONParser不存在。 因此,我们创建了它。 让我们上一堂课。 现在,对parse方法的调用不存在。 我们可以通过创建一个接受字符串并返回Any的方法解析来解决此问题。 。 空字符串应该失败,因为它不是有效的JSON,因此我们只返回nil 。 在JSON RFC中,它表示JSON可以是以下之一: Boolean , Number , String , Array , Object 。 让我们从最简单的解析器开始:一个布尔值。 首先,我们将解决真实情况: TDD通过最简单的方式产生更好的结果,因此让我们尝试最简单的方法来验证值是否为true 。 这次我们有机会在测试代码中进行一些重构 。 解析器分配开始重复,并且可能会在每个测试中重复。 将其移至设置功能似乎是个不错的机会。 然后我们有: 列表上的下一个是处理错误的布尔值。 我们以与真实案例相同的方式进行测试: 我们做了一个if来检查是否正确 。 […]

在Swift中实现编程语言—第7部分:声明变量

注意:这是“用Swift编写编程语言”教程系列的第七部分。一定要检查 以前的内容 。 上一次我们完成编写用于解析变量名称的功能,并使用了一个预先用变量初始化的全局字典来测试我们的代码。 因此,实现我们的语言自然而然的下一步就是增加声明变量的能力。 到目前为止,我们仅实现了表达式解析,例如,我们可以在单个语句中解析标识符,运算符和数字( x + 5 * 6 ),并且缺乏解析多个表达式的能力。 表达式解析是从解析器的parse()方法开始的。 我们想要将该方法的名称更改为parseExpression() ,因为我们仍然希望parse()代表解释器的入口点。 因此,在解析器中,我们要替换几行: func parseExpression()throws- > Node { //是:func parse() throws- > Node … } 和: func parseParens()引发->节点{ … let expressionNode = try parseExpression()//是:try parse() … } 这个想法是让新的parse方法支持两种语句类型,分别由parseExpresssion()方法和parseVariableDeclaration()方法表示。 后者我们尚未实施。 在准备实现parseVariableDeclaration() ,我们必须首先做两件事 为新的关键字var添加TokenGenerators,该关键字代表变量声明的开始以及=符号,用于声明变量声明的表达式的开始。 为变量声明添加一个名为VariableDeclaration的节点 首先,我们导航到Token枚举并添加以下内容: 枚举令牌{ typealias Generator =(String)->令牌? 案例操作员(操作员) 案例号(浮点数) 案例标识符(字符串) 案例解析 […]

用于UI调试的开发人员工具

现代应用程序的用户界面是一个复杂的结构。 UI元素,布局和图形之间的复杂关系使调试过程变得很艰巨。 知道可用的工具可以减少调试时间,并使发现问题的过程变得微不足道。 在本文中,我想快速回顾一下Apple提供的UI调试工具。 View Hierarchy Debugger提供了检查和理解UI层次结构的功能。 应用程序的层次结构,视图,约束和视图控制器,显示为层次结构列表。 对象检查器和大小检查器。 甚至是交互式3D模型。 全部内置在Xcode中。 多么酷啊! 调试视图层次结构按钮位于调试栏中。 Xcode将您的应用暂停在当前状态。 View调试可用于iOS,tvOS和macOS,模拟器和设备。 如果您更喜欢控制台而不是视觉工具,那么您会很高兴知道UIKit包含了不错的日志记录API。 小问题-该API是私有的。 但是我们无论如何都不会在发行版中使用调试功能。 -[UIView recursiveDescription] —以方便的形式打印UIView层次结构: (lldb)po [view recursiveDescription] <UIView:0x7faa328013c0; 框架=(0 0; 414736); 自动调整大小= W + H; 层= > <UILabel:0x7faa328045d0; 框架=(175198; 95 21); 文字=“您好,世界!”; 不透明=不; 自动调整大小= RM + BM; userInteractionEnabled =否; 层= > <UIButton:0x7faa2f408000; 框架=(152 325; 50 30); 不透明=不; 自动调整大小= […]

iOS应用程序中的URL路由:《指南针初学者指南》

应用程序通常具有许多屏幕, UIViewController可以与显示和导航API一起很好地用作屏幕的基础。 一切都很好,直到您迷失在流的森林中,并且代码变得难以维护。 避免这种情况的一种方法是中央URL路由方法。 可以将其视为处理并解决所有路由请求的网络路由器。 这样,代码就变成了声明性的和解耦的,因此列表组件不需要知道它所呈现的内容。 URL路由还使日志记录和跟踪变得容易,并且易于处理外部请求(例如深链接)。 有多种执行URL路由的框架。 在本教程中,为简单起见,将使用Compass。 您将重构一个现有应用程序,这是一个名为PhotoFeed的简化的Instagram应用程序。 完成本教程后,您将知道如何在Compass中声明和使用路由器以及如何处理深层链接。 下载入门项目并解压缩。 转到PhotoFeed文件夹并运行pod install安装此项目的特定依赖项。 打开PhotoFeed.xcworkspace并运行项目。 点击登录以转到Instagram登录页面并输入您的Instagram凭据,然后浏览一下该应用程序。 主应用程序由UITabBarController ,其中显示了提要,当前登录的用户配置文件和菜单。 这是一个典型的Model View Controller项目,其中UIViewController处理Cell委托并负责导航。 为简单起见,所有视图控制器都继承自TableController和CollectionController ,它们知道如何管理特定模型和单元的列表。 所有型号均符合新的Swift 4 Codable协议。 在Instagram上注册您的应用 为了使用Instagram API,您需要在Instagram Developer上注册您的应用程序。 获取您的client id ,切换回项目。 转到APIClient.swift并修改您的clientId 。 注意 :该项目随附具有受限权限的默认应用。 该应用程序无法访问关注或关注者API,并且您只能看到自己的帖子和评论 指南针的概念非常简单:您拥有一组路线以及用于处理这些路线的中心位置。 将路线视为到应用内特定屏幕的导航请求。 URL路由背后的想法是从现代Web服务器中借用的。 当用户在浏览器中输入URL,例如https://flawlessapp.io/for-teams时,该请求将从浏览器发送到Web服务器。 服务器解析URL并返回请求的内容,例如HTML或JSON。 大多数Web服务器框架都支持URL路由,包括ASP.NET,Express.js等。 例如,这是您在express.js中处理URL路由的方式: app.get(’/ api / category /:categoryTag’,函数(req,res){ const page = getCategoryPageFor(req.params.categoryTag) res.send(页面) […]

使用Alamofire 5和Codable在Swift 4中编写网络层:第2部分:使用Codable执行请求和解析

在上一部分中,我们为网络层创建了API路由器,实际上这是一个提供端点的enum 。 在这一部分中,我们将看到我们将如何使用Swift 4 Codable协议执行请求并解析JSON响应。 让我们开始定义数据模型并遵守Codable协议。 这是我们的User模型: 这是我们获取特定文章时的响应: 还要注意,在我们的Article模型中,我们使用的是自定义对象Category因此仅将Article声明为Codable是不够的,因为我们需要确保Article所有属性都符合Codable ,在这种情况下,标准库类型已经符合Codable但我们的自定义类型Category应符合Codable 。 这是Category模型的实现: 让我们向APIClient添加另一个请求。 让我们添加请求以获取文章列表。 我们的APIClient将如下所示: 我们在这里看到有两个参数queue和带有默认参数的decoder ,这就是为什么在我们的登录的第一个请求中,当我们调用responseDecodable ,我们刚刚传递了一个参数,即completionHandler 。 在我们的请求getArticles我们在调用responseDecodable时需要使用自定义JSONDecoder ,因为我们需要使用自定义格式来解析日期。 这提醒了JSON端点的JSON响应: 因此,为了帮助JSONDecoder知道如何解析日期,我们需要指定dateDecodingStrategy 。 我们首先需要创建一个DateFormatter : 现在,我们有了可以与Alamofire 5和Codable一起使用的功能齐全的网络层。 但是让我们重构我们的APIClient并避免重复代码: 我们刚刚创建了一个名为performRequest的新方法,该方法将在传递APIRouter和completion参数时执行请求。 同样,我们使传递自定义decoder成为可能。 现在,我们对APIClient感到满意,并且我们已经准备好使用完整的网络层。 这是完整的示例项目: AladinWay /网络示例 NetworkingExample –系列文章的Exampel项目:https://medium.com/@AladinWay/write-a-networking-layer… github.com 在本系列的下一部分中,我们将尝试改进APIClient并使用Future (有时也称为Promise )的概念,而不是我们现在使用的完成回调。 这将有助于更好地处理响应。 请随时发表评论并提出任何可能的改进,并请注意,我无法在“ Medium”上回答任何问题/评论。 相反,请在示例项目GitHub存储库中打开一个新问题: AladinWay /网络示例 NetworkingExample –使用Alamofire 5和Codable在Swift 4中编写网络层 github.com 请继续关注,不要忘了在下一部分出版后立即得到通知。 您可以在此处阅读下一部分: 使用Alamofire […]

Swift的行为驱动开发框架

XCBlog上的原始帖子在这里 最近,有多家公司在寻找使用Swift编写的iOS应用程序的BDD支持工具。 由于Cucumber没有对Swift的官方支持,因此大多数人都在努力为Swift项目寻找合适的BDD工具。 这篇文章将重点介绍一些在Swift应用程序中支持BDD的工具。 BDD aka行为驱动开发是通过使用Gherkin或类似格式的可执行规范来开发应用程序的过程,以便程序员可以将这些规范用于开发,而业务人员可以将其用于需求规范或实时文档。 BDD是一种由内而外的开发方法。 您可以在此处阅读有关BDD的更多信息。 由于缺少适当的BDD工具(如Swift中的Cucumber),iOS世界中的行为驱动开发始终面临挑战。 在网站开发中,BDD选项有特定于语言的选项。 有一些解析Gherkin语言语法的工具(Given / When / Then),我们可以执行BDD场景,例如Ruby的Cucumber,JavaScript的CucumberJS,Java的Cucumber-JVM,C#的SpecFlow,PHP的Behat等。适用于Spec级BDD的工具,例如Ruby的RSpec,PHP的PHPSpec,JavaScript的Jasmine。 但是,在iOS世界中,执行BDD的选项非常有限,尤其是对于Swift。 在本文中,我们将探讨Swift iOS应用程序当前使用的BDD选项。 使用诸如带Appiumor Calabash的Cucumber之类的工具可以轻松实现Gherkin Style BDD,但要在Xcode中支持BDD并非易事。 由于缺少适当的BDD工具(例如Swift中的Cucumber),iOS世界中的BDD始终具有挑战性。 Swift中没有可用的Gherkin解析器,因此Cucumber社区建议使用Objective-C Gherkin解析器。 这里提到了许多BDD工具来编写较低级别的测试,但是为了编写UI级别的测试,很少有选项可能没有Ruby中Cucumber的所有核心功能。 XCTest-Gherkin是另一个可用于在Xcode项目中实现BDD的工具。 在README文件上有关于其功能和限制的详细信息。 它纯净的表示形式,我们仍然可以使用String格式编写GWT(当时提供),但是主要缺点是我们无法编写或执行.feature文件,并且缺少许多核心的黄瓜功能,例如标签,过滤功能。 您需要使用CocoaPods或Carthage将XCTest-Gherkin作为UI测试目标的依赖项。 XCFit是另一个纯Swift实现,用于在Xcode项目中支持BDD。 它还提供了Xcode模板,以开始使用BDD,页面对象模式和面向协议的模式。 XCFit在Swift框架中有一些预定义的步骤,但是快速好处来自Xcode模板。 有关面向协议的BDD的更多信息,请参见此处。 另一个主要缺点是我们无法编写或执行.feature文件,并且缺少许多核心的黄瓜功能,例如标签,过滤功能。 Cucumberish是一个测试框架,可用于以Gherkin格式编写功能,并可从Xcode执行。 Cucumberish被编写为Objective-C,并使用来自Cucumber存储库的Objective-C Gherkin解析器。 能够从Xcode执行Gherkin功能文件非常好,但是Cucumberish有一些错误,在大多数情况下需要解决方法。 在完全Swift项目中引入Objective-C依赖关系也有些棘手。 可以使用CocoaPods或Carthage将黄瓜导入UI测试目标。 Plowman是Gherkin语言的另一种测试运行器,我们可以从命令行编写和执行功能文件。 在Ploughman的README文件中有很好的信息。 这缺少核心Cucumber的许多功能,例如示例,标签和过滤器。 可以使用Swift Package Manager导入此软件包。 SwiftGherkin是另一个Swift软件包,用于处理基于gherkin.feature的文件。 这是一个新创建的程序包,它支持功能,方案,方案大纲和步骤,但是将来还会支持所有其他核心黄瓜功能。 您可以继续关注该存储库,以获取有关此软件包的更多新闻。 该软件包只能与Swift Package Manager一起使用。 与用于Ruby的RSpec,用于PHP的PHPSpec,用于JavaScript的Jasmine相似,很少有工具可以为较低级别的实现编写规范。 我们将在Swift中看到那些规范级别的BDD选项。 […]

因为风格很重要

尽管已记录了适当的代码风格并根据准则制定了代码约定,但是开发人员可能会忘记始终如一地应用它,或者变得懒惰并开始忽略它。 您不想以任何方式花费自己的时间来修复代码样式或让同事去做。 代码样式是(尽管很重要)最不重要的编码任务之一,因此,建议让工具为您做花哨的格式检查,让您专注于编写代码的更棘手的方面。 Realm引入了一个非常不错的工具-SwiftLint,该工具可以帮助自动完成起毛过程。 在本文中,我将向您介绍如何在iOS项目中设置此工具,以提供所需的语义,保护代码的清洁度并帮助您编写更简洁的代码。 Swiftlint是一个工具,可以帮助您识别和标记可能不符合您定义的样式准则的代码部分。 如果尚未安装SwiftLint,请检查 原始存储库中的 “ 安装” 部分。 您可以通过在Xcode项目的Build Phases中添加运行脚本来使用它。 在下面,您将找到我们用来检查代码风格的脚本。 继续并通过将其保存到项目目录中来在项目中使用它: $SRCROOT/Build-Phases/swiftlint.sh 在此步骤中,可以将脚本本身复制并粘贴到“运行脚本阶段”中 ,但是我们建议将脚本保存在单独的文件中(因为您可能在项目的另一个目标中使用它)。 因此,将文件拖放到运行脚本或编写器中 ,其路径如下所示: 拥有此脚本将在每次下一次构建项目时直观地向您显示代码的哪些确切部分与您决定坚持的样式不符。 下图显示了一个警告示例,它违反了我们在样式指南配置文件中定义的规则之一。 SwiftLint确实可以帮助您加强自己和您的团队遵守团队所同意的样式指南,从而对团队产生积极影响,因为他们不会因为两个人使用不同的代码样式而引起任何讨论实践。 通过让机器为我们完成所有繁重的工作,自动化在这里很方便。 让我们(作为开发人员和代码审阅者)真正专注于重要部分。 主要目标是强制执行和鼓励使用样式惯例,这些惯例通常由社区或团队定义。 所有这些都可以使单个项目的文件之间或一般项目之间的代码样式保持一致,无论是您的个人项目还是公司的项目。 它还将有助于提高项目的可读性和更多好处。 从这往哪儿走: 阅读有关SwiftLint的更多信息,并查看它提供了哪些规则。 与团队一起构建自己的样式指南,并在.swiftlint.yml文件中对其进行配置,以在整个项目中使用它。 了解有关使用SwiftLint的其他方法的更多信息(例如,与github一起使用它,并在使用危险的每个拉请求上发布wanring)。 参考: https://github.com/realm/SwiftLint 👏🏻如果您喜欢这篇文章,并认为它很有用。 这会鼓励我写更多! 任何意见或反馈表示赞赏! 随时将我添加到github , twitter或 linkedin 。 感谢您的阅读!

快速面试问题–克里希纳

快速面试问题 1) Swift和Objective C之间的差异 Swift是用于iOS,macOS,watchOS和tvOS应用程序开发的新编程语言。 尽管如此,从您在C和Objective-C方面的开发经验中,Swift的许多部分都会为您所熟悉。 Swift提供了自己的所有基本C和Objective-C类型的版本,包括Int表示整数,Doubleand Float表示浮点值,Bool表示布尔值和String表示文本数据。 Swift还提供了三种主要集合类型(数组,集合和字典)的强大版本。 1. Swift引入了在Objective-C中找不到的高级类型,例如元组(值的分组)。您可以使用元组从一个函数返回多个值作为单个复合值。 2. Swift还引入了可选类型,用于处理缺少值的情况。 可选参数说“有一个值,它等于x ”或“根本没有值”。 它们适用于任何类型,而不仅仅是类。 使用可选选项类似于在Objective-C中对指针使用nil 3. Swift是一种类型安全的语言,如果代码的一部分需要一个String,则类型安全可防止您错误地将其传递给Int。同样,类型安全可防止您将可选的String意外地传递给期望的代码一个非可选的字符串。 类型安全性可帮助您在开发过程中尽早发现并修复错误。 4. Swift更易于阅读:不再需要用分号来结束行或括号,Swift中的方法和函数调用在括号内使用行业标准的逗号分隔参数列表。Swift代码更类似于自然英语 5. Swift易于维护: Swift将Objective-C标头(.h)和实现文件(.m)合并为一个代码文件(.swift)。 6. Swift更安全: 7. Swift与内存管理统一:在目标C中,开发人员有责任通过使用低级API(如Core图形)来管理内存处理。 与Swift中一样,即使在底层API中也无需考虑内存管理。 8. Swift需要更少的代码 9. Swift更快 10.Swift Playgrounds鼓励交互式编码: Playgrounds使程序员能够测试新的算法或图形例程,例如5至20行代码,而不必创建整个iPhone应用程序。 2) 类型安全和类型推断: Swift是一种类型安全的语言。 类型安全的语言鼓励您清楚代码可以使用的值的类型。 如果代码的一部分需要一个字符串,则不能错误地将其传递给Int,它会在编译代码时执行类型检查并将所有不匹配的类型标记为错误。 如果您没有指定所需的值类型,则Swift会使用类型推断来得出适当的类型。 当声明具有初始值的常量或变量时,类型推断特别有用。 3) 什么是类型别名 类型别名为现有类型定义备用名称。 您可以使用typealias关键字定义类型别名。 4) 什么是元组: 元组将多个值分组为一个复合值。 元组中的值可以是任何类型,而不必彼此相同。 元组作为函数的返回值特别有用。 尝试检索网页的函数可能会返回(Int,String)元组类型,以描述页面检索的成功或失败。 通过返回具有两个不同值(每个类型均不同)的元组,该函数提供的结果要比仅返回单个类型的单个值要有用得多。 […]

iOS中的单元测试

第3部分:快速灵活的测试 前言 我打算编写完整的iOS单元测试系列。 您可以在下面的链接中找到成品。 快乐阅读🙂 第1部分:为什么在开发应用程序时需要进行单元测试? 第2部分:我的第一个单元测试 第3部分:快速/灵活的干净测试 第4部分:如何处理上下文 第5部分:良好做法 第6部分:单元测试,Jenkins和SonarQube一起[待撰写] 借助XCTest框架,您已经可以为应用程序编写所有可能的单元测试。 但是,一旦您做了很多测试用例,并且在测试类中有多个上下文,您就会发现使用XCTest并不是那么酷。 您可能会对使用Quick&Nimble感兴趣。 这两个框架(主要是Quick)将帮助您组织测试类中的测试,以使其更清晰,更易于阅读并且更容易在一个测试类中具有多个测试上下文。 使用Quick,您将为编写异步功能测试感到更加自在。 将Quick&Nimble集成到项目中的最简单方法是使用可可豆荚或依赖管理,例如Carthage甚至Swift Package Manager(Quick&Nimble支持这3种方法)。 如果与CocoaPods一起使用,请在项目根文件夹的终端中运行pod init ,以为项目初始化Cocoa Pods。 然后使用任何文本编辑器添加Quick&Nimble,如下所示: 最后,运行pod install或pod update安装那些框架。 完成后,打开项目的.xcworkspace而不是.xcodeproject 。 考虑让一个Translator类从给定的键中获取本地化的字符串。 该翻译器能够处理多种语言,并以所选语言返回正确的文本。 如果我们使用XCTest为该类编写单元测试,我们将具有以下内容: 导入XCTestclass转换器XCTests:XCTestCase { 覆盖func setUp(){ //当我们有1个测试上下文时,此函数很有用,或者我们可以使用它来初始化公共上下文 } func testSetupTranslator(){ 让翻译器= Translator() 让yesButton = translator.message(“ yes_button”) XCTAssertNotNil(yesButton,“应该能够获得有效的本地化字符串”) XCTAssertEqual(yesButton,“是”,“应该使用英语作为默认语言”) } func testTranslationInFrench(){ 让翻译器= Translator() translator.setUp(“ fr”) […]