Swift中的设计模式:第二部分-行为设计模式

在该系列的第一篇文章中,我讨论了创意设计模式。 现在,我将描述另一组称为行为设计模式的模式。 行为设计模式处理对象之间的交互方式。 它描述了对象之间如何进行通信,以及如何在不同对象之间破坏任务的步骤,从而提供了更大的灵活性并使得代码更具可测试性。 让我们跳到以下10个行为设计模式: 1.责任链 责任链是一种行为设计模式,可让我们在一系列处理程序之间传递请求,其中每个处理程序都决定处理请求或将请求沿着处理链传递。 有一个名为“ 级别”的枚举将“体育”管理细分为三个级别:州,国家和国际。 首先,让我们创建一个名为Sports的类,它将仅保留当前的体育管理水平。 然后,我们有了称为GameManagement的协议,该协议可以沿处理程序链传递责任。 StateSportsTeam , NationalSportsTeam和InternationalSportsTeam类实现了此协议。 如果运动级别不属于他们的管理层,他们会将责任转移给更高的管理层(或管理人员链)。 在操场上运行代码: 让 stateSportsTeam = StateSportsTeam() 让 nationalSportsTeam = NationalSportsTeam() 让 internationalSportsTeam = InternationalSportsTeam() stateSportsTeam.nextLevelManagement =国家运动队 nationalSportsTeam.nextLevelManagement = internationalSportsTeam let sports1 =体育(级别:Level.international) stateSportsTeam.manage(sports:sports1) let sports2 =体育(级别:国家级) stateSportsTeam.manage(sports:sports2) let sports3 =体育(等级:Level.state)stateSportsTeam.manage(体育:sports3) 输出: 由国际体育管理公司管理 由国家体育总局管理 由国家体育总局管理 2. 命令模式 在命令模式中,将执行命令的类(称为Invoker )与产生命令的类( ConcreteCommand )和知道如何执行该命令的类( Receiver […]

核心数据iOS Swift

2.创建项目后,您将获得“ CoreData.xcdatamodeld”,我们将创建模型实体和其他用途。 3.单击CoreData.xcdatamodeld创建一个实体。 点击“添加实体”按钮创建实体。 4.添加属性 现在,我们有了Entity和attribute,所以让我们开始将数据添加到Core Data中。 #将数据添加到核心数据 func saveData { 卫队让appDelegate = UIApplication.shared.delegate为? AppDelegate else {返回} // 1 让managedContext = appDelegate.persistentContainer.viewContext // 2 让实体= NSEntityDescription.entity(forEntityName:“ YourEntityName”,在:managedContext中)! 让person = NSManagedObject(实体:entity,insertInto:managedContext) // 3 person.setValue(nameValue,forKeyPath:“名称”) person.setValue(ageValue,forKeyPath:“ age”) // 4 做{ 尝试managedContext.save() people.append(人) let alert = UIAlertController(标题:“成功”,消息:“保存成功”,preferredStyle:UIAlertController.Style.alert) alert.addAction(UIAlertAction(title:“ Ok”,样式:UIAlertAction.Style.default,处理程序:nil)) self.present(警告,动画:true,完成:无) }将let错误捕获为NSError { //打印(“无法保存。\(错误),\(错误.userInfo)”)} } #从核心数据中检索数据 func getData(){ var […]

构建旅行照片共享iOS应用

你好! 我想向您展示如何构建相对简单的照片共享应用程序:将您的图像放置在当前位置的地图背景上。 您还可以添加一条短消息和您的姓名,以得到如下所示的图像(这样,您就可以将自己在很棒的假期中所拜访的东西吹嘘给朋友): 要遵循本教程,您需要一台装有xCode的Apple计算机和一个Apple开发者帐户。 创建项目 打开xCode并创建一个名为PicTravel的新项目。 选择“ 单一视图应用程序”模板: 给项目起一个名字,我们选择了PicTravel但是您可以选择其他喜欢的名字。 还要填写项目的组织名称和组织标识符: 最后一步是将新创建的项目保存在Developer文件夹中。 建立介面 在左侧面板中,打开Main.storyboard 。 这是我们构建应用程序界面的地方。 从右侧面板的底部拖动ImageView并将其放置在场景的中心。 调整其大小,使其覆盖所有内容(将其捕捉为出现的蓝线)。 如下图所示,使用约束对话框将ImageView固定到场景边距: 我们将使用它为应用程序的主屏幕放置背景图像。 从此处下载背景图像,然后从左侧面板中打开Assets.xcassets项,单击底部的“ +”按钮,然后添加一个名为Background的新图像集。 将下载的图像拖到“ 1x”占位符上,以得到这样的结果(在本教程中,我们将不使用“ 2x”和“ 3x”占位符,但是如果需要,可以为其添加更大分辨率的图像)。 现在,回到Main.storyboard ,选择ImageView ,然后从Attributes Inspector中选择Background图像,然后将Content Mode设置为Aspect Fill 。 现在是时候将新图像添加到我们的资产中,用于将要添加的“拍照”按钮了。 从此处下载图像,在Assets.xcassets中创建一个名为Button的新图像集,然后将图像拖动到1x占位符中,就像我们之前在背景中所做的那样。 接下来,在Main.storybord ,将一个按钮拖动到场景的中心。 将“ 类型”设置为“ Custom ,清除“ 标题” ,并将“ 背景”设置为我们刚刚创建的“ Button图像。 从“ 大小”检查器中 ,将的按钮设置为,并将高度设置为115 。 为按钮的with和height添加两个新约束(每个115),然后从Alignment Constriants中将按钮在容器中水平和垂直对齐。 现在,我们为用户的名称和消息添加两个文本字段。 如下图所示,将它们放置在下面的约束中。 不要忘记蓝色的指南,这些指南使您更容易放置。 要在两个元素之间创建约束,可以按住Ctrl键并拖动到另一个,然后从出现的弹出窗口中选择所需的约束类型。 对于消息文本字段: […]

使用Firebase Cloud功能实施DeviceCheck

(这不是教程) DeviceCheck是iOS 11引入的,它使开发人员可以检查用户是否处于四个自定义状态之一。 所有状态均由开发人员决定。 引入DeviceCheck是为了允许开发人员在所有开发人员的应用程序中正确识别和分类其用户,而无论用户是否删除了他们的任何应用程序。 有许多用途,但通常与货币化和社交有关。 如果您提供应用内新用户交易并希望确保用户无法删除,重新下载和再次访问该交易,则DeviceCheck是您的解决方案。 如果您提供社交应用程序,并且想要确保违反您条款的用户无法长时间访问您的服务(直到他们获得新手机),DeviceCheck是您的解决方案。 在DeviceCheck之前甚至今天,开发人员将在Apple的视野中实施一般或高度可斥责的识别用户的方法,其中最大的例子是Uber直到2017年左右。 一般的解决方案之一是为每个用户使用唯一的,但不是永久的,有时甚至是不存在的广告标识符。 另外,一些开发人员会将信息存储在钥匙串中,但是一旦删除该应用程序,该信息就会被删除。 高度谴责实际上涉及访问每部电话的唯一IMEI /序列。 DeviceCheck已成为各方的完美答案。 它为开发人员提供了永久性,但确保了隐私,使Apple和用户都感到高兴。 开发人员在实施它时遇到的问题。 DeviceCheck要求与Apple的服务器通信,这意味着您必须拥有一台服务器才能完全实现它。 对于在大型公司以外工作的开发人员,花时间了解实施情况可能没有吸引力。 实际上,实施可以非常简单,并且无服务器。 对于我自己的项目(社交),我之所以坚持不懈,是因为用户的质量对于应用程序的成功是不可商议的。 所需的只是Firebase Cloud Functions,Firebase数据库和Node.js。 实施DeviceCheck所花费的大量时间涉及熟悉JavaScript,请求承诺和Apple的错误代码。 因为不仅在服务器之间,而且在数据库之间都会有很多来回回响,所以逻辑确实不是那么简单。 但是,一旦完成,这无疑会让您感到无比的成就。

知道如何进行单元测试的绝佳过程(您的Swift代码)

我将向您展示一种方法,该方法可以确定应测试的内容以及一些概念,使编写测试时的生活更加轻松。 在我职业生涯的某个时刻,我知道单元测试的重要性,但是我不知道如何测试代码。 许多人都面临着同样的问题。 我们阅读了有关如何开始的文章,但仍然很难将我们学到的东西应用到我们自己的代码中。 通常,我们没有那些仅对两个参数求和并返回结果的函数,我们在许多示例中都可以看到它。 好吧,我遇到了一个过程,这对我来说真的很容易。 我要说的第一件事是,您无需更改体系结构即可开始单元测试。 当某些开发人员听到某种结构可以使代码更具可测试性时,这是一个错误。 然后他们等到转移到这种新的编码方式开始编写测试。 让我们不要那样做! 如果要测试现有代码,则可能需要重构某些部分,但绝对不要更改您的体系结构! 消息是对象在面向对象的世界中彼此交谈的方式。 您希望对象执行方法时将消息传递给该对象。 获取属性值是相同的,并且适用于其他所有条件! 知道要测试什么的过程包含三个简单的步骤 ,并且都涉及消息。 1.确定消息的类型 消息有两种可能的类型:查询和命令。 这可能很明显,但是查询是当您要求某事时,而命令是当您告诉它要某事时。 查询具有返回值,但是在命令没有返回值时却不会更改任何状态,但是会产生一些副作用。 查询 =返回什么,什么也没改变 命令 =不返回任何内容并更改某些内容 2.标识消息的来源 一条消息可能有三个来源:传入,传出和发送给自己。 传入 :当一个对象从外部(另一个对象)接收到消息时。 传出 :当对象向外部发送消息时。 自我发送 :猜猜是什么?! 当对象向自身发送消息时。 3.遵循以下图表: 哦! 多么棒的图表! 对?! 保持这种状态直到对您自然。 第一个例子是采用Equatable。 该函数具有返回值,并且不会更改任何状态。 这是一个查询! 它是公共的,可以由另一个想知道两个Wallet是否相等的对象调用。 进来! 传入查询:声明结果。 传入查询非常简单。 您有一个预期的结果,然后调用该函数并断言它(如果它返回了预期的结果)。 (单词sut代表sut系统。在下面的示例中也将使用它) 第二个例子:在loadView之后,您想确保您的插座正确钩住! 他们在这一点上不应该零。 该函数没有返回值,调用后应设置出口。 因此,它有副作用。 所以,这是一个命令! (副作用是直接公开的,因为出口是sut上的财产 ) 该模块是公共的,可以从外部调用。 […]

Swift解决方案:复合

复合模式涉及集合和单个对象的树层次结构。 在上面的插图中,我们有一个文件夹和mp3的目录。 文件夹仅包含文件数组。 每个文件夹的集合可以包含mp3和其他文件夹的混合。 该插图很好地对应于我们定义的每个部分: 层次结构->目录 收集对象->文件夹 单个对象-> mp3文件 它允许客户以相同的方式对待每个层次结构元素。 层次结构中的所有文件共享一个公共接口,而不管它是文件夹还是mp3。 例如,mp3和文件夹都是可以重命名,移动和复制的文件。 因此,可以合理地期望符合要求实现类文件行为的协议。 重要的一点是,客户可以统一对待小组和单个部分。 在使用每个文件之前,无需经常对其进行类型检查。 这是使元素派生自相同协议或基类的直接结果。 UML 组件 :为集合和单个对象提供公共接口的抽象。 树中的所有元素都必须派生自组件协议或基类。 基元 :以前称为“单个对象”。基元只是树中不包含子级成分的成分。 Composite :以前称为“集合对象”。Composite是包含组件数组的对象。 虽然Composite对象和Primitive对象共享相同的接口,但是Composites包含其他方法来管理其子级。 请注意:有几种方法可以引用我们的具体组件: 我个人更喜欢“复合”和“原始”这两个术语。接下来,让我们进入代码吧! 实作 在我们的示例中,我们将向公司部门分配奖金,最终将其发放给员工。 在这种情况下,部门和员工分别充当我们的组合和基元。 零件 protocol Payee { var name: String { get } var bonusAmount: Double { get } func receive(bonus: Double) } 首先,我们为复合对象和原始对象创建一个Payee协议。 这将是我们统一对待他们的手段。 雇员 class Employee: […]

自定义React Native图标? 是的

2.编辑Info.plist并添加一个名为Fonts的属性,该属性由应用程序提供(如果Xcode无法自动完成/不使用Xcode,则为UIAppFonts),然后键入刚刚添加的文件。 它看起来像这样: 步骤1 在Sketch或Illustrator中创建图标,并将它们另存为svg。 第2步 转到http://fontello.com/并上传您的自定义字体。 您也可以从它们的选择中进行添加,以使它们都保持相同的字体。 第三步 从Fontello下载字体文件并打开它。 复制文件夹(其中的所有内容)并转到您的本地项目。 进入保存资产的目录,并创建一个名为fonts的文件夹,然后将该文件夹粘贴到其中。 我建议将文件重命名为“ fontello”。 接下来,打开Xcode并执行与“基本安装过程”中所述相同的插入过程,但使用新的字体文件。 完成此操作后,返回到项目所在的文本编辑器。 步骤4 创建一个名为“ icon.js”的文件。 创建文件后,添加以下代码。 第5步 然后,在需要图标的组件中,您将可以执行以下操作: 希望这对像我一样挣扎的人有所帮助。 干杯!

重新使用Xcode模拟位置

早在2013年,我写了一篇有关使用Xcode模拟位置的文章。 在2016年,Apple改进了这些工具,以使模拟位置变得更加容易且不易出错。 让我们看一下Apple对开发工具的增强功能以​​及已解决的问题。 GPX文件和Xcode Xcode使用标准化的文件类型来模拟位置。 GPX规范概述了定义路径或地理定位坐标集的许多不同方法。 Xcode仅使用标记,因此,如果找到一个生成基于或的GPX文件的工具,Xcode将无法正确模拟您的位置。 Xcode将像通过一条路线一样通过一系列标签运行,但是它没有提供任何机制来控制航路点列表中每个条目的速度或时间量。 可以在以下示例中找到GPX文件的示例,该文件模拟WWDC与会者朝库比蒂诺的朝圣(我希望他们会游泳): Moscone Cupertino 采购GPX文件 除非您希望将多个航路点串在一起以模拟用户驾驶,否则Xcode可以为您提供模拟位置的大部分方法。 在“ 新建文件”表中,“资源”部分下现在提供了创建GPX文件的选项。 生成的默认GPX文件自动设置为Cupertino。 将lat和lon属性修改为新的静态位置,即可开始使用。 配置项目 配置项目以模拟位置非常简单。 将GPX文件添加到项目后,可以在项目的方案编辑器或Xcode的调试区域中启用位置模拟。 通过导航到菜单栏中的产品->方案->编辑方案,打开项目的方案编辑器。 在方案的“运行”操作中,选择“选项”选项卡。 您应该看到类似以下内容: 另一个选择是在应用程序运行时对其进行调整。 在应用程序运行时,通过导航至菜单栏中的“视图”->“调试区域”->“显示调试区域”,打开“调试区域”(如果尚未打开)。 在“调试跳转栏”中,您将在“调试视图层次结构”按钮旁边看到导航图标。 单击它会显示类似于以下的视图: 最后一种模拟位置的方法仅适用于iOS Simulator。 导航至iOS Simulator菜单栏中的Debug-> Location会弹出一些选项,用于模拟静态位置(Apple或Custom Location)或模拟用户骑自行车,跑步或驾驶。 通过“自定义位置”选项,您可以输入静态的纬度和经度: 移动设备的模拟都在Cupertino区域中,因此,如果您需要模拟其他内容,则可以对多个标签进行拍摄。 最后说明 Apple修复的最大错误是模拟设备上的位置。 仅在调试器运行时模拟位置。 停止调试器会将位置服务的控制权返回给iOS设备上的相应无线电和传感器。

Xcode 7离线视图

当使用情节提要板时,Xcode 7在Interface Builder中引入了许多改进。 情节提要参考 ,改进的Unwind Segues和Segue子类化是有用的工具,将有助于使用情节提要构建和维护复杂的应用程序。 有关这些主题的所有详细信息,可以在WWDC 2015的“故事板的新增功能”部分中找到。 在此会话中强调的一项重要的小功能是能够在任何视图控制器的场景基座中添加“脱机视图”。 如果您需要呈现一个仅在其容器视图控制器显示后才显示的复杂视图,那么您很可能使用了以下两种方法之一: 在单独的xib文件中定义视图并加载它,如下所示: 让myView = NSBundle.mainBundle()。loadNibNamed(“ MyViewNib”,所有者:self,选项:nil).first! 如! UIView self.view.addSubview(myView) 将视图定义为容器视图控制器层次结构的一部分,可能使用alpha = 0或在主视图范围之外,然后响应某些事件而显示视图。 使用单独的xib文件方法,我们必须使用上面的代码以编程方式加载视图。 如果需要将IBAction和IBOutlet直接链接到视图控制器,则可以通过将视图控制器类指定为xib文件的文件所有者来实现。 尽管这可行,但它需要几个配置步骤,如果我们可以在其视图控制器旁边看到该视图,并且能够直接链接IBAction和IBOutlet,那就更好了。 所有这些都可以通过将视图直接添加到IB中的视图控制器的层次结构中来完成,但是最终我们可以将多个视图彼此并排堆叠,并且在视觉上由于它们彼此重叠而变得难以使用。 离线视图通过将所有内容保留在同一画布中,同时清楚地显示视图控制器及其离线视图,从而大大提高了故事板的清晰度: 要将离线视图添加到视图控制器,只需将UIView(或子类)拖到视图控制器场景停靠区中,它将显示在其上方。 同样,可以根据需要添加多个脱机视图并将其链接到视图控制器。 新添加的视图可以通过CTRL +拖动到View Controller的源文件中,作为IBOutlet链接: 显示视图 如果编译并运行该应用程序,即使调试器显示已设置了相应的IBOutlet,也将看到该视图不可见。 这是因为离线视图不会自动添加到视图层次结构中。 为了显示视图,我们需要自己添加它(例如,在@IBAction方法内部): self.view.addSubview(offlineView) 如果再次构建并运行,我们将看到该视图出现在主视图的左上角,并且其大小与在“界面”构建器中指定的宽度和高度匹配。 查看尺寸 以上所有都是很棒的-但是如果我们希望离线视图成为与其超级视图范围相匹配的叠加层,该怎么办? 从Xcode 7.0 beta 3开始,无法告诉IB添加后,脱机视图应扩展到容器视图,因此我们需要以编程方式进行此操作。 幸运的是,我们的朋友自动版式可以为您提供帮助。 我们可以编写一个简单的UIView扩展类,以将所有视图锚点约束到其超级视图边缘。 有关如何完成的信息,请参见本要点。 有了这个扩展,我们的视图可以像这样锚定到超级视图的边缘: self.view.addSubview(offlineView)//这是我们的@IBOutlet offlineView.anchorAllEdgesToSuperview()// UIView扩展方法 警惕的读者会注意到,以编程方式添加约束时,translatesAutoresizingMaskIntoConstraints设置为false。 WWDC 2015的第2部分“自动布局的奥秘”部分对此做了很好的解释。 结论 脱机视图是Interface […]

Flutter vs React Native-您需要知道的。 – openGeeksLab的Dmytro Dvurechenskyi

Flutter vs React Native-您需要知道的。 先进的工具不时需要现代流行的移动应用程序来实现它们。 因此,专业开发商努力满足这一领域的实际市场需求。 最有趣,最有用的创新成为讨论的主题。 React Native跨平台于2015年在GitHub上作为开源发布,结合了Android和iOS本机API。 尽管它具有无可置疑的好处,但是我们可以肯定的是,您一定听说过另一种有趣的,不寻常的编程方法-Flutter,它是Google对标准技术的高级答复。 这个新的用户界面于2017年启动,旨在在创纪录的时间内制作iOS和Android版本上的高质量本机应用程序。 什么是颤振? Flutter是Google对React Native的回应,我敢肯定您一定听说过它。 在Flutter发布之后,各种移动开发社区开始进行比较讨论,其中“ React Native或Flutter”是使用JavaScript开发跨平台移动应用程序的最佳框架。 但是,这很容易。 Flutter允许Google开发人员同时使用完全相同的代码同时为iOS和Android构建应用。 对于Flutter来说,这听起来像是一次巨大的飞跃,但要赶上React Native仍然有很长的路要走。 目前,对React Native开发心存疑虑的开发人员甚至没有认真考虑Flutter。 尽管我相信Flutter可能是移动应用程序的未来。 关于Flutter的5个快速总结: –这是Dart语言。 说什么飞镖? !!! 那是大多数开发人员的反应。 –推荐的带有Flutter插件的IDE是Android Studio或Intellij Idea。 – Flutter具有Dart桥,应用程序较大,但运行速度更快。 与带有Javascript bridge的React Native不同。 – React Native和Flutter共享类似的范例,例如事件处理程序和类扩展。 – Flutter的动画和安装体验分别非常出色和流畅。 大多数人在初次熟悉Flutter时会问的问题是“它像React Native吗?” 为了回答这个问题,我们的开发人员Viktor Gavrilov驾驶Flutter旋转了一下,这是他的发现: 在添加软件包时: 在Flutter中,所有内容都会自动连接。 但是,在React中,某些本机模块是手动连接的。 我们通过内置的“程序包管理器”连接程序包,因此不必像通常那样通过Xcode CocoaPods,React Native链接进行连接,而是通过npm将程序包连接到RN。 我们添加到pubspec.yaml。 该包,我们之前在https://pub.dartlang.org/flutter中找到并执行以下命令: “颤振包得到” […]