Tag: Swift 4

服务器端Swift — MVC(单元测试)

在我的上一篇文章中,我描述了如何根据MVC模式(与ASP.NET MVC类似的构建)构建服务器端Swift应用程序。 但是,这里缺少一件事: 单元测试 。 没有单元测试,我无法想象认真的应用程序。 在本文中,我将介绍如何在Swift(和Per​​fect框架)中向我们的MVC应用程序添加带有单元测试的项目。 首先,我们必须重新构建一些应用程序。 我们无法为可执行应用程序创建单元测试。 这就是为什么我们必须将应用程序分为两部分: 可执行文件 -这部分应包含尽可能少的文件, 库 -该部分应包含整个业务逻辑-这部分我们可以连接到我们的测试库。 划分应用程序后,我们应该有一个如下所示的项目: 来源/ TaskerServerApp / 主Swift TaskerServerLib / 控制器/ * 楷模/* 仓库/ * 扩展名/ * 测验 TaskerServerLibTests / 因此,我们有TaskerServerApp可执行文件,其中仅包含一个文件(引导我们的服务器的主文件)。 我们有TaskerServerLib ,其中包含业务逻辑的主要部分(控制器,模型,存储库等)。 在单独的项目TaskerServerLibTests我们将进行单元测试。 要创建该项目,我们必须为Swift Package Manager准备Package.swift文件。 它看起来应该像这样: 现在我们必须考虑如何创建伪造的实现。 在像C#/ Java这样的语言中,我们可以使用功能强大的模拟框架,例如:Moq,Rhino.Mocks,mockito。 不幸的是,在Swift中,这项任务并不是那么容易。 Swift的反射/自省能力不足,无法在运行时生成动态类(在许多被称为代理的模拟框架中)。 我发现了一些模拟库,例如: SwiftyMocky-我们可以标记协议( //sourcery:AutoMockable ),然后适当的伪造实现将由Sourcery工具生成, Cuckoo —特殊的生成器( CuckooGenerator )和框架,generator负责基于配置文件生成伪造的实现, Mimus —框架,提供我们可以在人工生成的假文件中使用的方法(目前仅支持模拟), Dobby-与Mimus相似,但是在我们的虚假实现中,我们可以使用模拟和存根。 […]

Swift 4 Introduction系列1.6 — Swift数据类型可选

Optionals是一个后缀运算符,可以附加到任何数据类型。 可选项目以问号( ? )表示。 我们使用可选参数来指示变量所分配给的数据类型可以不包含任何值。 我们使用关键字( nil )分配一个没有值的可选内容。 只有声明为可选变量的变量才能分配nil值。 我们在某些情况下声明了可选变量,在这种情况下我们不知道输入源是否包含数据。 可选选项使程序更安全地进行编码。 例如,声明为( Int? )的变量; 告诉系统该变量可能没有任何值。 我们可以测试变量是否有值,如果有值,可以从变量中解包值。 用于指示或声明可选选项的语法如下: ? 例如,要声明一个可选变量,我们执行以下操作: var someOptional1:Int? var someOptional2:String? var someOptional3:Double? var someOptional4:Bool?someOptional1 someOptional2 someOptional3 someOptional4 请注意,在声明可选变量时,我们不需要初始化变量,因为可选变量数据类型变量会自动初始化为无值或nil。 但是, 自动初始化仅适用于变量,不适用于常量。 我们可以使用值设置可选选项,如果程序需要设置为nil,则将它们重置为nil。 例: //从先前的代码继续 someOptional1 = 766 someOptional3 = 7123.98 someOptional4 = falsesomeOptional1 =无 someOptional4 = nilsomeOptional1 someOptional2 someOptional3 someOptional4 请注意,在Objective C中找不到可选参数。尽管我们可以在Objective-C中将对象设置为nil,但在Objective-C中,nil指向空指针,而在Swift中,我们可以将任何数据类型设置为可选参数。 我们还可以同时声明和分配可选内容。 […]

快速登录/注销导航过程

创建Login和Tab Bar VC之后,我们需要将一个Storyboard ID分别添加为“ loginvc”和“ tabbarvc” 登录VC 不使用用户和密码文本字段,并且登录操作将状态设置为true并调用updateRootVC静态函数。 稍后我将解释updateRootVC函数。 个人资料VC 概要文件vc是执行注销操作的位置。 AppDelegate和切换器 最后,AppDelegate在启动时将调用切换程序updateRootVC函数。 Switcher updateRootVC函数是进行分支的地方。 AppDelegate和切换器 完成了! 任何改进/建议都是最欢迎的!

[Swift 4]排名前三的String API新功能

在每个版本中,Apple都使我们越来越爱Swift。 但是,并非总是那样。 就我个人而言,Swift 3感觉是Swift的第一个正式版本,而不是版本1和2。他们感觉更像是该语言的beta发行版。 现在我们得到了Swift 4,它是Swift 3的升级,而不是像以前版本中那样对语言进行全面的改进。 它随新的Xcode 9一起提供。在使用Swift 4之后,我决定专门讲一个故事,重点放在令人兴奋的新String API上 。 关于Swift 4 Swift 4以Swift 3的优势为基础,提供了更高的鲁棒性和稳定性,提供了与Swift 3的源代码兼容性,对标准库进行了改进,并添加了诸如智能键路径和序列化之类的功能,同时缩短了构建时间并减小了尺寸应用程序二进制文件。 为您推荐: 我❤Swift [第1部分] — UIViewController和扩展 字符串API 字符串是Swift中最常用的类之一,因此最终,它得到了很多当之无愧的爱。 新的API包含许多更改,但我将仅关注最佳更改。 3个多行字符串文字会让您忘记在行中添加带有内联\ n的新行 较长的字符串,会使您的字符串显得肮脏且难以阅读。 这是多行字符串文字可能有帮助的众多示例之一。 通过将示例字符串添加到print()中,让我们比较当前和新的字符串多行方法。 迅捷3 print(“ \ n示例:\ n-第一行\ n-第二行\ n-第三行”) 斯威夫特4 print(“”“示例: – 第一行 – 第二行 -第三行“”“) 可能您会发现差异以及新的多行字符串的清洁程度。 为了使用多行字符串文字,您将需要使用“”“确定字符串的基本缩进。 2个集合–字符串再次成为集合。 它是在Swift 1中首先引入的,但在Swift 2中却被删除。现在,该字符串被视为字符的集合,我们可以对它们执行各种操作(迭代,过滤器等)。 直接在String上迭代 let str =“超赞的字符串” […]

应用数据流:第一部分

与商店合作 示范代码 在我们陈述之前,如果您在标题中看到商店,并认为这与商务应用程序有关,那么不幸的是,事实并非如此。 在这种情况下,Store是针对组织用于应用程序的数据的存储和检索的特定方式。 好的,既然我们已经解决了这个问题,那么今天我们将要讨论应用程序数据流。 虽然这个主题听起来可能并不超级有趣,但是从长远来看,很好地处理流经应用程序的信息流将为您节省大量时间。 乱序 在开始构建之前,您多久坐下来勾勒出一个应用程序的大致轮廓? 经常? 一点也不? 如果是定期的,那么有多少时间用于映射数据和应用程序状态,以及有多少时间在计划UI上? 事实是,花时间计划数据的人并不像在UI上那么多。 为什么不呢?有很多很棒的工具,例如Sketch,可以用来计划UI,还有很多博客和其他资源,可以用来学习更多有关计划UI的信息。 计划数据并不是乐趣的一半。 但是,如果您做得正确,花时间去做将为您节省两倍的麻烦。 组织混乱 如果您考虑一下,那么一开始没有太多经验并在iOS中使用MVC作为指导的人可能会以多种方式构造代码。 没有什么限制甚至路标可供他们遵循。 清晰可见的路标通常像救生筏一样被抓住。 这就是为什么这么多的初学者代码最终出现在ViewController中,尤其是viewDidLoad中的原因。 没有太多其他参考,这成为他们的组织原则。 开放的画布 除了基本UI类的实现之外,作为程序员,您几乎没有做出任何决定。 刚开始时,打开的画布通常是挫败感的源头,因为在那个阶段,您真的想知道应该去哪里。 但是,有了这个自由空间,您会感到更加舒适,这为您提供了一个探索的好地方。 MVC 对于此示例,我们将使用接近普通MVC的内容进行处理。 过去,我必须承认,我对iOS使用的标准MVC抱有不必要的苛刻意见。 主要是由于我自己的不耐烦。 只要有一点时间,加上适当的实现,MVC就能很好地工作。 尽管在演示项目中有视图模型,但是代码没有什么特别的花哨,没有RxSwift,也没有协调器。 出于所有目的和目的,它都是原始的MVC,因此tableview单元模型的结构如下: 数据流 在继续之前,我只想澄清一个术语:数据流。 当我指的是应用程序中的数据流时,我指的是如何将数据从源头传递到应用程序以进行显示以及其结构。 它涵盖了从API响应到数据模型乃至数据呈现的所有内容。 就其重要性而言,它并没有获得应有的价值。 我愿意打赌,当我第一次学习网络电话并开始构建更复杂的应用程序时,我经常会遇到很多麻烦,这是因为我并没有真正考虑数据将通过应用程序的方式。 希望它将变得更加清楚演示代码的重要性。 同步器 同步器是一个类绑定协议。 实施后,它将允许您的控制器预订正在更新数据模型的对象。 这样,它就可以采取相应的行动。 在我给出的示例中。 当数据模型添加新项目时,将通过其与Synchronizer的订阅来通知控制器。 然后,它可以同步数据和视图。 同步 同步维护控制器和更新数据的对象之间的连接。 当您认为数据已完成更新时,将发送同步消息。 这可能在API调用或CoreData提取的末尾。 商店 商店协调流程并保存数据。 在基本形式中,它只是定义某些特征的协议。 当您针对特定数据和任务实施它时,它将变得很有用。 物品商店 […]

在iOS中设计实体层次结构:类继承v组成

设计不佳的实体层次结构可能像这座塔一样不稳定。 不灵活的设计可能无法接受新的实体或特征,并且可能导致大量的代码复制和粘贴。 层次结构中更下层的实体可能会导致不必要的行为或意外的实现,并且大量的覆盖可能导致较差的动态调度。 简而言之,正确设计很重要! 设计这种层次结构有两种常用方法: 类继承 和 组合 ,您可能会惊讶地发现一种方法明显优于另一种方法。 在本文中,我们将使用这两种方法设计一个简单的层次结构,以讨论它们的优点和缺点。 让我们开始吧! 方法1:类继承 类继承是在OOP中设计实体层次结构的经典方法,即使是初学者,也将很快熟悉本节中的概念。 作为一点点回顾,让我们提醒自己,继承是一种基本行为,已植入到类中,但未在结构中找到。 出于本文的目的,我们将构建以下层次结构的代码表示形式: 在代码中,它看起来像这样: 在这种情况下,不能将任何功能放在Bird超类中,因为它们都不是所有四个Bird子类都通用的。 相反,我们有不同的组合。 为了使这些功能在需要的地方可用,我们被迫做这样的事情: 即使一眼就能看出这是一个糟糕的解决方案,原因有几个。 首先,有很多重复,将相同的方法实现复制到不同的类中。 试想一下,如果我们需要对这些方法之一进行更改,那么现在我们需要在多个位置进行相同的更改。 接下来,它也打破了单一责任原则。 就Puffin而言,我们在单个类中实现了所有三种方法。 为了代码的可维护性,我们理想地希望看到封装在不同实体中的这些不同职责。 有人可能会争辩说,可以通过一些“创造性”子类来减少复制的数量,但这不可避免地导致了继承杂耍行为,这种行为只会随着新方法的引入而变得更加复杂,或者新类仅需要某些继承的方法而变得更加复杂。 。 我们最终得到了一个非常脆弱的层次结构,在该层次结构中,超类的单个更改可能在继承链的更下方产生无法预测的结果。 除此之外,当我们查看开始的层次结构图时,我们被提醒,我们的理想是将所有鸟子类都置于同一级别,这是用这种方法无法实现的。 那么为什么类继承不能给我们想要的结果呢? 构架此讨论的一种有用方法是考虑“是”与“具有”的关系。 类继承仅限于表示“ is-a”关系:很好地描述了海雀 “ is-a” Bird和Bird “ is-a(n)” Animal 。 但是,当我们尝试表示“具有”关系时,通常会达不到要求。 在这种情况下,我们可以将“具有”表示为一种属性(“具有喙”)或一种方法(“具有飞行能力”)。 我们看到想要添加swim() , walk()和run()的功能未在我们的鸟子类中一致地应用,这并不罕见。 在您脑海中越是用“ is-a”和“ has-a”观察世界,您就越会意识到自然世界并不是那么容易装箱。 方法2:通过协议组成 因此,现在让我们通过合成解决相同的问题。 以下方法由四人帮提出,用一种优雅的方式描述了这种方法: 编程到接口,而不是实现。 在iOS中,我们通过使用协议定义接口。 任何采用协议的实体都必须在合同上遵守所要求的接口,这实质上就是上述短语要求我们执行的操作。 现在,我们的基本设置如下所示: […]

在iOS 11和Swift 4中拖放表格视图单元格

在IOS 11中,UITableView添加了一些专门的API,用于将tableView行从一个tableView拖放到另一个tableView。 对于拖放,我们需要实现委托UITableViewDragDelegate和UITableViewDropDelegate。 UITableView和UICollectionView都具有拖放API(协议)。 对于UICollectionView,可以按照本教程进行操作。 这些代表完全独立,我们可以根据需要使用任何一个代表进行拖放。 两者都适用于拖放。 注意:-请注意, iPhone和iPad均支持拖放功能,在iPad上,不同应用程序,同一应用程序和同一屏幕之间可使用拖放功能,但在iPhone中,仅可在相似屏幕上使用拖放功能。 通过使用CollectionViewDataSource和CollectionViewDelegate方法在同一屏幕上创建带有两个tableView的基础项目。 您可以从此处下载基础项目。 现在,我们开始拖放代理,以将tableView行从FirstTableView移至SecondTableView。 为了回调UITableViewDragDelegate,我们需要在viewDidLoad()方法中设置.dragDelegate 。 覆盖func viewDidLoad(){ super.viewDidLoad() self.topTableView.dragDelegate =自我 } 为了启用拖动吸引力,我们需要设置表格视图的dragInteractionEnabled属性。 在viewDidLoad方法中启用此属性。 此属性的默认值在iPad上为true,在iPhone上为false。 self.topTableView.dragInteractionEnabled = true 在UITableViewDragDelegate中,只有一个必需的方法 itemForBeginning用于支持拖动项。 tableView(_:itemsForBeginning:at 🙂 ->提供项目以开始与给定indexPath相关的拖动。 如果返回一个空数组,则拖动会话将不会开始。 NSItemProvider UIDragItem NSItemProvider- >通过使用此类,您可以创建数据或文件的对象,以便在拖放期间在进程之间传送数据或文件。 UIDragItem- >从一个位置拖动到另一个位置的基础数据项的表示。 扩展ViewController:UITableViewDragDelegate { func tableView(_ tableView:UITableView,itemsForBeginning会话:UIDragSession,在indexPath:IndexPath)-> [UIDragItem] { 让dragItem = self.dragItem(forPhotoAt:indexPath) 返回[dragItem] } ///辅助方法 私人功能dragItem(forPhotoAt indexPath:IndexPath)-> UIDragItem { […]

协调员:复审

驯服无节制的应用程序架构 返回协调员 因此,距离我写上一篇关于协调员的文章已经几个月了。 在此期间,发生了很多事情! 我发布了一个名为PodCatch的新应用程序(我使用协调器概念构建了该应用程序-仍在进行中): chriswebb09 / podcatcher podcatcher –播客应用 github.com 我参加了尝试的活动! 纽约市Swift会议: 在此过程中,我有机会更详细地探讨了这个概念,并找出了对我有用的功能。 背上盘旋 我觉得现在是时候回过头来,完成我关于协调员的系列讨论的好时机。 在我走得太远之前,我想先拥有一件事。 我认为我的第一篇文章不是对该主题的出色介绍。 它缺乏重点,因为我试图将太多概念引入范围更窄的事物中。 除了这篇文章之外,本系列文章很可能是第三部分,因为这篇文章本身并不完整,我对我最初写的内容不满意。 我知道现在回过头来是我在CoreLocation上写的系列以及我希望退出的示例项目中的一个不切实际的话题(下周暂定)。 我现在写这本书是因为我想在尝试有关该主题的对话时记下来! 上周在纽约召开的Swift大会仍然让我记忆犹新。 ¯\ _(ツ)_ /¯ 应用程序控制器/协调器 因此,让我们对第一部分进行一些回顾,如果您已经阅读了该文章,那么这似乎有点多余。 视图控制器的问题之一是,随着应用程序开发的进行,它们可能变得庞大而笨拙。 这是因为它们的目的可以得到广泛的解释。 如果您的大多数应用程序都在视图中工作并且视图控制器“控制”视图,那么将许多应用程序逻辑放在其中似乎是完全合理的。 显然,这种方法存在严重的缺陷。 如果您已经阅读了Soroush Khanlou关于协调员的博客文章,那么这是多余的,如果您还没有,我只是简单地谈谈一些背景信息。 不幸的是,以视图控制器为中心的应用程序开发方法不可扩展。 协调器是将您的代码隔离为易于替换的小块的好方法,并且是解决控制器不适的解决方案的另一部分。 — Khanlou:协调员 协调器模式是一种企业软件设计模式,已适应iOS世界: 您可以通过将所有流逻辑放在应用程序控制器中来删除重复项。 然后,输入控制器向应用程序控制器请求适当的命令,以根据模型和要根据应用程序上下文使用的正确视图来执行该命令。 —马丁·福勒 我喜欢他们在顶部发布的tl; dr,它对协调员要完成的工作的定义很简洁: 处理屏幕导航和应用程序流程的集中点。 出于这篇文章的目的,我想尽可能地强调应用程序的流程和导航。 观察结果 我尝试了一些开发人员! 在纽约召开的Swift大会上,他们对协调员的使用以及与我交谈过的每个人都对他们的职责和限制有不同的解释。 我与之交谈的一些开发人员已经定义了功能,这些功能要求将任何东西标记为诸如start方法之类的协调器。 其他人则使用协调器协议,而无需任何方法来将控制其应用程序体系结构的类绑定在一起。 从我与Soroush的对话中收集到的信息,解释的范围是设计使然的。 那么什么是协调员? 协调器是使一个或多个视图控制器周围的对象。 将所有驱动逻辑从视图控制器中移出,并将这些内容向上移动一层,将会使您的生活变得更加美好。 […]

#48骰子转转乐3.1之你的骰子不是你的骰子

爱因斯坦曾说过:上帝从不掷骰子表明表明他对随机性的看法立场那一定因为是他还来不及认识swift4.2 random新语法的缘故 就在我日夜不眠不休不休加紧赶工之际发现骰子的随机性仿佛有了自我意识一样发展起来了所有的控制……。 不要哇……。 好吧阶层都黏在一起在一起这是失败的3.1版…… 只能是当删除去法用了…… 既然没办法讨论程式码就回应一下开头提到的上帝不掷骰子这件事在写码崩溃的时候不免就上网东看西看一下看会不会刚好随机看到什么资讯可以拯救一下红字错误的结果发现了一个恐惧的真相!!! 肯定了爱因斯坦果然是真知灼见的大科学家有想法,有正见还总是都能一针见血! 以下是防雷线,请小心服用〜 ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** ****** 嗯〜我确认我两只眼睛都清楚明白看到了应该是在玩扑克牌才对。 上帝果真没有在掷骰子! 所以此时此地我在这边打废文一点都不是或然随机发生的一定是有个什么4.0版在等我写出来对吧!对吧!对吧! 拜托你一定要生出来啊! 我愿意赞助上帝10副扑克牌可以吗? 文末顺便推一下爱因斯坦他跟费曼两个人都满有趣的是我大开科学眼界的敲门砖(只是深奥的东西我也读不太懂就是XD) 好啦就让我们忽略爱因斯坦最近被小推翻的那个理论我想如果爱因斯坦也能有超级电脑跟超级望远镜之类的我们现在应该早住火星了好不好 在那个年代的有限资源下能有这样的的前瞻性发现已是十分惊人的了那可是包含包含很多看不见摸不不也理解不了的现象啊啊啊啊何况如果科学发现一被发表就一定无法被推翻的话 那想必后来同领域的学者也会很寂寞的啊连一点往根源研究的动力都没有了啊484〜 有兴趣的人可以找国家地理频道拍的第一季就是爱因斯坦的故事 导演的镜头很强大,整部都是浓浓的欧洲风华跟光影变幻 不论爱因斯坦或是费曼先生从理论面去认识他们对我们一般人是很难下手的但是从生活面去了解观察他们的所行所思也不失为一种向大师致敬的方法啊 听说爱因斯坦的脑子被妥善保存起来如果有一天能向他的脑子膜拜是不是对我的脑子也能有所帮助呢?(并不会!)

字典和元组之间的区别

词典用于存储相同类型的无序值列表。 每个值都与唯一键相关联,该键充当字典中该值的标识符。 让我们创建示例字典 var studentDetails = [String:String]() 它也是一种可变类型,意味着您可以通过添加,删除或更改其项目来进行更改。 studentDetails [“ firstname”] = [“ Roy”] 元组表示单个组件中的值的集合。 在可以返回多种类型的函数时使用。 我们可以使用dot( . )表示法后跟值的索引来访问内部值: var name = [“ Joy”,“ Martin”] var firstname = name.0 var lastname = name.1 它可以是零个或多个类型的组合。 var value = [“ joy”,1,true] 元组上方是(String,Int,Bool)类型。 元组和字典之间的主要区别 元组是逗号分隔的多种类型的列表,字典是键值类型。 元组只能包含预定义数量的值,在字典中没有这种限制。 元组可以包含具有不同数据类型的不同值,而字典一次只能包含单个数据类型的值。 谢谢阅读。 如果您喜欢本文,请确保鼓掌以表示支持。