当在实现通用协议或共享通用基类的类之间进行选择时,将使用工厂方法模式。 这种模式允许实现子类提供专业化,而无需依赖它们的组件知道这些类的任何详细信息以及它们之间的关系 什么是工厂设计模式? 工厂方法模式选择一种实现类来满足调用组件的请求,而无需组件知道有关实现类或它们之间的相互关系的任何信息。 有什么好处? 这种模式巩固了决定选择哪个实现类的逻辑,并防止其在整个应用程序中扩散。 这也意味着调用组件仅依赖于顶层协议或基类,而不需要有关实现类或选择它们的过程的任何知识。 什么时候应该使用这种模式? 当您有几个实现通用协议或从同一基类派生的类时,请使用此模式。 什么时候应该避免这种模式? 在没有通用协议或共享基类的情况下,请勿使用此模式,因为此模式通过使调用组件仅依赖单一类型来起作用 让我们看一下示例: 协议JobContactProtocol { func sendRequestResumeEmail() } struct Contact { 变量名称:字符串 var job:工作 初始化(名称:字符串,工作:职位){ self.name =名称 self.job =工作 } 枚举Job { 案例IOS 案例Android } } IOSJob类:JobContactProtocol { var联系人:联系人 func sendRequestResumeEmail(){ 打印(“亲爱的\(contact.name)您是ios候选人”) } 初始化(联系人:联系人){ self.contact =联系人 } } AndroidJob类:JobContactProtocol { var联系人:联系人 func sendRequestResumeEmail(){ 打印(“亲爱的\(contact.name)您是Android的候选人”) } 初始化(联系人:联系人){ […]
低调…大调 Swift编程语言中的集合将相同类型的元素组合在一起。 Swift集合(数组,集合和字典)以与具有相似兴趣或个性的人一起闲逛并组成小队的方式存储值。 范围(…)是原始班级 Apple将范围定义为“可比较类型上的间隔”,通常是整数(Int)或Double类型。 但是,范围也可以被视为集合-索引的集合。 而且由于Swift集合都具有索引,因此Arrays,Sets和Dictionary Arrays是非常基础级别的索引(又称Ranges)集合: 分数= [88,90,88,93,97]是… 数组 = [0,1,2,3,4]→ 0…4 体育= [“足球”,“篮球”,“橄榄球”,“足球”)是… 设置 = [0,1,2,3]→ 0…3 州= [纽约:纽约州,加利福尼亚州:加利福尼亚州,内华达州:内华达州]是… 字典数组 = [0:1,1:2,2:3]→ 0…2 有两种类型的范围: 范围可以做什么: 范围可以一次更改数组中的多个值: 在上面的示例中,两个项目或值被添加到shoppingList数组中,特别是在索引范围3…4处。 删除“香蕉”和“冰淇淋”,并替换为“奶酪”和“葡萄”。 在这里,Range使更新数组的多个值更有效,因此我们不必通过一次执行shoppingList [index] =“ new item”来一次更改一个索引的值。 如果要删除的项目总数不等于要添加的项目总数,这也可以工作。 范围可以定义条件: 有时,我们可能希望我们的程序仅在“某些”条件为真或假的情况下运行。 对于可以用数值表示的条件,例如游戏中的功率水平,天气应用程序中的温度或车辆的速度,我们可以使用Range设置必要的参数。 在上面的示例中,速度的条件写为布尔语句(> = 0 && <= 90),但是我们可以将其转换或读取为范围从0开始直至90(0…90)的范围。 我们可以根据字符串值创建一个范围: 在上面的示例中,我们通过从较大的字符串(“ OCTOBER”)中隔离出一组值(“ TOBE”:索引0、1、2、3)来创建“字符串之外的值”。 然后,我们为索引范围为1…3的新子字符串定义索引参数。 接下来,将定义一个半开范围值类型(.. <)的subRange,它表示在对String调用subRange时,获取Range的String值,该值从索引1开始,但不包括3(1…2)。 这给出值“ OB”。 […]
从iOS 8开始,我们(iOS开发人员)使用WKWebView替代UIWebView。 即使看起来非常简单(加载HTML并在特殊视图中呈现),webViews在使用它们时也会遇到问题。 在本文中,我想分享一些有关在iOS项目中使用WebView的想法。 问题 乍一看,webView应该不难。 如渲染一些HTML或通过URL加载网页。 但是在iOS中使用WKWebView可能很容易成为一项艰巨的任务。 我试图将我的经验分为四个部分: Cookie管理 终止内容过程 记忆问题 信息清单🙂 饼干 加载页面时,将在webView中加载URLRequest的实例。 WebView通过它的ProcessPool处理它的cookie,您不需要中断它的工作。 要通过WKWebView接收HTTP标头和cookie(cookie是HTTP标头之一),您应该实现WKNavigationDelegate方法 如果您想在特定时间检查webViews cookie,则可以通过Safari Web Inspector(首先在iPhone设置中启用JavaScript调试)进行检查。 HTTPCookieStorage通常与Safari不同步。 如前所述,cookie,缓存和所有此类资源均由webView的WKProcessPool实例处理。 如果您需要在不同的webView之间共享cookie,而不是在其配置中共享相同的进程池。 如果您确实需要注入自己的cookie,则分两个步骤进行。 创建URLRequest实例时,在相应的标题字段中设置Cookie 加载了WKUserScript的页面后,使用javascript“注入”您的cookie 这就是具有这种逻辑的UIViewController的方式 在处理重定向和更改cookie时要小心。 在重定向期间,webView使用其内部cookie状态,而不是您在第一次加载时通过的状态。 例如: 您在URLRequest中设置自定义cookie,然后将其加载到webView中。 WebView接收代码30x(重定向),服务器通过标头设置其cookie。 WebView根据其内部状态构建新的URLRequest。 您的Cookie可能丢失了。 与查尔斯检查 最后,关于cookie,我建议您将cookie逻辑留给webView,如果您需要服务器跟踪应用程序的请求,则可以通过设置自定义用户代理来实现。 通过设置 通过UserDefaults iOS可以确保您每个HTTP请求都具有该用户代理。 终止内容过程 其基础Web内容处理已终止的Web视图。 对您的用户意味着什么? 意思是“死亡白屏”。 您的用户看不到任何内容。 触发“重新加载”方法无效。 WebViews属性URL设置为nil。 您应该跟踪此事件,并尝试恢复您的webView,加载最后一个已知的URL或重新创建webView。 当您使用困难的JS加载页面或上传大量媒体(例如高分辨率图片)时,可能会出现此事件。 记忆问题 WKWebView API并不完美。 如果您使用webView构建复杂的内容,请检查是否存在内存泄漏。 例如,如果要跟踪监听JS代码,则需要将WKScriptMessageHandler添加到WKUserContentController中: 但是内容控制器对他的脚本消息处理程序拥有很强的引用。 […]
今天让我们来谈谈创建应用程序时的常见问题。 应该选择哪种设计模式? 实际上,在构建iOS应用程序时可以使用许多模式:MVC,MVP,MVVM,VIPER等。这些是iOS中最常用的模式,每种模式彼此之间使用不同的方法,但最后哪种方法最好? 这取决于您从事的工作,项目的规模以及构建应用程序所花费的时间。 如果您想了解有关这些模式的更多信息,可以阅读本文:Bohdan Orlov的iOS体系结构模式。 现在让我们讨论两种不同的模式: MVVM :视图模型负责以易于管理和显示对象的方式公开(转换)来自模型的数据对象。 换句话说,这是模型和view / viewController之间的桥梁。 这是避免Massive视图控制器将逻辑移至View模型的一种绝佳方法。 协调者 :协调者或中介者将负责我们的应用程序路由(导航),然后view / viewControllers不需要知道它们在哪里或是否在导航内,它们只需要将导航操作发送到协调员/调解员。 MVVM运行中 首先让我们看一下MVVM的工作原理,以及为什么这对我们非常重要。 这有点容易理解它是如何工作的: view / viewController将事件或任务发送到viewModel viewModel执行任务(在后端中获取内容,执行操作,获取模型等) viewModel通过以下方式通知viewController:KVO,委托,回调,绑定等。 实际上,如今,如果您听到“ MVVM”,则认为是Reactive编程,反之亦然。 尽管可以通过简单的绑定来构建MVVM,但是RxSwift和RxCocoa将允许您获取大部分MVVM。 这样,我们将使用RxSwift来获取一些数据,并使用RxCocoa将数据绑定到视图来制作示例。 首先我们有viewController: 在这里,我们有好处: 分发 —现在,我们的viewController不再关心模型,它只是将事件发送到视图模型,并执行任务,完成后将响应发送回视图控制器,实际上视图控制器不知道什么真正发生在后台,因为现在这不是它的责任:)。 可测试性 – 视图模型对视图一无所知,这使我们可以轻松对其进行测试。 View也可能已经过测试,但是由于它是UIKit依赖的,因此您可能希望跳过它。 可重用性 -由于我们的viewControllers不执行特定任务,因此很容易重用项目中的大量代码和视图以及视图模型。 可扩展性 —现在,由于角色定义明确并且视图控制器并没有像以前使用MVC(大型视图控制器)那样执行很多任务,因此项目易于更改或更新。 是时候到协调员了 我们的应用程序看起来非常好,但是仍然有一个大问题,如果我要转到另一个屏幕,该任务由谁负责,viewController,viewModel,该怎么办? 答案不是全部,我们需要架构中的新元素来处理应用程序路由。 让我们尝试将协调器添加到我们的应用程序中,但首先我们需要了解应用程序应在何处以及如何运行。 好的,它看起来比以前非常相似,但是现在我们有了一个新的组件协调器,它负责处理应用程序路由。 通常,您的项目中有许多协调员,因为您的应用程序中有不同的导航和模块。 您可以将协调器与UITabBarController,UISplitViewController等容器相关联,或与UINavigationController之类的导航相关联,这些是应用程序中最常用的容器和导航。 每次您需要创建其中一个时,就知道需要一个协调器来处理流程:)。 现在是时候编写一些代码并观看协调员的实际行动了。 首先,让我们更改视图控制器以了解用户何时选择行。 这很简单,我们只调用方法modelSelected(Repository.self) ,然后将存储库绑定到视图模型。 现在更新视图模型。 在这里,我们有一些新东西让我们看看: […]
如果您要为移动应用程序构建后端,则必须采取什么步骤来完成它? 我将通过7个步骤总结后端开发: 确定后端和前端职责 编写初始端点并使其正常工作 设计API并记录下来 设计和实现数据库 编写后端测试脚本 使用编程语言实现API 部署 让我们更详细地完成每个步骤。 确定后端和前端职责 对于某些类型的应用程序,后端只是简单值的数据存储。 但是对于更复杂的应用程序,您可能必须在后端而不是前端执行复杂的任务。 在两种情况下,您将在后端执行复杂的任务: 您的数据需要在服务器上进行验证。 例如,用户试图播放音频文件,但是服务器必须通过检查数据库来检查她是否有权播放文件。 您的数据与系统的其他部分(例如数据库)进行交互。 例如,您的应用程序注册了一个必须更新用户数据库的用户,该用户数据库将向用户发送验证电子邮件,还向系统管理员发送电子邮件。 还有其他原因可能会在后端而不是前端上执行操作。 关键是要在开始之前大致弄清楚这一点。 编写初始端点并使其正常工作 在确定后端的职责之后,是时候启动并运行某些东西了。 您可以与客户端连接的实际服务器端点。 使用向后后端技术来实现这个目标。 这意味着为后端和前端应用程序都编写存根函数。 不是完整的API,而是足够使您拥有最少的工作后端。 设计API并记录下来 第三步是设计您的后端API。 关于设计RESTful API的讨论很多,但我认为您不必遵循本书的RESTful原则。 相反,只需清楚地记录每个后端API端点应该做什么。 对于每个端点,请清楚地记录客户端需要提供哪种类型的值,以及后端将返回哪种类型的值。 指定哪些值是必需的,哪些值是可选的。 例如,假设您有一个get_movies端点,该端点根据日期范围返回电影列表。 如果客户端提供了日期范围,则它将返回在该日期范围内创建的电影。 如果未提供日期范围,则使用从当前日期开始的过去一周。 记录这一事实很重要。 这似乎很简单,但是关键是要对其进行记录并保持 文档更新。 设计和实现数据库 现在,您可以从API文档中了解数据的结构以及如何存储它们。 在大多数情况下,请使用MySQL。 遵循良好的数据规范化原则,但要走得足够远 有意义,仅此而已。 编写后端测试脚本 用bash / curl或Python编写一个快速测试脚本,以验证所有后端端点是否正常运行。 使用编程语言实现API 现在是时候使用编程语言来构建API。 我更喜欢使用Python。 (我将在截屏视频中更详细地介绍) 部署后端 您可以使用诸如AWS之类的云服务来部署后端来托管后端,也可以使用专用主机。 这是一个很大的主题,我一定会在另一篇文章中介绍。 […]
根据某些数据,Apple的策略是通过减少代码来过渡到这种新语言,从而简化开发工作,而最终由“ Swift”这个名字来强调。 尽管如此,Objective-C仍然是一种落后了几年的语言,但是Apple提出了向SWIFT驱动的环境迈进的问题。 根据Apple的说法,学习SWIFT比使用Objective-C更容易。 到今天为止,尚未确认任何消息,Apple还没有强迫开发人员将其代码从Objective-C重写为SWIFT。 苹果公司在开发iOS本机应用程序时仅推荐使用Swift。 正如苹果所说,Swift是“没有C的Object-C”。
iOS / macOS开发真的很有趣。 您可以在很多领域获得领域知识! 您可能会学习图形技术,例如Bezier或3D变换。 您需要了解如何使用数据库或设计有效的架构。 此外,您应该能够以嵌入式系统的方式管理内存(特别是对于那些处于伟大的MRC时代的人)。 所有这些使iOS / macOS的开发变得如此多样且充满挑战。 在本文中,我们将学习您可能需要了解的另一件事:持续交付(CD) 。 持续交付是一种软件方法,可帮助您随时可靠地发布产品。 CD通常带有术语持续集成(CI) 。 CI也是一种软件工程技术。 这意味着系统一直在不断将开发人员的工作合并到主线中。 CI和CD不仅对大型团队有用,而且对单人团队也有用。 而且,如果您是一个单人团队的唯一开发人员,那么CD对您可能意味着更多,因为每个应用程序开发人员都不可避免地需要交付。 因此,本文将重点介绍如何为您的应用程序构建CD系统。 幸运的是,所有这些技术也可以在CI系统的构建中采用。 假设我们正在开发一个名为Brewer的iOS应用,那么我们的工作流程将非常简单: 首先,我们发展。 然后,质量检查小组会帮助我们手动测试该应用。 质量检查批准测试版本后,我们发布(提交给AppStore进行审查)我们的应用程序。 在不同阶段,我们有不同的环境。 在开发过程中,我们会在临时环境中构建应用程序,以便每天/每晚进行测试。 质量检查小组进行测试时,我们准备了一个基于生产环境构建的应用程序。 这可能是专门针对质量检查团队的每周构建。 最后,我们使用生产环境提交该应用程序。 这样的最终版本可能根本没有预定义的时间表。 让我们更深入地研究交付部分。 您可能会发现我们在构建测试应用程序方面有很多重复的工作。 CD系统可以为您提供帮助。 具体来说,我们的CD系统需要: 在不同的环境(阶段/生产)中构建应用程序。 根据我们选择的环境对代码进行签名。 导出应用程序并将其发送到分发平台(例如Crashlytics和TestFlight)。 根据特定的时间表构建应用。 大纲 这是我们在本文中要做的: 设置项目 :如何设置项目以支持不同环境之间的切换。 手动签名代码 :如何手动处理证书和配置文件。 独立环境 :如何使用Bundler隔离系统环境。 使用fastlane进行构建🚀 :如何使用fastlane生成和导出应用程序。 Jenkins将是您今晚的服务器 :Jenkins如何帮助您安排任务。 在开始之前,您可能需要检查一下: 什么是快车道 詹金斯是什么 什么是代码签名 […]
有时,您需要为应用程序的UI添加自动测试。 有几种不同的方法可以实现此目的。 在测试中,您可以获取屏幕的元素并断言所有帧是否都符合您的期望。 根据要测试的UI,这可能需要很多工作。 或者,您可以使用Xcode提供的UI测试。 但是这些操作非常慢,以我的经验,有时它们只是停止工作。 有更好的选择。 Facebook有一个名为FBSnapshotTestCase的开源组件。 此类允许您创建快照测试。 快照测试将视图的UI与快照的外观进行比较。 让我们看看它是如何工作的。 我要测试的UI如下所示: 有两个带有标签,按钮和两个文本字段的堆栈视图。 使用迦太基安装FBSnapshotTestCase 我是迦太基人。 因此,我将向您展示如何使用迦太基在测试目标中安装FBSnapshotTestCase并使用它为简单的登录屏幕添加快照测试。 创建一个如下所示的Cartfile: github“ facebook / ios-snapshot-test-case” 然后要求Carthage使用以下命令创建动态框架 迦太基更新-平台iOS 迦太基将从github上获取源代码并构建框架。 迦太基完成后,将框架从迦太基/ Bild / iOS文件夹中拖动到测试目标的链接二进制文件与库构建阶段: 接下来,向测试目标添加一个新的运行脚本构建阶段。 输入命令 / usr / local / bin / carthage复制框架 并添加输入文件$(SRCROOT)/Carthage/Build/iOS/FBSnapshotTestCase.framework 。 在Xcode中,它应如下所示: 配置FBSnapshotTestCase 接下来,您需要配置放置快照的目录。 每当快照测试失败时,您还可以告诉FBSnapshotTestCase创建差异映像。 这意味着,当测试失败时,将创建一个图像,该图像显示预期的UI和使测试失败的UI之间的差异。 这样,您可以找出UI中发生了什么变化。 打开您使用测试的方案,并添加以下环境变量: FB_REFERENCE_IMAGE_DIR:$(SOURCE_ROOT)/ $(PROJECT_NAME)测试/失败差异 FB_REFERENCE_IMAGE_DIR:$(SOURCE_ROOT)/ $(PROJECT_NAME)测试 在Xcode中,它看起来像这样: 创建快照 要创建快照测试,请将FBSnapshotTestCase的子类添加到测试目标并添加以下导入语句: 导入FBSnapshotTestCase […]
如果您想要更深入的解释,请跳至注释部分👇🏻,在其中我将详细分析脚本的每个组件。 总而言之,我想说,根据您想做的事情以及使用正确的工具,Swift当然是脚本编写的非常可行的选择之一! 有关信号量的注释 如果您想知道上面的脚本中为什么有DispatchSemaphore ,那是因为任何Swift脚本只要其控制流到达末尾就退出。 如果必须处理异步性(例如,由于加载了网页,就我而言),则需要使脚本保持生命的东西。 无耻的插件:如果想了解更多有关信号量的信息,请确保在此处阅读我的上一篇文章。 脚本和Xcode游乐场 如果您的脚本允许,我建议您在脚本开发过程中使用Xcode Playgrounds: 这样,无需在终端和代码编辑器之间进行切换就可以更快地进行测试。 准备就绪后,您可以快速将其变成真实的脚本。 代码段 对于这篇文章,我做了一个小仓库, Selenops🕷 (一只飞翔的蜘蛛,是的! 😱),在GitHub上: 在其中,您会找到与Xcode Playground,Marathon脚本和标准“ Command Line Tool ”脚本完全相同的脚本。 祝脚本编写愉快!
Xamarin Forms的最佳MVVM框架:)…老实说,不要相信我,相信这个人 我无法在一个博客文章中涵盖PRISM必须提供的所有内容,因此,我将集中介绍我最喜欢的功能之一: 导航! 。 导航 这就是在不使用MVVM框架的情况下处理移动应用程序中导航的感觉 这就是在PRISM中使用导航服务时的感受 它是如何工作的? 首先,您必须在使用的DI容器中注册所有页面 注意RegisterTypes()方法。 现在,如果您拥抱MVVM,您将同意在ViewModel中进行导航。 我们通过在构造函数中注入INavigationService来实现。 然后,我们可以使用_navigationService.NavigateAsync(“ PageNameHere”)将页面加载到导航堆栈中,或使用_navigationService.GoBackAsync()从堆栈中弹出页面。 就如此容易! 参数呢? 很高兴你问 为此,我们具有NavigationParameters对象,可以使用它传递参数,但请注意不要发送太多信息。 现在,我们如何在另一端接收参数? 简单,使用使用相同的NavigationParameters对象: InavigatedAware 我们如何知道何时将ViewModel导航到,或者您将要从视图模型导航? 这是INavigatedAware发挥作用的地方 通过实现此接口,我们可以使用3种新方法 OnNavigatedFrom 在此我们可以导航到下一页之前进行自我注入。 OnNavigatedTo 当另一个页面导航到我们时,将执行此方法。 在将ViewModel推入堆栈后调用此方法。 OnNavigatingTo 最后(这是PRISM 6.3中的新增功能),它与OnNavigatedTo之间的区别在于,这是在将ViewModel推入堆栈之前调用的。