Tag: 移动

用继承编写可测试和可维护的代码

总览 软件工程师应努力实现的众多目标之一是构建可测试且可维护的代码,并且似乎许多人无法编写此类代码。 我敢肯定有很多原因会导致这一因素,例如完成项目的紧迫期限,或者工程师可能没有学习编写代码的正确方法。 我在Kaodim工作,我很高兴能有机会向我的前辈学习,并能够理解为什么我们倾向于以某种方式做事。 我记得在Kaodim编码我的第一个功能时,我在很多方面都感到不足,因此开始编写意大利面条式代码。 当我重新审视我的第一个功能时,我开始注意到我以前犯过的错误,并且我觉得自己可以做得更好。 供您参考,我的第一个功能称为“客户注册”,它允许新用户注册,而现有用户可以使用OTP功能登录。 这是该功能的技巧,但是随着我们深入研究,围绕它展开的逻辑很多。 对于这项功能,八月,我的上司创建了一个一次性密码库,我可以不时地对其进行修改,以适应该功能的需求。 代码气候测量 我们使用Code Climate来衡量我们的代码质量和可维护性。 在重构代码之前,我的PhoneNumberViewController和VerifyPhoneViewController的质量进行了如下测量: 继承方法 这里的计划是专门使用面向对象的编程继承,并且通过这种技术,我能够编写可伸缩且可测试的代码。 让我直观地向您介绍我们预期的代码结构。 为了让您更清楚地了解情况,我有两个父类,其子类数目灵活。 每个子类都将从父类继承,这样我就可以消除子类中的重复代码,并可以添加所需的任意多个子类。 让我以可视化的方式向您展示屏幕,然后给您一个场景。 作为新用户,我输入了我的电话号码,并被提示使用OTP代码进行注册。 然后,我通过短信收到我的OTP代码,并将其输入到我的验证屏幕上。 通过这种方法,我能够最大程度地减少代码中的冗余并拥有更简洁的代码结构。 但是,作为工程师,通过查看代码可以清楚得多。 我们将首先查看父类,在该类中,后端工程师创建了一个API,以检查电话号码以确定是否需要验证电话。 在满足不同条件的情况下,执行了不同的函数,但就我而言,我创建了几个空函数,这些空函数可以被子类覆盖。 比以前的分数高两个等级。 但是从可维护性来看,持续时间从24小时分别提高到25分钟和1小时有很大的提高。 我认为这是一个巨大的进步。 但是,我觉得我们仍然可以做得更好。 随之而来的是,所有子类创建的可维护性得分为A,0分钟。 快速而灵活地编写单元测试 我们将使用Quick&Nimble进行单元测试。 首先,我们将模拟自己的数据,而不依赖于API调用。 我们可以这样做,如下所示: 在这里,我们正在创建自己的模拟数据版本,以确定每个键的值,然后可以选择所需的返回值。 接下来,一旦有了模拟数据,就可以进行相应的测试。 首先,我们将测试电话是否被拿走,我们不允许用户注册。 我们可以通过选择checkNumberCase以返回我们需要的某些值来进行检查。 像往常一样,没有我的上校奥古斯特的帮助,我一个人不可能提出这种解决方案。 他在提出减少重复代码的解决方案方面做得非常出色,我得以在他的指导下实施该解决方案。 最后,我相信有很多不同的方法可以实现这一目标。 但是,我发现它可以以我的方式很好地工作,如果您以任何方式认为可以完成任何改进,请在下面随意评论。

Swift 5中的ABI稳定性–这是什么?

从事Swift工作的人谈到了长期目标,即稳定macOS,iOS,watchOS和tvOS的Swift ABI。 这实际上是什么意思? ABI ABI代表Application Binary Interface ,它定义编译的代码如何与其他编译的代码交互。 这意味着我们需要具有良好的调用约定,命名,对象在内存中的布局等。ABI的用途包括用户运行的程序与操作系统之间的接口,该接口将定义如何在机器代码中访问结构。 ABI还是API? API代表应用程序编程接口 ,这是一个较高级别的接口,通常Swift程序员可以访问该接口访问基于库或基于Web的系统。 ABI兼容性是什么意思? 缺乏ABI兼容性将意味着编译后的代码将无法在运行时与其他编译后的代码进行交互。 因此,有意义的是,Swift始终具有ABI,并且随着语言的成熟,它一直在稳步发展。 那么ABI稳定性对Swift意味着什么 具有兼容ABI的已编译Swift代码(例如应用程序或库)可以彼此交互。 这可以采用相互定义的调用函数和方法的形式,并在它们之间的API边界上来回传递值。 ABI稳定性 为了获得ABI稳定性,Swift需要锁定关键方面或为向前兼容做好准备。 ABI稳定性意味着要使用特定的Swift版本编译一个Swift库,并且仍然能够在运行时从使用更高版本的Swift构建的应用程序中与它进行交互。 同样,使用比特定Swift库更早的Swift版本构建应用程序仍然可以编译和运行。 未来 Swift 5向前发展将允许使用未来版本的编译器进行编译的框架/ SDK仍然可以正常工作。 Swift 5还有其他一些很棒的功能,因此当然还有很多值得期待的地方! 官方资源:https://swift.org/blog/abi-stability-and-more/

适用于类固醇的iOS模拟器:提示和技巧

iOS模拟器是任何iOS开发过程的组成部分。 我们就是不能忽略它。 Xcode 9中的New Simulator带来了许多有用的技巧,可以使您的工作效率更高。 最后,苹果公司回忆说他们在那里有模拟器! 与以前的适度更新相比,此更新似乎意义重大。 🙌 因此,让我们分解一下,列出我在新的iOS模拟器中发现的所有功能(您也可以在旧的模拟器中使用一些技巧)。 #1在Xcode的全屏模式下使用Simulator 当您拥有13英寸的屏幕时,Xcode的全屏模式将为您节省生命。不幸的是,您以前无法在Xcode的全屏模式下使用Simulator。现在,您可以 为此,您需要在根目录中创建一个名称为“ AppleInternal”的空文件夹。 只需在下面运行此命令,然后重新启动Simulator: 须藤mkdir / AppleInternal 新菜单项应显示。 ☝️ 注意: 我已经在Xcode 9b3的Simulator上测试了这种方法。 如果没有,请在此处下载最新的Xcode。 #2一次打开多个模拟器 您还记得在不同的模拟器上测试应用程序的挫败感吗? 以前,您当时只能打开一个Simulator实例。 如何在旧版本的Xcode中打开iOS模拟器的多个实例有很多“技巧”。 但是最后,使用Xcode 9可以立即使用此功能。 #3调整大小模拟器,就像常规窗口一样 在Xcode 9之前,我们只能使用“缩放选项”来调整模拟器的窗口大小。 现在,Apple终于使模拟器窗口的大小可用。 这是有用的小细节,如果您打开了多个模拟器,可以帮助您有效地组织工作区。 #4录制模拟器视频 苹果在Xcode 9的官方“新功能”文档中声称, 现在您可以录制模拟器屏幕的视频。 这不是完全正确的。 您甚至可以使用simctl在旧版本中执行simctl 。 我没有找到任何证据可以通过界面启用视频录制(iOS 11中的内置屏幕录制除外)。 要获取视频文件,请执行以下命令: xcrun simctl io引导的recordVideo –type = mp4 booted —表示simctl选择当前引导的Simulator。 如果您有多个引导的模拟器,则simctl选择当前活动的实例。 #5直接从Finder共享文件到Simulator 现在,模拟器具有Finder扩展程序,该扩展程序使您可以直接从Finder的窗口共享文件。 […]

简单的UIViewController状态机

如何轻松地在不同的视图之间切换 作为移动开发人员,我们非常普遍,必须实现某种内容视图(通常是列表),以显示必须从后端服务中获取的数据。 此外,通常还必须对某些错误或空视图的结果做出反应。 有了这个要求,在iOS开发之初,开发人员就习惯了与此非常类似的设置: 一个UIViewController + UITableView来显示内容列表,并在等待时带有一个UIActivityIndicator 。 表示错误状态的UIView 。 另一个UIView表示空状态。 取得成功后,除了隐藏加载指示符之外,我们什么也不做。 但是,如果提取操作因错误而结束或返回空数据集,则我们将必须: 隐藏UITableView 。 创建要显示的错误或空白视图的实例,通常将列表视图控制器设置为其委托。 将子视图添加到列表视图层次结构中。 尽管这种方法没有错,但是就可伸缩性和维护而言,它并不是理想的处理方式: 我们必须保持特定的逻辑,以确定何时显示或隐藏每个视图。 如果有代表团要做,这也迫使我们将内容视图与其他视图结合起来。 当添加新状态时,通常需要使用臭味的switch语句,这需要大量的工作。 由于同时存在多个视图,因此具有更高的内存占用量。 幸运的是,iOS 5.0附带了一个新的API,可以将视图控制器作为其他视图控制器的子代来管理视图控制器,这使得我们可以做自己的容器视图控制器(例如本机UINavigationController , UITabBarController等)并以更好的方式重用组件在视图生命周期方面,允许使用UIViewController实例组成复杂的视图。 在本文中,我将展示一种非常简单的方法来说明如何使用子级视图控制器对视图状态进行建模。

Twitter最佳iOS技巧:11月版

开发社区在11月非常活跃,因此我为您找到了许多出色的iOS Twitter技巧。 准备探索Xcode 9的最新功能(暂时忘掉一些错误!),有关单元测试的许多技巧(您已承诺明年开始编写),方便的LLDB详细信息和一些有趣的时刻! 上个月开始享受280个符号的宝石。 Twitter技巧#1 这个方便的解释表将描述Pointer名称后面隐藏的所有“内脏”: Twitter技巧2 使用Core Data / Realm和多个线程时要遵循的“黄金法则”。 这样,数据库维护就不会随着时间的流逝而成为噩梦。 Twitter技巧#3 一个可变阴影的好用例! 您可以使用它来确保引用的是参数值的本地可变副本,而不是原始参数。 Twitter技巧#4 每个旅程都从一个步骤开始。 如果遵循以下3条简单的规则,即使是单元测试的旅程也是可以实现的: Twitter技巧5 在约翰·桑德尔(John Sundell)启发我们之后,您已经开始进行单元测试,对吗? 多亏了Arek,现在您知道⌃⌥⌘U快捷键的行为可能因光标位置而异: Twitter技巧#6 Xcode的能量影响分析器非常强大。 您甚至可以根据OLED功率模式估算对iPhone X的能量影响。 不是纯技巧,而是要知道! Twitter提示#7 最新的Xcode 9进行了不错的改进。现在,您可以在Objective-C项目中使用`@ available`关键字在运行时检查系统版本: Twitter技巧#8 最新的Xcode的另一个绝佳提示。 这是通过删除单个文件来提高UI性能的方法。 Twitter提示#9 使用自动版式时,停止更新动画的约束。 有一个更好的方法: Twitter技巧#10 您是否曾经想过将指纹用作Macbook Pro上的sudo密码? 现在,通过这一行代码,您可以做到这一点。 Twitter技巧#11 字典的alt下标处于最佳状态。 第一个版本更干净,也更快。 Twitter技巧#12 充分利用LLDB的e ( e表示expression )命令的全部潜能,并始终停止使用po命令。 这将大大改善您的调试体验。 Twitter提示#13 LLDB表达式很难处理吗? 使用此命令,您可以查看日志输出并找出问题所在。 Twitter提示#14 […]

Xcode构建阶段和环境

如何教Xcode尊重环境。 如果您曾经做过iOS开发,那么您肯定会使用Xcode Build Phases。 构建阶段可以执行的任务之一就是运行Shell脚本,这是您可能会遇到的一个特殊问题…… 问题在于,在Xcode构建阶段中运行的Shell脚本无法获取用户Shell配置文件。 尝试将以下内容放入您的外壳配置文件中: Shell配置文件中的任何消息都不会显示。 原因是从Xcode构建阶段运行的外壳是非交互式外壳。 它实际上不是错误,而是预期的行为,但这可能会使您感到困惑。 这个例子 举例来说,假设您有一个要在Xcode构建阶段中运行的Ruby脚本。 该脚本恰好使用了2.5.x Ruby语言功能,而这些功能在2.3.x中不可用。 您还使用RVM来安装和使用版本2.5.x。 现在,将ruby –version添加到构建阶段,构建项目并检查输出。 在Mojave OS X上,输出为2.3.7 ,这是系统Ruby版本。 通常在外壳程序配置文件中定义的RVM环境都没有加载到脚本中。 解决此问题的一种方法是使用登录外壳程序。 就像在构建阶段的“ Shell”参数中添加-l一样简单,例如/bin/sh -l 。 但是,它不适用于Bourne shell(sh)。 但随后它将适用于再次使用Bourne的shell(bash),因此您可以将“ Shell”参数更改为/bin/bash -l 。 您现在将在日志中看到以下内容: 加载〜/ .bash_profile 那行得通,但并不理想。 如果团队中有很多开发人员,他们的~/.bash_profile可能会发生各种各样的事情,而您不一定要在Xcode构建阶段中运行它们。 您只需要加载RVM环境,别无其他。 其他开发人员也可以使用zsh或其他类型的shell。 构建阶段脚本 解决此问题的另一种方法是仅在每个构建阶段脚本中提供重要的内容。 例如,要使用RVM在非交互式shell中加载Ruby版本,可以使用以下代码: 尽管此方法可能需要更多工作,但由于以下几个原因,它仍然是更好的方法: 您只加载运行脚本所需的内容,而不加载用户的shell配置文件中的所有内容 根据项目的.ruby-version文件选择Ruby版本,而采用登录Shell方法时,将加载为RVM全局设置的默认Ruby版本,并且您必须运行额外的代码才能切换到正确的版本 提示 有关使用Shell脚本构建阶段的一些技巧。 脚本错误 如果shell脚本返回的错误代码不是0 ,例如/bin/sh -e ,则构建阶段的Add -e标志将失败。 管理构建阶段脚本 […]

Swift中的通用数据源

在我从事的绝大多数iOS应用程序中,表视图和集合视图是最常用的UI组件。 由于设置表视图或集合视图需要很多样板,因此我最近花了一些时间来寻找一种避免一遍又一遍地编写相同代码的好方法。 我的工作重点是尝试通过一组抽象来封装所需的样板。 随着时间的流逝,许多其他开发人员都致力于解决这个问题,并且随着Swift的最新发展,已经开发了许多有趣的方法。 在这篇文章中,我将说明一段时间以来一直在使用的方法,以减少在应用程序中设置集合视图所需的样板。 表格视图与集合视图 “为什么只谈论集合视图而不是表视图?”你们中的一些人可能会问。 在过去的几个月中,我一直在每个实例中使用过集合视图,而以前,我本可以使用表视图。 到目前为止,它一直运行良好! 它帮助我避免了由于使用两个几乎相似但不完全相同的概念而产生的双重性。 我做出此决定的理由如下: 任何表视图始终可以作为具有一列的集合视图实现/重构。 桌面视图在大屏幕(例如iPad)上无法正常工作。 我想指出的是,我不建议您遍历代码库并将所有表视图重新实现为集合视图。 我的建议是,如果需要添加需要显示项目列表的新功能 ,则应考虑使用集合视图而不是表视图。 尤其是在使用通用应用程序的情况下,集合视图可能会通过动态调整布局来简化所有屏幕尺寸的工作。 Swift泛型和有用的抽象搜索 我一直是泛型编程的狂热者,所以可以想象,当Apple在Swift中引入泛型时,我感到非常兴奋。 但是,一段时间以来,泛型和协议无法很好地协同工作。 然后,随着Swift 2.x中相关类型的引入,创建通用协议变得更加容易,许多开发人员开始尝试使用它们。 我将要呈现的抽象开始是使用泛型(特别是泛型协议)的实验。 这样的抽象使我能够封装设置集合视图所需的样板,并将为集合视图创建数据源所需的代码减少为两行代码(用于简单用例)。 我想指出的是,我建立的并不是万灵丹。 我实现的抽象专注于解决一组特定的用例。 对于这些情况,它们在简化设置集合视图所需的代码方面做得相当不错。 对于某些更复杂的用例,可能需要其他代码。 我主要致力于隐藏与集合视图相关的最常见功能。 如果需要,可以封装更多功能,但是对于我的特定用例而言,并不是必需的。 出于这篇文章的目的,我将提供一些抽象,这些抽象涵盖使用集合视图时通常需要的功能。 这应该是一个很好的起点,以说明您可以使用泛型(尤其是泛型协议)构建的内容。 集合视图单元格抽象 我通常在实现集合视图时的第一步是创建要用于显示所需数据的单元格。 处理集合视图中的单元格时始终需要执行以下操作: 出队 配置单元 为了简化上述任务,我创建了两个协议: 可重用单元 可配置单元 让我们看一下上述抽象的细节。 可重用单元 ReusableCell协议要求您定义一个reuseIdentifier ,在使单元出队时将使用它。 在我的应用中,我通常采用以下约定:单元标识符与单元类名称相同。 因此,很容易通过创建协议扩展来使它抽象化,该协议扩展使复用标识符返回具有类名的字符串: 可配置单元 ConfigurableCell协议要求您实现一种方法,该方法将用于使用特定类型的实例来配置单元,该实例被声明为通用类型T : 当需要加载单元格内容时,将使用ConfigurableCell协议。 我将详细介绍它的一些细节。 就目前而言,我只想强调以下几点: ConfigurableCell扩展了ReusableCell 2.使用关联类型( associatedtype […]

iOS 11:DeviceCheck API

快速说明-我将来所有的帖子都将发布在我的专用网站上,并且此出版物不再更新。 谢谢阅读! 每个WWDC,总是会有晦涩的API进入每年的新玩具“单词泡沫”幻灯片,供开发人员使用。 微弱地坐在那里,这是有理由的,苹果公司认为它是有用的补充,只有少数几个会使用,而不会很多。 DeviceCheck适合该帐单,然后再适用。 您可能会认为Cupertino&Friends ™的必要性,他们不得不做出或面对这样一个现实,即工程师会找到另一种方法来处理X或Y,从而导致可耻的目的。 因为开发人员不会像以往那样做任何可疑的事情。 因此,DeviceCheck有点像大多数开发人员出于完全正当的商业原因想要做某事时发生的事情,但是实际上并没有任何好的方法。 这是一个奇怪的小API,这是我们本周讨论的主题。 那么,这是什么? TL; DR仅此而已:这是Apple认可的有保证的方式,可以在保持绝对用户隐私的同时,将您的应用标识为在有效的Apple设备上运行。 我想那不是新闻中最有趣的。 这里真正的讨论在于事物的为什么部分。 在这种情况下,频谱的使用范围可能包括从切换某个设备上的促销优惠,将购买链接到帐户或为欺诈活动审核设备。 例如,会议室中谁在此使用两个不同的用户名或个人资料来扩展某种免费试用? … ….. …….. ♂‍♂️ 就是这样 我们只是在帮助一个人,特别是为任何给定的iOS(或tvOS)设备关联某个给定的状态。 为了使您的创意源源不断,请考虑已发布了两个应用程序。 如果他们打开App One,则可以将设备分配为状态01;当他们打开App Two时,您可以查询状态,因为状态将以相同的方式保留,然后解锁一些内容,折扣或奖励。 它是与应用程序无关的API,因此在场合需要时可以充分利用它。 但是,也请注意,这是否会对您构成设计约束。 再说一次,我们谈论的是每个设备两位,而不是每个应用程序两位。 那么它是怎样工作的? API 我一直很欣赏“直截了当”的API类型,而这正是我们所能获得的。 该设置允许开发人员为每台设备存储两位信息(以及时间戳)。 因此,与其偷窥苹果希望让您闭门识别设备的几扇门,您还可以拿回一点点并完成该操作: 让curDevice = DCDevice.currentif curDevice.isSupported { curDevice.generateToken(completionHandler:{(数据,错误)在 如果让tokenData =数据 { print(“接收到的令牌\(tokenData)”) } 其他 { 打印(“命中错误:\(错误!.localizedDescription)”) } }) } 请注意,模拟器不会通过isSupported,因此,如果您要对其进行测试,我想无论如何都要做我们应该做的事情,并使用真实的东西📱。 有了该代码,您就可以进行以下操作: 00 […]

用Swift 3向iOS应用打个招呼–第1部分

这个故事是关于一个对iOS和Swift不了解的Android开发人员如何开发适用于iPhone的应用程序。 基本上,关于我的故事,由于对Java / Android已有多年的了解,所以希望学习iOS。 iOS和Android之间的概念,设计,编程和生命周期完全不同。 两者在某些方面都赢得了比赛。 首先,我决定使用Swift 3编程语言在iOS中开发我的第一个hello world应用程序。 选择Swift的原因是Objective -C变得过时了,多年来,Swift将成为开发iOS应用程序的官方语言。 此外,如果您了解基于Typscript的JavaScript,那么使用Swift中的几个新概念即可轻松学习Swift。 在高级Swift,Typescript和Android上,Kotlin在语法上相似,并且有许多共同点。 让我们开始吧。 如果您想学习iOS应用开发,则需要Macbook(pro),8 GB RAM(安全)和XCODE 8+。 另外,您需要一个Apple开发人员帐户。 打开XCode,然后创建新项目并立即选择单视图应用程序。 接下来填写基本详细信息项目名称,等等。 创建成功后,IDE将打开,文件浏览器位于左侧。 实用程序面板在右侧,调试面板在底部。 在项目下的文件浏览器中,您会看到几个文件,这些文件是自动创建的,并且内部的骨架代码也是自动创建的。 Main.storyboard-将在此处设计每个屏幕的所有应用程序UI视图。 按钮,文本视图,文本区域等将移至此处。 在这里,您将链接所有UI组件以进行事件处理(我们将在本节的后面部分看到) ViewController.swift —此文件是故事板上您应用程序屏幕的关联文件,每个UI屏幕都可以与Viewcontroller文件关联。 UI组件所有事件处理的代码将在此处处理。 AppDelegate.swift-此swift文件具有适用于所有应用程序UI生命周期状态的处理程序方法。 这意味着AppDelegate的“关注区域”正在处理特殊的UIApplication状态。 有关生命周期的详细信息,请单击此处。 第1步-为您的应用创建UI 第一步是为您的应用创建UI。 对于我们的第一个hello应用程序,我们将具有标签,文本框和按钮。 单击按钮时,应使用文本框的内容更新标签。 简单不是吗。 点击main.storyboard, 从右下角的对象库中拖动标签对象,并将其放在故事板内部的视图中,如下所示。 然后从“实用程序”面板的“属性检查器”选项卡中更改标签值。 3.同样,将“文本框”和“按钮”添加到屏幕。 完成后,屏幕将如下所示。 您可以在实用程序面板的“属性检查器”选项卡中更改标签,颜色,大小和所有其他属性。 接下来是我们链接UI组件以进行事件处理。 我们应用程序的用例是使用标签添加到文本框输入的“ hello”文本来更新标签。 单击窗口右上角的助手编辑器按钮。 该按钮将如下所示。 这将打开故事板内部的viewcontroller.swift文件。 2.要链接UI组件以获取值和处理事件,在Swift和Xcode中,您只需将组件从情节提要板拖放到视图控制器即可。 比在android中要编写许多代码行更容易。 3.单击情节提要中的CTRL +文本输入,然后将其拖放到视图控制器文件中。 4.拖放后,它将打开一个小弹出窗口,您需要在其中选择此链接是从UI组件获取/更新值还是处理事件。 […]

React Native一直很糟糕。

我一直在努力给React Native一个机会,这让我一直很失望。 最近有人对在React Native中使用我们的本机iOS和Android模块之一感兴趣。 这听起来很不错。 我们希望我们的代码尽可能有用。 我对React Native相当熟悉,但是有一段时间没有从头开始创建Native模块。 我着手整理文档。 这是iOS和Android本机模块的React Native文档。 两者都引用了React Native-Native Module Setup。 该文档指出启动本机模块的方式是 因此,官方的React Native文档会创建损坏的代码。 我尝试成为一名优秀的开源公民,所以我出发去寻找react-native-create-library的存储库并提交错误。 该错误已存在。 无法打开生成的iOS工作区#95,它已于2月前打开,截至4/10/2019。 在浏览此问题和其他问题时,我注意到该工具不是由Facebook React Native存储库提供的,而是由单个开发人员提供的。 我还发现了这个问题:这个项目死了吗? #106。 在撰写本文时,react-native-create-library作者尚未对这两个问题发表评论。 我不怪作者没有跟上该工具或没有对问题做出回应。 但是,如果此工具是创建本机模块的官方React Native方式,则应由React Native团队保持最新。 对于一个React Native大小的项目,我希望文档更加正确,而且不会那么明显。