Tag: 编程

如果您的类型名称平庸,则您的代码将构成责任

我创建代码的过程如下所示: 研究目标的细节(学习) 提出实施计划(创建) 代码(单击并键入) 当我意识到我有一个错误的假设时,请返回步骤1(遗憾) 在进行编码工作之前,正确命名类型是计划中的最后一个障碍。 就像,嗯,我知道计算机不在乎我给我命名的类型。 机器解释指令时,所有这些都将被剥夺。 我的功能不会受到影响。 为什么我花了很多时间来确定角色以及事情如何融合在一起? 因为代码不仅仅适用于机器。 适用于必须充分理解它才能正确操作它的开发人员。 该类别中包括“未来”。 要做到这一点,就需要弄清问题集,并有足够的同理心,以使听众可以预期您选择的名字的所有含义。 真名 有一个古老的想法,即如果您知道某事的“真实名称”,那么您将拥有权力。 这是幻想中的常见现象,也是宗教故事的一部分。 以伊西斯和拉的故事为例。 伊希斯(Isis)是一位出色的治疗师,但只有知道她的真实姓名时才能帮助Ra。 他试图用“小写”的名字满足她的要求,但这仅使Ra未能解决核心问题。 一旦他放弃了他的真实姓名,她就可以治愈他。 这听起来像调试我。 如果您不知道所处理事物的真正含义,就无法解决该问题。 懒惰的标签将欺骗人。 您在阅读代码时让人们做的心理锻炼越多,使用它的认知就越消耗精力。 “是的,被称为 Provider 但实际上只是转换数据。” “该 modelId 不适用于该模型,适用于其他通用模型。” 但是,如果您真正知道什么是东西,则可以轻松地对其进行操作。 这很重要,因为将来必须更改代码。 我的理想是功能与代表功能的标签之间的绝对统一。 既然是理想的,我永远都不会到达那里。 想起名字时会出现回报递减的情况,但是值得花一些时间。 在清晰度和可读性之间取得平衡 某物的最精确名称可能是…… 绝对清晰。 把它收拾好。 该名称公然忽略了所有可用的上下文。 显然,这个例子很荒谬,但是添加不必要的限定词可能很诱人。 即使您觉得这个名字不是最好的,也最好在项目内部保持一致,而不要在两个约定之间来回穿梭。 一旦人们适应了您项目的标准,他们就会知道您在说什么。 一致的信息比冲突的信息要好,即使最终效果不佳。 同样,在引入新元素时也不要害怕重命名旧元素,以澄清它们之间的差异。 我们不是用石碑编码。 有些人梦想着将来验证自己的代码并期待未来的变化。 我宁愿使代码清晰地代表当前的情况,并在反映未来的将来进行更改。 这使我省去了很多我无法控制的事情。 我们控制双方 也许您没有花时间准确地命名某件事,因为它正在做很多事情…… 再塞另一种方法 有时正确的答案可能是重构基础实现以启用更好的名称。 我们都可以控制。 […]

一个APP产生多少次观看?

通过编码视图和创造力,该数字可能会比您想象的要少 我在本文中的动机是不评判工具。 但是,展示了另一种无需界面构建器的APP构建方法,即使用iOS本机API并通过创造力享受这一过程。 在这篇文章中,您将了解: 锚点布局 堆栈视图 依赖注入 数据流量 故事板? XIB? 编码视图? 从一个有争议的主题🙃开始。 我进入Xcode的第一步和一些专业的工作都是使用Storyboard完成的。 我无法想象有人可以用代码替换界面构建器的拖放。 因为,它非常简单,快速。 直到情节提要开始困扰我,然后才让XIB困扰。 在我更喜欢使用代码构建的视图之前,我非常抵制此更改。 但是有一天,我开始反思,得出结论,这是我的懒惰。 毕竟,当是全栈开发人员时,我写的是HTML,而不是拖放组件(例如旧的Dreamweaver)。 但是对我来说,Visual Format Language和NSLayoutConstraint构造函数很无聊。 视觉格式语言对拼写错误非常敏感。 NSLayoutConstraint的默认构造函数为long。 因此,我参加了Thiago Lioy @tpLioy关于视图代码的一些讨论。 在这些谈话中,他展示了如何将Storyboard项目迁移到使用Snapkit使用代码创建的视图。 结果令我惊讶的是,结果非常好。 这就是我开始喜欢查看代码的方式,谢谢@tpLioy。 但是我仍然想学习如何使用Apple为我们所做的事情。 那是我遇到锚定布局的时候。 NSLayoutAnchor Apple文档将NSLayoutAnchor描述为一个类工厂,旨在生成NSLayoutConstraint对象。 NSLayoutConstraint对象负责启用自动布局。 简而言之, NSLayoutAnchor将使创建自动布局中使用的约束变得更加容易。 使用NSLayoutConstraint方法代替使用NSLayoutConstraint类的构造函数创建约束。 这样做的好处是代码更简洁,类型检查可以避免创建无效约束。 例如,此检查将不允许将X轴属性与Y轴属性混合。 尽管NSLayoutAnchor类提供了附加的类型检查,但仍然可以创建无效的约束。 例如,编译器允许您将一个视图的leadingAnchor与另一个视图的leftAnchor ,因为它们都是NSLayoutXAxisAnchor实例。 但是,“自动布局”不允许将前导和尾随属性与左或右属性混合使用的约束。 结果,此约束在运行时崩溃。 NSLayoutAnchor 行动时间 为了演示如何在实践中使用布局锚,我创建了一个Playground。 在这个操场上,会有一张名片清单。 根据用户选择的计划,卡片的视图不同。 考虑到这一点,我创建了下面的布局。 一切的根源 如您所见,所有名片都具有相同的数据。 但是,显示方式有所不同。 如果您曾经使用过前端Web,那么它就像只有一个HTML,并且每种布局都有不同的CSS。 […]

面向对象的校长—普通英语

这篇文章讨论了面向对象的原始概念。 在编写代码时,您知道如何将方法声明为私有方法,或者如何从类中进行子类化,而在这里,我尝试用通俗的英语解释这些概念。 这是对每种情况的简单合理解释,以防您想将其解释为六岁的孩子: 遗产: 继承允许我们从类中继承子类。 在面向对象的编程中,类都是层次结构的所有成员,并且只有在继承的帮助下才有可能。 子类从父类继承方法和属性。 这使开发人员可以轻松地重用代码。 抽象: 抽象意味着表示基本功能而不包括实现。 这意味着什么? 抽象是根据事物在继承层次结构中的位置,用更简单的术语(抽象的细节)描述事物的概念或范例。 它有助于表示基本功能,而不必担心实现。 在最抽象的级别上,没有实现细节。 最抽象的概念位于顶部,更具体的思想位于底部。 该图表示抽象概念的一般概念: 接口是一组没有实现的方法。 抽象类包含抽象方法和具体方法,它们必须被继承。 封装形式: 封装用于定义,隐藏和限制访问以外的属性和方法。 它可以防止不必要地访问方法和属性(类是封装数据的容器)。 该访问仅在需要时可用,这由访问修饰符处理: 公开:可从任何地方访问 受保护的:可在相同的包和子类中访问 默认值(无说明符):包内可访问的表格 私有:仅可在同一类中访问,子类不可见 Swift中的访问修饰符可以是一个示例。 多态性: 多态性使我们可以定义在父类中已经声明的方法(在子类中)。 通常有两种类型的多态性: 编译时多态或重载: 您可以定义多个具有相同名称的方法,唯一的区别是方法签名。 运行时多态或覆盖: 您可以使用与父类(或已实现的接口)相同的名称和签名来定义方法。 这使我们能够定义特定于特定子类的方法。

适用于iOS应用程序的VIPER架构的优点,缺点和缺点。

VIPER介绍 如果您开发iOS应用程序已有一段时间,您会注意到大多数逻辑都放在UIViewController的子类中。 通常将其称为Massive ViewController问题。 视图是一个简单的对象,仅关心在屏幕上绘制自己。 模型是无用的数据存储,可以用简单的集合或复杂的数据结构表示。 基本上,所有其他逻辑都应该放在这个可怜的孤独ViewController中。 它将模型对象转换为更多对视图友好的状态,反之亦然。 它还处理用户输入,获取数据,进行网络调用,分配和显示其他ViewController。 所有这些乐趣都归于ViewController是否公平? 不仅ViewController的可读性受到额外的负担(在代码行中),而且可测试性,可维护性和重构速度也受到影响。 考虑到Swift瞬息万变,Apple每年都会发布新的iOS,因此维护和重构ViewControllers是您作为iOS开发人员的重要工作。 可测试性在这里非常重要,因为您不希望那些可怕的回归。 因此,一些聪明的人决定以ViewController基本节食的方式改进MVC(模型-视图-控制器)。 MVVM(Model-View-ViewModel)是第一次尝试。 它使ViewController无需在模型对象(如果愿意,可以选择业务对象)之间转换为对视图友好的对象(从现在起将它们称为ViewModels)即可。 这种方法提高了可测试性,并使ViewControlles更加精简,但这是否足够? 它不涉及对动作,网络,导航等的响应。 因此人们决定他们还需要从其他东西中释放ViewController。 首先,他们创建了Presenter (在MVVM的情况下为ViewModel)。 此类负责更新用户界面。 它接收业务对象并将其转换为ViewModels。 它从哪里接收它们? 来自另一个称为Interactor的类,该类负责从任何可能的地方获取业务对象:网络,持久性存储,并将它们传递给Presenter。 它还负责响应用户的操作。 因此,当您按下登录按钮时,ViewController会将其传递给Interactor并进行网络调用(通常,您想在一个单独的对象中进行此操作,更多信息在下面的内容中),等待响应,然后确定下一步需要执行的操作。 因此,当Interactor做出此决定时,它将调用另一个称为Router的对象(您可能会在某些文章中找到Wireframe ),该对象执行监视或以模态形式显示ViewController。 因此,您可能会问ViewController还剩下什么? 除了与Presenter通信外,它还可以管理很多事情。 由于我们在UIKit的领土上玩游戏,因此我们无法摆脱它的影响。 我相信您应该将ViewController分配为各种事物的委托和dataSource。 这样,您就不会在Interactor上做一些疯狂的事情。 不要试图破坏UIKit。 这是不可能和不必要的。 因此,我们有V表示视图 , I表示交互器 , P表示主持人 , R表示路由器 。 那么VIPER中的E代表什么? E代表Entity 。 实体基本上就是您在MVC中所说的模型 -枯燥的数据存储。 就我个人而言,我觉得将它放在VIPER中只是为了使其听起来很酷。 您的Interactor将从各种来源获得这些实体 ,但还将使用Services (封装此类任务的对象)进行网络调用或执行一些长期任务。 例如,您可以在ToDoList应用中创建TasksService (每个iOS开发人员都应该创建一个) […]

从头开始创建Marvel iOS应用。第2部分测试,覆盖率以及更多..

这是一系列文章的第二部分,介绍了如何使用许多不同的Pod和工具从头开始创建iOS应用,从而使您的生活更轻松。 如果您错过了第一部分,则可以在此处进行检查。 在这篇文章中,我将讨论测试,覆盖率报告,如何使用Fastlane自动化流程以及更多内容。 该项目的源代码可在此存储库中找到。 我为此帖子创建了一个名为v0.2的标签,您 只需克隆存储库并切换到标签v0.2。 初始步骤.. 首先,我们必须确保项目具有单元测试目标,如果不是这种情况,我们可以通过单击文件>新建>目标来创建目标 测试盒.. 为了正确创建测试,我将使用几个不同的测试库。 在编写测试的过程中,它们可以为我们提供很多帮助,因此,请将它们添加到我们的Podfile中。 在下面,您可以看到类似Pod的容器:Quick,Nimble,Fakery。 这些吊舱将大大增强我们进行测试的方式。 该测试并没有做太多事情,只是产生了一个期望,即true是true,并且总是会成功。 它看起来很简单,却有更大的用途。 这个断言可以告诉您一切都已正确配置和设置。 到目前为止,仅使用XCTest编写测试的人可能会感到奇怪,这种编写测试的方法是使用Expect而不是XCAssert来描述和创建断言。 但是,它更接近自然语言,因此到目前为止,它可以大大提高测试的可读性。 这就是为什么人们选择这种方法后,经过学习之后,它使编写测试变得更加容易和直观,从而增加了测试在项目中的采用率。 可以肯定的是,如果很难编写测试,则没人会编写! Quick和Nimble等测试框架的最终目标是充分降低学习曲线,以确保人们编写测试。 接下来..自动化,然后再添加复杂度.. 在添加任何其他测试之前,请确保我们可以运行测试并从cmd行生成代码覆盖率报告。 这样做将确保我们正确设置所有内容,而复杂度仍然较低。 这是一种安全的措施,如果有什么不对劲,我们可以减少要找出正在发生的事情的要点。 这一步非常重要,通过使我们的开发流程自动化,我们可以放心,以后再插入连续集成过程将更加容易。 Fastlane是一个了不起的工具,可以为我们提供帮助,我们可以使用它的“扫描”操作来运行测试,然后使用Slather生成测试覆盖率报告。 抱着你的马..首先更多的设置.. 在进行自动化过程之前,让我们确保每个人都在正确的页面中,这意味着,确保我们使用的是预期的快车道,cocoapods等版本。我们可以通过在项目中采用Bundler来做到这一点。 让我们创建一个像这样的Gemfile: 用Fastlane自动化.. Fastlane非常直观,我们需要做的就是运行其cmd并完成设置步骤。 完成此操作后,您会注意到一个名为fastlane的新文件夹,其中包含一些文件。 现在,让我们仅关注fastfile。 图为标签v0.2上的项目覆盖率报告, 97.16% 的确不错! 到达那里.. =) 现在,测试.. 让我们从模型层开始,确保在我们的情况下可以使用它们来映射api响应,因此我们必须有一种在测试中加载json并从中创建模型的方法。 为了做到这一点,我们将在测试目标中创建一个名为MockLoader的帮助程序结构。 下一步是创建第一个真实规范,让我们创建一个CharacterSpec,以测试我们的第一个模型。 这里没有太多事情要做,但是即使是这个小小的测试也可以证明我们的模型可以用来解析我们的api响应。 即使任何一次api调用都经过一次,我们也可以放心地声明。 这就是强大而有用的测试。 手动测试这种事情,没有自动化测试,这是不好的并且容易出错。 一路上有很多地方,事情可能会横着走,并表现出异常情况,例如互联网问题,网络层问题,api调用错误等。测试可以帮助我们避免所有这些,专注于我们真正想要的东西的情况下,有一种方法可以从json创建模型。 我不会涵盖该项目中的所有测试,否则这篇文章会很大。 但是,我强烈建议您克隆项目并检查所有项目。 现在,让我们继续进行下一种测试,即视图控制器。 测试ViewController .. 一个更大的例子,还有很多事情要做。 我将设计要点,并讨论一些重要的部分。 […]

Swift中的泛型和JSON解码

因此,上一篇文章写了有关如何使用Alamofire进行联网的文章,这使我回想起最初开始获取数据的时间。 一团糟。 就是这样: 假设您需要执行GET请求才能说出两个端点。 您最有可能做什么? 您很可能会复制第一个GET请求,然后将其粘贴并更改一些内容,例如端点和模型等。 您可能会执行以下操作: 当您添加更多请求时,这很快会使您的代码成为噩梦,更不用说看了。 这就是Generics发挥作用的地方。 我们可以使用更简洁的代码将这两个请求合并为一个函数。 就像上次一样,我将对所有API端点使用https://jsonplaceholder.typicode.com/。 模型 我们的第一个端点是: https://jsonplaceholder.typicode.com/posts : https://jsonplaceholder.typicode.com/posts 对于/posts ,我们将获取userId , id , title , body 。 实施泛型 现在我们有了数据模型,让我们设置通用函数。 如果您阅读了我有关Alamofire的上一篇文章,您可能会注意到一些差异。 而不是返回responseJSON我们只是返回response 。 同样,我们只获得response.data而不是response.data 调用我们的函数 最后,我们在使用JSONDecoder()地方进行了do catch 。 现在我们可以调用通用函数: 很简单,但是我们只给出一个url字符串,并给它一个可解码的模型。 现在我们有了通用的网络请求,可以将其用于所需的任何端点。 我们只需要创建一个可解码的模型,然后传递url端点即可。 然后再次 让我们调用https://jsonplaceholder.typicode.com/comments /comments返回一个postId , id , name , email , body 。 现在我们要做的就是调用我们的泛型函数。 我们可以继续前进,尽管我觉得您明白了。 如果需要更多请求,只需为该端点创建一个模型,请确保您符合Decodable ,然后调用通用函数并传递url和模型。 […]

快速运行Shell进程

每当我想进行一些快速脚本编写(例如创建大量随机测试用例以测试某些python程序)时, perl通常是我选择的语言。 当然,几天后很难理解,但是对于快速又脏的东西,它的工作非常出色。 主要优点之一是,从perl运行shell命令非常简单:您只需在反斜杠中写一些东西: `echo“ foo”` 例如,这使我很容易在计算出要使用的测试输入后调用适当的python脚本,然后在过程完成后验证输出。 为了将脚本编写过程切换到Swift,我想知道是否有可能这样做。 事实证明,在Foundation中有一个名为Process的类可以做到这一点。 但是,像大多数基础课程一样,它非常灵活,这也意味着有很多样板要进行。 这是我尝试将其转换为简单的函数调用。 首先,我在Google上搜索了一些使用Process类的代码片段,这样我就可以获得一种初步的方法。 事实证明,我还需要使用Pipe类来捕获输出。 真正困扰我的是,我正在尝试测试的程序需要从stdin读取其输入。 我想给它提供一个普通的字符串(而不是编写它来读取一个文件,这似乎太麻烦了),但是我找不到用Pipe做到这一点的方法-官方文档使我在其他方面进展顺利但这使我失败了。 然后,解决方案:将输入内容写入临时文件,使用该文件作为输入来运行该过程,然后删除该文件。 笨拙,有点太笨拙了,但是我知道了。 考虑到我以为刚开始时这甚至是不可能的,因此产生的功能出奇地好。 我只是用它们来创建一些测试功能并成功地对一些作业进行评分。 最终代码在下面的要点中:

我讨厌我爱你:了解关闭和完成

封闭是Swift的一个很棒的小功能,我绝对讨厌。 它们提供了许多好处,当我第一次以正式形式遇到它们时,就被它们让一个类遍历另一个函数的范围来获取和设置我从未见过的变量的能力所震惊。 理论上闭包是如何工作的: 在我自己实施它们之后,我很快意识到它们确实是可怕的生物,使我的生活更加艰难。 闭包在实践中如何工作: 但是,很多……我的意思是大量的练习,阅读和询问一百万个问题,我很快就开始理解它们的工作方式以及何时以及如何使用它们。 之后,我觉得也许是我最初想到它们的方式引起了我的困惑,所以我想用做晚饭的比喻来简单地详细解释它们。 一个简单的关闭函数说明: 现在,当我们调用函数时,就是魔术发生了! 我们从函数makeDinner()上的紫色箭头开始。 当我们调用此函数时,我们需要为其提供两个参数,第一个是一个字符串(我们选择“牛排”),第二个是一个函数。 我们赋予原始功能(makeDinner)的功能是choiceSides。 当我们的makeDinner()实现在调用完成函数时达到其代码中的要点时,我们实际上停止了执行并开始运行传入的函数。 有一些方法可以运行makeDinner()的其余部分,而无需等待第二个完成,但是我没有在此处实现它以保持简单(好像)。 ChooseSides()函数的实质无所谓,只是知道它以字符串作为自己的参数,这是由makeDinner()提供的,当我们在类实例anthony上首次调用它时,我们直接将其提供给makeDinner()。 choiceSides()的结果是一个字符串,该字符串冒泡返回并进入makeDinner,并替换makeDinner()首次调用chooseSides()的位置(在我们打印的字符串的第二个插值处)。 如果这一切看起来都是令人费解的,我常常想知道我这样做时是否没有违反自然法则,但是直到现在仍然有效。 再往前走,我们可以直接从choiceSides()中提取代码,然后将其直接用作makeDinner()作为封闭函数,而不用传入choiceSides()作为参数。 查看上面代码的下半部分,看看原始方法和闭包函数方法都可以打印出相同的内容!

动画制作NSLayoutAnchor约束和所涉及的陷阱

正确布置iPhone应用程序有时会感觉像一个项目的20%占用您80%的时间/时间。 这就是为什么当苹果在iOS 9中用NSLayoutAnchor击中我们时,我抓住了让生活更轻松的机会。 如果您还没有花时间使用NSLayoutAnchor,请快速阅读一下NSLayoutAnchor入门,然后再回来。 今天,我想向您展示如何动画化我遇到的那些限制和最佳实践。 动画NSLayoutAnchor约束 如果您想在这里看到完整的项目,可以在GitHub上看到。 让我知道您在设置约束动画时所做的任何改进。 如果您已经阅读了本文,则非常感谢! 我真的希望这值得一读,并且您会分享/喜欢/心动,并让其他人知道这也值得他们度过! 请给我评论,我很乐意与喜欢这篇文章的任何人交谈! Auf wiedersehen! 有关

Mengenal代表团pada Swift

彭加塔尔 Biasanya kalau bermain dengan UITableView ataupun UICollectionView杨diletakkan pada UIViewController Pasti akan menemui suatu语法sepiti ini … self.tableView.delegate =自我 Untuk bisa berinteraksi dengan tableView塔迪,misalkan melakukan suatu aksi tertentu ketika salah satu baris pada tableView telah dipilih maupun akan dihapuskan,maka kita sering kali menggunakan 代表团 pada tableView supaya bisa melakukan aksi dissebutbut。 彭巴哈桑 塞卡拉·巴哈萨(Secara bahasa), 代表团成员 auau […]