您刚刚发布了最新功能,一切进行得很好,除了要求已更改。 在您的用户界面中,需要将tableview中的所有cityName实例替换为countryName. 如果您使用的端点具有这种灵活性,该怎么办? 如果该端点允许您呈现动态,灵活且受控的服务器端视图,该怎么办? 如果此视图使您可以显示各种类型的对象或更改当前对象的值而不发布新版本的应用程序该怎么办? 好吧,坚持。 这篇文章将向您介绍一种设计模式,以帮助您完成上述所有工作。 灵活性的需求 与移动应用程序相比,在网络上部署更改要快得多,因为没有其他应用程序需要提交和审批。 即使这样,减少部署数量同时仍然能够在移动和Web客户端上进行更改将被认为是成功的选择。 这可以通过提前使端点,数据协定和UI更加抽象的努力来实现。 这种抽象将为您的UI提供更大的灵活性,并让您控制服务器端的业务逻辑,从而可以帮助减少进行这些更改所需的部署。 上面列出的场景并不少见,但是还有其他一些优势可能有助于我们朝着这种设计模式迈进。 这些功能包括: 从服务器更新/重新排列UI元素 运行各种A / B测试版本 避免在App Store审核过程中增加额外的发布时间 将业务逻辑移至服务器并具有单个控制点进行更改 典型到灵活 现在您已经确信了,让我们开始做生意,看看如何实现这一目标。 让我们以一个基本的旅行应用程序为例,该应用程序会根据您的位置向您显示飞往目的地的费用。 此视图的JSON是什么样的? 通常,数据库中会有一个destination表,该表将在端点中传递。 它可能看起来像以下内容: { “目的地”:[{ “ id”:“ 1234567890”, “ city”:“ Los Angeles”, “ state”:“ CA”, “国家”:“美国”, “ background”:“ http://www.example.com/losAngeles.jpg”, “ airportCode”:“ LAX”, “ lat”:“ 165.0987654”, “ lon”:“ 45.3456788”, “ flightPrice”:“ 180” […]
如果我们想学习一种编程语言,我们需要忍受它。 这意味着尽可能多地使用Swift。 今天,我们将开始讨论Swift中的设计模式。 除了简单的解释之外,我们还尝试提供图形,样本,用例等。让我们开始吧。 第一种模式是简单工厂。 简单地说,我们建立了一个工厂来生产属于同一类型的不同对象。 如下图和代码所示,我们有不同类型的汽车,轿车,SUV和面包车。 它们都符合协议Car。 这意味着该协议定义了汽车的通用接口。 特定的汽车类型会实现自己的逻辑。 class Factory { static func produceCar (type: CarType ) -> Car { switch type { case . sedan: return Sedan () case .SUV : return SUV () } } } let sedan = Factory.produceCar (type: . sedan) sedan .drive () let suv = Factory.produceCar (type: […]
您是否曾经想过,当您开车开车时,导航系统如何根据基于输入数据的变化(例如交通拥堵和错位)校正从当前位置到目的地的最佳路线? 这是最小生成树(MST)问题的实时实际应用之一,其中像Kruskal算法那样的算法试图解决该问题。 在本文中,我们将学习Kruskal算法中使用的主要数据结构,以便有效地解决MST问题。 在本文中,我们将快速完成: 介绍 怎么运行的 用C ++实现 在Swift中实现 结论 资源资源 介绍 想象一下有一个图,就像下面的图片一样。 您被要求非常快速地进行两个查询: 1. unionSets,即将两个集合合并在一起。 2. isSameSet,即查找两个节点是否在同一集合中。 Disjoint-set数据结构使我们可以非常快速地确定两个项目是否在同一集合中(或等效地确定两个顶点是否在同一连接的组件中),并且还可以非常快速地将两个集合联合(或等效地组合两个连接的组件)成为一个连接的组件)。 联合查找算法是一种对此类数据结构执行两个有用操作的算法: 查找:确定特定元素位于哪个子集中。这可用于确定两个元素是否在同一子集中。 联合:将两个子集合并为一个子集。 联合查找算法可用于检查无向图是否包含循环。 此方法假定该图不包含任何自循环。 我们可以跟踪一维数组中的子集。 怎么运行的 在下图中,让我们找出在此图是否有周期的情况下购买此联合查找算法。 对于此图中的每个边缘,请使用边缘的两个顶点制作子集。 如果两个顶点都在同一子集中,则会找到一个循环。 然后创建一个父数组并将其memset为-1(即,将-1作为所有数组的初始值)。 然后一一处理所有这些边缘。 0 1 2->节点。 -1 -1 -1->父数组。 边缘0–1:查找顶点0和1所在的子集。 由于它们位于不同的子集中,因此我们将它们合并。 要采用并集,请将节点0设为节点1的父级,反之亦然。 0 1 2->节点。 1 -1 -1->节点编号1是节点0的父节点。 我们将动态创建父数组和sz数组,我们还将需要一个私有方法来获取当前节点的父节点,最后,在私有成员部分中,我们将需要一个swap方法。 在公共成员部分,我们需要一个构造器 ,该构造器将使用图的大小,并用unionSets方法将两个集合合并在一起,使用isSameSet方法来找出两个节点是否位于同一集合中,最后当然,我们需要一个析构函数。 在实现这些方法时,从find_parent()开始 。 这里的想法是将节点的父级保存在父级数组中,因此,当您需要此信息时,它将以摊销的O(1)复杂度而不是O(n)的形式提供给您信息。 在same_set()中 方法,我们将只比较两个节点的父节点。 如果它们匹配,则它们在同一组中。 […]
。이커스프로젝트정정해서합니다합니다。 는이커스는iOS앱을실습하는로젝트입니다。 Xcode 9,iOS 11,Swift 4版本。 시작해볼까요? 您好,AppMakers! 아닌이커스프로젝트의아닌이아닌 ‘만들기’ 이지만,앱을로어쨌든합니다합니다。 는리고로그래밍을때, 您好,World 앱을보도록다。 를,Xcode실행합니다! (Xcode的있지면다면, Xcode的Xcode 를다。) Xcode的iOS发行版。 능한그래밍능한능한능한와스스스스스스스스스그램입니그램입니그램입니 그램 입니그램입니그램입니그램입니그램입니그램입니그램입니그램입니그램입니그램입니그램입니 그램 입니그램입니그램입니그램 입니 그램입니。 iOS 创建一个新的Xcode项目 。 Xcode플랫폼플랫폼 iOS iOS(iOS,watchOS,macOS,跨平台) 템플릿이나타납니다。 iOS만들려면iOS플랫폼에서 Single View应用程序 됩니다。 。지템플릿은다시보만들어다。 에지막으로위의이나오면이름을产品名称에,语言는Swift선택합니다。 组织名称,组织名称组织名称(组织名称)组织名称。 톺아보기 AppDelegate.swift Life리)이고,고기 (生命周期) 관리할다。 active이때,active이활성 (活动) 될가때,background이생명주 (背景) ,생명주이생명주기생명주기가다가다。 ViewController.swift Single View应用程序。 生命周期(生命周期) 있습니다할다。 […]
注意:这是“如何从头开始创建iTunes Samples Player? (第2部分)”。 本文分为两个部分: 在ProgressView和标签文本中显示下载进度。 实现暂停,恢复和取消下载。 上一篇文章的最后一步是添加URLSession的委托方法。 URLSession中还有另一个委托方法,可提供进度的确切状态。 我们可以利用此委托获取当前的进度信息,并在TrackCell中使用新方法,更新标签和进度视图。 TrackCell中进行了一些更改。 删除了隐藏进度标签和progressView的行。 将进度视图的进度值设置为零。 下载完成后,我们将隐藏进度视图。 另外,在Main.storyboard中,删除进度标签上的默认文本“ Label”。 请注意,在底部添加了新方法updateDisplay。 生成,运行并点击下载。 在下载过程中和下载之后,您应该看到以下屏幕。 到此完成第1节 。 解决方案 :URLSession支持暂停/恢复和取消。 我们已经在单元格上隐藏了按钮。 当用户点击它们时,某些委托方法应触发。 这些方法应由SearchViewcontroller处理。 暂停,恢复或取消之类的操作应直接应用于活动下载。 为了进行这些更改,我们需要在TrackCell上声明三个新的委托方法。 然后,我们需要将按钮操作连接到IBAction方法,该方法将依次调用委托,在这种情况下为SearchViewController。 我们还在单元格行上进行了一些UI调整,以便与下载相关的控件仅在活动下载时出现。 完成的课程如下所示: 我们已经更改了Configure方法TrackCell的签名,以便传递活动的下载对象。 更改“ SearchViewController + TableViewDelegate”内部的方法调用以通过活动下载。 cell.configure(跟踪:跟踪,下载:跟踪。下载,下载:downloadService.activeDownloads [track.previewURL]) 生成,运行,搜索,下载,暂停,恢复,取消。 该版本的源代码在GitHub中可用。 希望您能够成功看到具有预期功能的上述屏幕。 这标志着我们为本文设定的所有目标的完成。 学习愉快!
我最近决定开始在Instagram上发布我的Swift编程语言经验。 该平台似乎只限于异国风情的度假照片和猫照片,但我相信它也可以用于承载惊人的视觉代码和构建应用程序的过程。 这里的挑战实际上是将好的代码和想法与呈现它们的美学方法结合在一起。 我的第一篇文章与情节提要有关,这是Xcode的可视化界面,用于构建具有漂亮的拖放功能的应用程序UI。 如果你问我的话,相当合适。 事不宜迟,请查看嵌入的帖子,如果喜欢的话可以给它一些爱,并在末尾查看完整的代码! 原始Storyboardable Instagram帖子 分镜脚本代码
通常,我们需要对带有副作用的代码进行单元测试,这些副作用通过抽象与Swift中的协议与系统的其他部分进行交互。 有很多方法可以验证它是否按预期工作:打桩,监视,伪造等。总的来说,工程师将这些形式称为模拟 ,即使“ test double”也是合法名称。 仅供参考,“测试双倍”的名称来自电影行业中的“特技双倍”。 在Swift中编写测试双打(例如存根或模拟)是一个无聊的过程,开发人员经常尝试使用Sourcery / SwiftyMocky之类的工具自动生成它。 但是,如果您希望进行更精细的控制,或者不想在构建过程中引入新的步骤,则可以使用一个技巧来快速(至少更快)实现双重测试。 如果您知道存根和模拟的工作原理,则可以轻松地跳过以下两章,跳至下一章或直接跳至解决方案。 首先,让我们区分存根和模拟之间的区别是什么,因为它们非常相似。 根本区别在于验证过程: 对于存根,测试用例必须手动调用一些方法以验证是否发生了预期的副作用 模拟使用预定义的配置自动进行验证 让我们用伪swift代码进行比较: 与CounterStub相反, CounterMock是在初始化期间进行预配置的,在CounterStub中,在验证步骤中,我们需要将一些addCalledTimes属性与3进行显式比较。实现这两个测试对addCalledTimes的方式是实现细节。 一般的经验法则是, 验证可以区分我们是使用存根还是模拟(或混合混合)。 让我们先不进行理论讨论,然后再回到地面。 存根实际上如何在Swift中实现? 我们想要创建一个符合协议的对象,并有机会1)验证是否已使用期望的参数调用了给定的函数,以及2)控制函数返回了值。 有许多方法可以做到这一点,最简单的方法就是引入想要跟踪到存根中的行为一样多的属性。 例如,如果要在给定的时间调用该函数,请添加一个计数器,在函数中对其进行递增,然后在测试后验证其值-如上面的代码段所示。 但是,一种替代方法是添加一个附加变量,该变量提供一个函数占位符 (具有与该函数几乎相同的签名类型),并在遵守协议时调用它。 我写这本书几乎是因为如果测试用例完全希望忽略给定的功能,我们将其设为可选只是为了方便。 在此博客文章中,我们将讨论协议功能,因为变量相对于存根而言相对简单-仅通过引入实例即可。 为了这篇文章的缘故,让我们考虑一下最简单的协议,该协议将用户名同步保存到数据库中,并返回一个布尔值来通知过程是否成功。 它的模拟看起来像这样: 对于函数addUser ,我们引入了一个变量addUserAction -每次调用addUser时addUser对其求值的函数。 然后,在测试场景中,您可以1)验证被测系统(测试代码)确实调用了该函数,并且2)模拟数据库的响应方式(无论返回true还是false ): 一般而言,通过引入与函数参数和返回类型匹配的addUserAction变量,我们让测试用例定义协议相关函数的主体。 顺便说一句,如果您不喜欢addUserAction属性的可选性,则可以继续执行等效的实现: 在上面显示的存根中,我们必须显式提供一种addUserAction变量。 对于短函数来说,这似乎是一件容易的事,但对于涉及多个参数,闭包, (re)throws , @autoclosure ,最终可能会导致您和编译器之间的较量。 为了克服这种麻烦,我们可以利用Swift的类型推断系统。 解决方案涉及一个全局函数,该函数返回与参数类型相同的nil值: 起初,它看起来像一个胡说八道的函数,但我们只会用它来拉出T类型,而不是它的值。 函数是Swift中的一等公民,因此我们可以将函数作为参数传递给asNil以获取Wrapped类型与函数类型匹配的nil实例。 在下面的示例中,我们将变量addUserAction初始化为与协议功能相同类型的nil值。 那正是我们以前必须手动写下的内容: 需要将此变量标记为 lazy 因为引用 addUser 隐式依赖于 […]
在本教程的第一部分中,我简要回顾了初始需求和最新技术趋势。 在这一部分中,我将首先回顾两个现成的iOS开发课程,然后再为您提供有用的资源列表,以与流行的库,框架以及开发人员广泛使用的其他一些资源取得联系。 如果您选择只参加现成的课程,请确保在学习结束时查看我的列表,以了解您可能会错过的一些主题。 Raywenderlich.com 正如我在第一部分中所述,Ray的网站对于初学者来说是一个时尚的地方。 当我是iOS开发人员时,我使用此网站来学习使用新的框架和新的iOS功能。 这些教程对于初学者来说非常容易,而且非常简单。 但是,它具有一些体系结构上的反模式,例如在AppDelegate中编写大量代码打破了单一职责原则。 优点: 许多教程几乎涵盖了您需要的每个主题 每天或两天有新文章 准备学习路径 非常详细的教程 对于初学者 缺点: 大多数视频没有转录功能,因此您必须完整观看 一些视频教程的内容太小了 广泛使用建筑反模式 付费订阅(每月$ 19.99 /年度方案$ 179.88) 因此,raywenderlich.com对于初学者甚至是探索新技术的初级/中级开发人员都是一个很好的来源。 但是,还有许多其他方式可以开始。 Paul Hegarty用Swift开发iOS 11应用 Paul Hegarty在斯坦福大学工作。 随着2014年第一版Swift的推出,他开始了本课程的开发。 斯坦福大学是世界计算机科学领域最顶尖的大学之一,因此具有很高的水准。 最新版本涵盖iOS 11和Swift4。尽管现在是iOS 12倍,但由于这些版本之间的微不足道的更改,您仍然可以使用它。 而且,Swift 5仍将在2019年某个地方发布。 优点: 自由 由世界一流大学提供 涵盖了iOS开发中几乎所有重要主题,包括体系结构 非常专注和直接 缺点: 适合熟悉编程的人 比雷的难一点 没有文字转录 我选择斯坦福大学作为研究的起点。 它是免费的,已被许多学生认可,并由世界顶尖的大学之一提供。 苹果软件工程高级副总裁克雷格·费德里希(Craig Federighi)也推荐了此方法。 您可以在这里找到iTunes U播客。 有用的资源 此有用的资源列表无意于替代上面的专业课程或与之竞争。 相反,我将专注于实际应用程序开发,并向您介绍流行的技术,框架和库。 开发语言 […]
僵尸! 是! 谁说僵尸不是真实的,如果您是iOS开发人员,您会非常了解它们。 没有? 别担心,让我们来探索一下。 在某个时间点,我们在不知不觉中或有意将它们植入我们的代码中,而更糟糕的情况是我们想要杀死它们。 僵尸不过是一半死亡,一半释放或保留的物体。 在本文中,我们不仅会跟踪它们,而且会以一种更简化的方式进行处理。 您是否曾经在跟踪已释放对象时遇到麻烦? 您是否曾经遇到过崩溃,内容是“发送到已释放实例的消息”? 真正!!! 然后,本文适合您,让我们开始吧。 有时,二进制语言会给我们带来沉重打击。 您能从这个“ 0x10010d681 ”中猜出类名吗? 也许不是。 假设这是一个已释放的对象,现在难度级别将更加困难。 尽管Xcode为我们提供了一个很好的工具来理解和跟踪“ Instruments” 。 在拥有大量分析模板的地方,Instruments是一个很好的工具。 从“ 分配 ”到“ 泄漏 ”再到“ 僵尸 ”。 但是今天,我们将不再探索Instrument,而是采用一种更为简单的方式来追踪僵尸对象的内存历史记录。 知道答案总是更好,无论答案是什么 因此,首先我们将编辑项目的方案: 在“诊断”下,我们有各种“内存管理”选项。 选择“僵尸对象”,然后为“日志记录”选择“ Malloc堆栈”。 就是这样,我们已经准备好运行该项目。 现在,当我们遇到可能由僵尸实例引起的崩溃时,这就是我们要通过在xcode的控制台中输入以下命令来调试它的方法: a)(lldb)命令脚本导入lldb.macosx.heap 这将产生类似于以下结果:
Swift中的本地收据验证似乎没有被广泛介绍。 我已经能够找到分散在Internet上的代码片段,但是没有什么可以将所有内容集中到一起,因此我可以全神贯注于整个过程。 我一直在研究一些代码,这是我从头到尾将所有内容组合在一起的尝试。 我编写了7篇指南,从入门到测试收据验证,一直到处理收据验证过程的结果以启用/禁用您的应用程序功能。 此外,我已将所有代码放入新的GitHub存储库中,供您使用和学习! 只需要代码? 干得好! andrewcbancroft / SwiftyLocalReceiptValidator SwiftyLocalReceiptValidator – Swift中用于iOS的本地收据验证逻辑的实现 github.com 如果您有兴趣了解整个过程中的每个步骤,那么以下是我针对Swift中的本地收据验证主题编写的七本指南: 准备针对iOS的测试收据验证 适用于iOS和Swift的OpenSSL简单方法 使用Swift加载收据进行验证 使用Swift提取PKCS7容器进行收据验证 收据验证—在Swift中验证收据签名 收据验证-使用Swift分析和解码收据 在Swift中完成收据验证-计算GUID哈希 防止软件盗版很难。 这些指南中提供的代码以及在Git存储库中共享的代码并不旨在保护您免受未经授权使用您的应用程序或其功能的侵害。 这些指南和代码旨在用于学习目的,并且可能是您自己实施本地收据验证的起点。 如果您在应用中按原样使用此代码,则后果自负。 您必须付出额外的努力来混淆此处提供的代码,以阻止攻击者绕过该存储库中包含的收据验证逻辑的尝试。 最初于 2017年8月1日 发布在 www.andrewcbancroft.com 上。 安德鲁·班克罗夫特(Andrew Bancroft)是Pluralsight上多个与iOS / Swift相关的课程的作者。 他定期在www.andrewcbancroft.com和www.dataday.life上撰写博客,热衷于学习和发现,并喜欢与他人分享新见解。 安德鲁(Andrew)用@andrewcbancroft推特介绍了软件开发和数据科学。