Estéartigo pretende trazer ao seu leitor,软件开发者,软件开发者,可移动iOS应用程序的速记4 SOLID和KISS解决方案的重要性软件quando desejamos construir umasoluçãorobustaesustentável。 Arquitetura软件 从本质上说,使用高质量的语音软件可以通信和使用Carinho。 可以使用部分软件,也可以使用ganhar novas funcionalidades软件。 一种由软件组成的软件,它可以解决软件开发中的任何问题。 Neste linkháum materialtambémescrito por mim quepoderáte explicar mais sobre o problema。 通用软件安装软件鲁棒软件,依赖软件。 界面和接口的实现以及实现的接口。 EstePadrãonos ajudatambém是princípiodainversãodadependência (SOLI D )的代表。 蟒蛇 Como boaspráticas, POO的公用事业概念,通用的公用事业RXSwift公用程序。 Estaspráticas,pro deto的长期运作,nos ajudaram和SOLI D restantes的回应。 没有iOS的重要事项 Este artigoabordaráo或us e dedeçênciautilizando使用了一个故事板 ,并推荐了一个UI。 使用casovocênão,使用nãopoderáusar ométodo 准备(用于segue :) pois作为seguessão类,特别用于故事板 。 […]
本文是对 KeyPathKit 框架背后思想的详细介绍 。 如果您喜欢您将要阅读的内容,我敦促您看一下图书馆必须提供的所有功能😉 非常感谢 JérômeAlves 向我展示了我将在下面描述的一种方法。 Swift 4引入了一个称为KeyPath的新概念。 它允许开发人员处理特定类型的特定属性。 稍后,他们将能够针对指定类型的对象评估此句柄,以便为其属性获取值: 最重要的是,此过程完全是类型安全的,并且与struct和class都兼容,并且其语法灵活而简洁:您可以使用类型推断(例如\.count将是有效的)并且可以轻松地链接属性(例如\UIView.layer.cornerRadius是有效的KeyPath ) 现在考虑以下示例数据: 用例进行改进 假设我们要过滤掉lastName不是”Webb” 。 使用filter ,我们可以按照以下方式编写: 现在,我们尝试重写此代码,以便使用KeyPath而不是闭包: 呼叫站点看起来已经干净了一些,而且在不关闭的情况下也更易于阅读。 但是最好的还没到。 现在想象一下,我们想要保留其lastName遵循使用正则表达式指定的特定模式的值。 现在,如果我们只想获取名称以”son”结尾的联系人,则可以如下编写: 这种语法看起来确实很干净,并且比闭包可以实现的可读性高。 谓词介绍 让我们回到第一个用例,再次比较两种语法: 第一种语法具有直接使用运算符==的优势,当人们快速浏览代码时,该运算符提供了宝贵的视觉线索。 第二种语法的优点是不需要闭包,这使代码更加简洁。 如果我们将它们的优点结合在第三种语法中怎么办,那将使我们能够编写: 当然,那看起来不错! 👍 那么如何实现呢? 首先要开始的是运算符== 。 在Swift中,我们习惯于在Equatable类型的上下文中定义此运算符。 在这种情况下, ==返回Bool 。 但是完全有可能重写==以使其返回Bool以外的其他值。 为了解决我们的问题,我们将编写一个返回Predicate的重载。 什么是谓词? 您可以将其视为表达对特定类型的值的约束的一种方法。 一旦定义,就可以针对指定类型的特定值评估谓词。 首先,我们定义一个类型来实现KeyPathPredicate : 然后,我们重载==以使其采用KeyPath并且常量具有参数并返回KeyPathPredicate : 最后,我们定义一个与KeyPathPredicate一起使用的filter版本: 而且,瞧,我们现在可以使用目标语法来编写代码🎉 结论 为了使本文的长度合理,我仅考虑了一些基本用例。 但是还有许多其他用例需要讨论。 例如,最好重载运算符~=以便根据正则表达式评估String值。 […]
众所周知,移动应用程序的范围正在日益扩大。 即使这样,登录页面/模块也不是一件容易的事。 因此,完成可测试,可重用和用户友好的登录编剧非常重要。 这篇文章旨在展示iOS登录/登出时的最佳做法,而无需情节提要,而是带有动画。 TL; DR 如果您只是对项目感兴趣,而不对故事感兴趣,那么这里是github存储库: ogulcan / iOS登录示例 iOS登录示例–一个示例iOS应用程序展示了如何在没有故事板 github.com的情况下处理登录/注销 分步指南 0.简介 考虑一下登录方案。 对于大多数应用程序,登录不是应用程序的真实部分。 通常,登录是要采取的步骤。 并且在必要时需要重新应用这一步骤。 例如,如果令牌已过期或用户更改了密码等。 因此,当应用程序启动时: 1.需要知道用户是否已登录或令牌未过期或用户未被禁止等。这意味着应用程序应检查相关服务。 2.如果用户正常,则意味着已登录,首页应显示为下一页。 如果用户不满意,则意味着应再次登录,登录页面应显示为下一页。 3.设置一些假登录,如果我们使用一些动画会更好。 这些是我要采取的步骤。 让我们开始。 1.检查用户 您可能希望在UserDefaults上保存用户。 否则令牌可能永远不会过期。 即使不推荐,事实并非如此。 因此,您可能不需要检查用户是否仍在登录。尽管我仍然建议您遵循以下步骤。 通常建议使用以下方法: 在didFinishLaunchingWithOptions内部的AppDelegate.swift中,检索用户数据并确定应显示哪个视图控制器。 并如建议的那样,让我们创建一个名为AppStoryboard的文件来定义每个故事板文件。 还有UIViewController扩展。 我们准备以更简单的方式启动每个视图控制器。 3.登录/注销操作并进行动画处理! 现在,如果我们运行该应用程序,我们将面临登录屏幕,因为我们没有任何令牌。 让我们实现登录和注销IBAction。 首先,我们需要一个更新RootViewController的方法/扩展。 每个IBAction使用钥匙串删除或保存令牌并设置视图控制器。 最后,如果我们运行该应用程序,则每个按钮都可以正常工作。 如果仅点击登录并重新启动应用程序,我们将面对主视图控制器。 精细。 为了更好,让我们添加一些动画。 首先,我们需要更新UIApplication扩展。 这是新版本: 准备使用。
2015年11月,我踏上了一个激动人心的新旅程,构建一个iOS应用,将iPhone上的图像和视频投射到连接Chromecast的电视上。 在Swift中,作为一个单独的开发人员,作为一个辅助项目,所有这些都在其中。 在这篇文章中,我将分享一些考虑因素和实践,这些因素和实践已帮助我在3.5个月内将代码扩展到4000行以上,同时又将技术负担降至最低,并最大程度地提高了可维护性。 快速预览: 就上下文而言,第一个版本的功能已完成约50%,因此我希望代码库最终会翻倍。 与我以前的所有应用程序和客户端项目相比,我估计在编写更多模块化代码而更少编写模块化代码的同时,我可以更快地增加价值- 至少两倍 。 事不宜迟,这就是我的工作方式: 口头禅:为维护性和未来自我而设计 力争绝不重复代码 始终将源文件保持在200行以下 代码本地化获胜。 凝聚 不要分散属于同一类的多个类代码。 使用类内部的扩展对确实属于一起的功能进行分组。 这使得在需要时更容易将事情排除在外。 适当地命名事物 最小化可变状态 仔细考虑对象图中的所有权 , 尤其是对于异步调用 使用ViewModels驱动UI更新 在添加新功能后始终进行重构 添加新功能后,请务必进行广泛的测试-在添加新代码之前先修复AKA错误 默认将所有内容设为私有 在Interface Builder中完成所有UI和布局。 代码不是您的表示层所属的位置! 错误处理对于应用程序设计至关重要 使错误对开发人员和用户友好 程序员错误应立即消除 奖励 :将开发容器用于我计划开源的自包含代码,例如这样。 到目前为止我还没有做 ReactiveSwift :我很想尝试一下,并在应用程序中利用Observables的功能 ,但是还没有机会。 TDD / BDD /单元测试-尽管我已经对依赖注入进行了仔细的考虑,并且上面的约束迫使我保持班级小。 集成测试。 由于我总是在添加新功能之前修复错误,因此这并不是一个强烈的要求。 但是,我为接收器应用程序构建了一个伪造/存根 ,以便在没有可用的Chromecast设备时可以测试大多数应用程序。 另外,我可以在运行时在假/真实接收器之间切换。 其他注意事项 对于这样的附带项目,我发现尝试每天取得一些进步是有益的,并且如果不进行任何工作 ,通常连续三天不能超过。 这使我始终专注于产品,并且我可以计划新的工作或考虑如何持续解决问题。 在单独构建此文件时,我可以使用一个Google文档来跟踪进度,错误,待办事项,里程碑和日常任务。 在现阶段,我发现这比拥有专用于每种情况的专用工具要简单,这在大多数组织中都是如此。 最后,我选择将其作为辅助项目进行构建,同时将大部分时间用于客户服务。 好处: […]
我创建代码的过程如下所示: 研究目标的细节(学习) 提出实施计划(创建) 代码(单击并键入) 当我意识到我有一个错误的假设时,请返回步骤1(遗憾) 在进行编码工作之前,正确命名类型是计划中的最后一个障碍。 就像,嗯,我知道计算机不在乎我给我命名的类型。 机器解释指令时,所有这些都将被剥夺。 我的功能不会受到影响。 为什么我花了很多时间来确定角色以及事情如何融合在一起? 因为代码不仅仅适用于机器。 适用于必须充分理解它才能正确操作它的开发人员。 该类别中包括“未来”。 要做到这一点,就需要弄清问题集,并有足够的同理心,以使听众可以预期您选择的名字的所有含义。 真名 有一个古老的想法,即如果您知道某事的“真实名称”,那么您将拥有权力。 这是幻想中的常见现象,也是宗教故事的一部分。 以伊西斯和拉的故事为例。 伊希斯(Isis)是一位出色的治疗师,但只有知道她的真实姓名时才能帮助Ra。 他试图用“小写”的名字满足她的要求,但这仅使Ra未能解决核心问题。 一旦他放弃了他的真实姓名,她就可以治愈他。 这听起来像调试我。 如果您不知道所处理事物的真正含义,就无法解决该问题。 懒惰的标签将欺骗人。 您在阅读代码时让人们做的心理锻炼越多,使用它的认知就越消耗精力。 “是的,被称为 Provider 但实际上只是转换数据。” “该 modelId 不适用于该模型,适用于其他通用模型。” 但是,如果您真正知道什么是东西,则可以轻松地对其进行操作。 这很重要,因为将来必须更改代码。 我的理想是功能与代表功能的标签之间的绝对统一。 既然是理想的,我永远都不会到达那里。 想起名字时会出现回报递减的情况,但是值得花一些时间。 在清晰度和可读性之间取得平衡 某物的最精确名称可能是…… 绝对清晰。 把它收拾好。 该名称公然忽略了所有可用的上下文。 显然,这个例子很荒谬,但是添加不必要的限定词可能很诱人。 即使您觉得这个名字不是最好的,也最好在项目内部保持一致,而不要在两个约定之间来回穿梭。 一旦人们适应了您项目的标准,他们就会知道您在说什么。 一致的信息比冲突的信息要好,即使最终效果不佳。 同样,在引入新元素时也不要害怕重命名旧元素,以澄清它们之间的差异。 我们不是用石碑编码。 有些人梦想着将来验证自己的代码并期待未来的变化。 我宁愿使代码清晰地代表当前的情况,并在反映未来的将来进行更改。 这使我省去了很多我无法控制的事情。 我们控制双方 也许您没有花时间准确地命名某件事,因为它正在做很多事情…… 再塞另一种方法 有时正确的答案可能是重构基础实现以启用更好的名称。 我们都可以控制。 […]
我是卫斯理大学(’18)的计算机科学和戏剧双专业,整个暑假都在Flatiron学校(FS)学习。 由于我一生都是学生,所以我习惯于进行测验,学习测验,在测验前拖延,以及受到测验的情绪影响(无论好坏)。 我认为大多数人都可以同意的事实是测试很糟糕。 但是,就编码而言,从长远来看,测试可以节省时间和金钱,并且可以产生更完善,更完美的应用程序。 要进行大量测试,对于一篇博客文章而言,测试太多了,但让我们对其进行分解。 我们都很熟悉XCode向我们提供的红色或绿色小菱形,其中包含支票或’x’。 我们都看着颜色从红色变成绿色,有时又回到红色。 最后,我们全都翻了个白眼,甚至在看到红色的眼睛时甚至撞到了墙上,而在看到绿色的眼睛时就为喜悦而跳了起来。 作为程序员,成功是保持我们编码的动力。 小小的成功是使头脑振奋值得的。 想象一下,如果等到所有编程完成后才知道代码是否按预期进行编译和运行,您会头疼。 这就是为什么测试是一种绝妙的做法。 测试使我们能够构建声音产品并对其功能进行检查。 对于新编码员,养成优雅的习惯很重要。 测试是一种习惯,可能会改变您对编程的看法。 编写测试可能有些繁琐,因此尽早开始很重要。 您越早开始编写和练习进行测试,就会越好。 测试方式 这是几个不同测试选项的简要说明。 Specta和Expecta是不错的选择,因为它们不需要您输入返回类型,并且可读性强。 “总体Specta和Expecta使得语法更加简单,易于编写和阅读。 这直接转化为开发人员的生产力” ( Harry Hornreich )。 XCode提供了一个测试构建框架,使编写测试更加容易。 XCode框架很好,但是IMO最多不过是万不得已,因为它总比没有好。 XCode框架的问题在于,无法知道您正在包括最有意义的测试。 有很多UITesting工具(例如XCode)作为唯一的测试源都不可靠。 有意义的测试 测试有各种形状和大小。 编写测试可能并不像提出测试那样困难。 例如,假设我们在Pig-Latin中编写代码字。 “ in”和“ as”之类的词保持不变。 如果程序员不熟悉该语言,则他们可能会忽略此细节,并让其代码返回“ niay”和“ saay”。 或者,他们可能会记住该规则,却忘记了以元音或以“ sh”或“ ch”开头的单词在其中辅音必须保持在一起的单词的规则。 这种代码中有太多的出错机会,这就是为什么使用测试有益的原因。 如果没有遵循的准则,没有规则,那么如何使程序员避免使程序充满错误? 测试的目的是消除运行时错误(与语法等编译器问题相对)。 测试不是为了弄清楚如何使用内存空间,也不是为了提高速度和效率。 测试以二进制形式进行:您通过或失败,直到通过。 有被迫失败的事情。 强制失败用于指示代码是否朝着不应执行的方向行进。 如果存在某种情况,您担心会发生并且不希望发生,那将是包括强制性失败的充分理由。 右BICEP Right-BICEP是我经过多年编程学习的一种助记符设备。 Right-BICEP是考虑编写代码的绝佳方法。 正确是指检查结果是否正确。 […]
SwiftLint是用于实施Swift样式和约定的开源工具。 它是由Realm开发的。 您可以设置不同的编码样式规则,并在新项目和现有项目的开发过程中强制使用它们。 SwiftLint具有命令行工具,Xcode插件,AppCode和Atom集成。 因此,它始终适合您的开发环境。 如果您违反棉绒规则,它将向您显示警告和/或错误。 步骤1.安装工具 将快速线添加到Pod文件并执行Pod安装。 吊舱“ SwiftLint” 步骤2.在构建中运行脚本 “ $ {PODS_ROOT} / SwiftLint / swiftlint” 现在,无论何时构建目标,Swiftlint都会自动运行。 如果使用现有项目运行,则可能会有警告/错误。 这是因为使用了默认规则。 步骤3.自定义规则 您可以找到所有规则。 默认情况下,启用约70%。 您可以使用项目根文件夹中的.swiftlint.yml文件来自定义规则。 让我们看一下如何创建.swiftlint.yml文件以及配置文件如何工作: #您可以禁用默认情况下已启用的规则 disabled_rules: -标识符名 -force_cast #同样,您可以启用默认情况下已禁用的规则 opt_in_rules: -first_where #排除您不想掉线的目录 排除: -豆荚 – 快车道 #使用“ xcode”,以便在构建时,结果将显示在Xcode中 记者:“ xcode” #其他记者:json,csv,checkstyle,junit,html,表情符号 #默认情况下,“ function_body_length”规则在40时触发警告,在100时触发错误 #这个例子增加了3倍 function_body_length: 警告:120 错误:300 为您的项目创建.Swiftlint.yml 1 —打开终端: CD …到您的项目路径 2-创建文件: […]
尽管已经写了有关如何正确使用UITableView ,但新开发人员甚至是经验丰富的开发人员仍然偶尔会遇到一些问题。 关于如何使与UITableView相关的代码更短,更好和更易读的内容,有很多有趣的文章以及方便的示例和最佳实践,但是以某种方式,我还没有看到所有建议的总览。 因此,我决定在这里列出至少在使用UITableView时要遵循的所有原则,但是如果您有任何添加或分享的方式,请在下面的评论部分与我联系🙂 0.分成几节 假设您有一些要使用UITableView实现的Profile屏幕: 第一个建议很简单:将表分成几个部分,以使用不同类型的单元格。 如果 indexPath.section == ProfileSectionIndex { //对个人资料进行处理 } 如果 indexPath.section == InfoSectionIndex { 整数索引= indexPath.row //用info [index]做点什么 } 如果 indexPath.section == FriendsSectionIndex { 整数索引= indexPath.row //与朋友做某事[index] } 比这更有意义,更容易使用: 如果 indexPath.row == 0 { //个人资料 } 如果 indexPath.row> 0 && indexPath.row <info.count + 1 { int index = indexPath.row-1 //我看到了很多次T_T […]
最近,我的伙伴对编程表现出了兴趣,因此自然而然地我推荐Swift作为一种很好的语言。 我花了很多时间亲自研究了Swift的最佳实践,我想确保她确实遵循了整个Swift社区的最佳/常见实践(我认为其中有些是最佳实践),并且没有从一些那里的教程。 即使这些教程为初学者提供了一个很好的起点,我也注意到一些确实困扰我的做法,我建议您反对。 注意 我应该指出, 这要取决于我在编写Swift代码时的最佳做法以及我在社区中的研究中所收集的内容。 我敢肯定会有人不同意,这很好。 我仍然会睡个好觉😉 首先,让我们从合作伙伴搜索初学者教程时遇到的编码实践开始。 我还将介绍与其他开发人员一起进行项目时所经历的一些经验。 1)冒号空间 尽管这看起来很小,因为它只是一个空格,但是它可以大大提高代码的可读性。 推荐的 命名:字符串 不建议 让名字:字符串 命名:字符串 让名字:字符串 简单。 在冒号之后,在类型之前添加一个空格。 2)花括号 当谈到花括号时,通常似乎是一个意见问题。 但是,在浏览互联网上的一些样式指南,Apple文档中的示例以及我个人的看法时,确实有一个赢家。 推荐的 如果isValid && list.count == 0 { …}否则,如果isValid { …}其他{ … } 不建议 如果isValid && list.count == 0 { …} 否则,如果isValid { …} 其他{ … } 要么 如果isValid && list.count == 0 […]
您已经知道什么是单元测试,并且您可能已经在自己的iOS应用中编写了其中的一些测试。 那很棒! 现在,我们将进一步了解单元测试的结构。 当以某种方式编写单元测试时,它们是最有效的。 目标是以一种有组织的方式隔离组件和行为,从而使您深入了解应用程序的哪些部分有效,哪些无效。 只需一点技巧,您就可以编写单元测试来帮助您诊断问题,从而节省了比花费更多的时间。 这是创建测试套件时应遵循的最佳实践的简单列表。 隔离组件 好的单元测试不会尝试一次全部测试。 它一次测试一个组件的一种行为。 这是一个简单的经验法则。 每个要测试的组件都应该有一个XCTestCase文件。 该组件的所有测试都在该文件中。 在我的一个项目中,我有一个类来验证用户在文本字段中键入的薪资。 我将其称为PayrateValidator ,并将其命名为PayrateValidator.swift 。 在相应的测试套件中,测试PayrateValidator的XCTestCase子类称为PayrateValidatorTests ,包含该文件的文件称为PayrateValidatorTests.swift 。 这样一来,您也可以轻松地发现应用程序的哪些部分未被单元测试覆盖。 如果没有相应的测试用例文件,则很有可能没有该组件的单元测试 。 您还可以使用Xcode的测试覆盖率工具,我们将在另一篇文章中进行介绍。 关键是要有某种命名约定,以便您知道哪些文件可以测试什么。 等待。 我没有像这样的小组件。 我该怎么办? 对于初学者的iOS开发人员而言,这可能很难。 如果您没有MVC或MVVM等设计模式的经验,则您的应用程序可能没有任何隔离的组件。 您可能拥有一个巨型视图控制器,其中包含所有应用程序功能。 没办法判断。 我们都必须从某个地方开始。 我自己写了很多庞大的视图控制器。 编写好的单元测试的关键是要理解,您需要将应用程序分解成可以测试的较小部分 。 例如,如果视图控制器进行网络连接,请提取该逻辑并创建一个可以测试的单独的网络服务组件。 如果您不知道从哪里开始,请继续阅读一些常见的iOS应用程序设计模式,例如MVC或MVVM。 只需遵循这些步骤,您就会自动获得一个具有单独组件的应用程序,与庞大的视图控制器相比,这些组件更容易进行单元测试。 隔离行为 假设您已经隔离了一个组件。 您有一个与其关联的XCTestCase文件。 凉! 现在您需要测试。 结构良好的单元测试套件将每个组件分解为行为,每个行为都有其自己的功能来测试它们。 假设您正在编写Rick Astley的人工智能版本。 只是奠定基础,您可以像这样模拟他的一些行为。 这必须是Rick Astley的最笨拙的AI版本,但是也许这是您永远需要的所有编程。 在您的测试用例中, 通用约定是在单独的函数中测试不同的行为 。 它应如下所示。 在这里,我们只是断言,Rick […]