通过查看此架构,我们看到协调器需要实例化,添加和删除其他协调器,实例化控制器,并知道如何在应用程序中导航。 没有一种方法可以实现这种逻辑。 如您所见,我的方法依赖于Andrey Panov的方法。 为了实例化协调器,我们使用CoordinatorFactory。 在BaseCoordinator中,我们具有添加和删除协调器的逻辑。 ChildCoordinators数组存储活动的协调器。 我们需要对它们有充分的参考,否则,它们将从内存中删除。 查看应用架构。 如果用户使用Profile VC,则Profile协调器位于Main协调器的childCoordinators变量中。 同时,主协调器位于应用程序协调器的childCoordinators变量中。 如果我们从Profile VC导航回A VC,则Main协调器将从childCoordinators数组中删除Profile协调器,我们将不再有强大的参考资料。 为了实例化视图控制器,我们使用ViewControllerFactory。 这个课很简单。 我们使用工厂模式来创建控制器。 对于路由,我们使用一个Router对象。 它具有对导航控制器的引用,因此路由器可以为我们显示,推动,关闭和弹出控制器。 它还支持自定义过渡。 现在,我们的协调器对象具有所需的所有条件,让我们尝试使用它。 实施协调员 在AppDelegate中,我们将初始化Application协调器并设置根视图控制器。 应用程序协调器将决定我们应该使用LaunchInstructor对象来进行认证还是主流。 因为这只是概念证明,所以我们不会实现它。 但是,其想法是LaunchInstructor应该检查auth令牌是否可用,如果可用,则注册完成。 启动应用程序时,我们可以登录或注册。 完成后,登录过程Application协调器将删除Auth并启动Main协调器。 到目前为止我们得到了什么? 控制器中的代码更少,因为导航逻辑已失效。 控制器不了解其他控制器。 可重用性 正如您在模式中看到的,我们在两个地方都有更改密码协调器。 如果要重用任何流,则需要创建一个选定协调器的新实例,一切准备就绪。 流量变化 产品经理来找你多少次,说一个小小的改变。 我们只需要添加演练和深层链接。 如果问我太多次。 幸运的是,现在这种过渡将不再那么痛苦。 如果要添加演练,则需要创建一个新的协调器并更改LaunchInstructor对象。 我们不需要更改应用程序委托或任何视图控制器中的任何内容。 向项目添加深层链接和推送通知可能非常痛苦。 但是,流量协调器也有解决方案。 启动协调器时,将使用startWithOption并创建新流程或重复使用现有流程。 测试中 现在,我们的控制器和视图模型更加整洁,可重用,并且没有太多依赖项。 因此对我们来说编写测试更容易。 在本文中,我们将不涉及测试,因为这可能是一个全新的话题。 结论 使用流程协调器,我们从视图控制器中删除了导航逻辑。 我们的代码更干净,可重复使用,更易于更改且更易于测试。 起初,它可能会发现有太多的代码要编写。 但是,您可以编写许多代码-BaseCoordinator,Router,LaunchInstructor,您可以在其他项目中重用,因此这是第一次,需要进行大量工作。 有人说这太复杂了,我不这么认为。 […]
故事板。 你不能和他们住在一起。 没有他们,你活不下去。 作为团队一部分构建iOS应用的任何人都知道,合并地狱中有一个特殊的圈子专门解决此特定问题。 使用源代码控制, 将所有应用程序的UI设计放在单个文件中是不现实的。 您团队中的太多人将触摸该文件。 很快,任何东西都不会自动合并,因为情节提要中存在冲突。 当然,我们还希望故事板附带所有假定的好处。 原则上,希望在一个视图中查看应用程序的整个流程似乎是合理的。 不用说,拥有用于设计UI的可视工具真的很棒。 多年以来,我们一直吃着蛋糕,但也无法食用。 为什么? 这似乎是我们应该能够解决的问题。 今天的团队如何管理情节提要 我参与的最好的团队总是会在第一天就了解某种情节提要策略。 通常就是这样。 1.没有故事板代表通过应用程序的整个流程。 2.每个情节提要板代表应用程序中的单个屏幕,如果需要,则为View Controller。 3.每当您打算重用视图时,请继续使用它自己的nib文件创建一个自定义UIView子类。 4.散步,享受一生中额外的5个小时,因为您不再需要在同一个该死的整体XML文件中解决合并冲突。 当然,如果您做这些事情,您似乎会错过情节提要的关键卖点。 您已经放弃了一个文件可以神奇地向我们展示应用程序所有屏幕上所有用户旅程的想法。 也许这首先是一个误导的愿景。 也许在这样的想法中只存在边际效用,并且一直使用情节提要的人(阅读过实际的开发人员)并没有从中获得任何价值。 您当然可以提出一个案例,即一个情节提要不一定会浮出水面。 通常,注销用户会将用户带到某个开始屏幕,如果您查看情节提要,这并不是很明显。 因此,似乎我们想要的真正工具比我们现有的工具复杂得多。 故事板搜寻器的外观如何? 首先,我认为苹果公司或决定接受这一挑战的任何人都必须承认形势的现实。 不再有理智的开发人员在他们的项目中使用单个故事板。 这样做是因为无法使用源代码管理来处理您的应用程序。 因此,也许有一些单独的开发人员正在执行此操作,但是除非您拥有某种团队,否则项目无法真正快速扩展。 考虑到现实,我们如何改变它? 也许我们可以在真正使用它们时开始提及它们。 故事板,至少是我和我团队使用它们的方式,与其说是故事板,不如说是一个单一屏幕的表示。 因此,我们称它们为屏幕。 屏幕可以连接到其他屏幕。 不同的控制器可以管理如何显示不同的屏幕。 屏幕概念的本质是屏幕与其相邻屏幕的关系。 有了这个想法,我们就腾出了故事板,以表示它们本来应该具有的含义。 遍历应用程序中所有屏幕之间的所有关系时,将得到一个故事板。 作为开发人员,故事板不应该成为您要操纵的东西。 它应该是您在各个屏幕上完成的工作的计算结果,可以在需要时随时查看的高级视图。 这样的工作完成了吗? 并非如此,至少我不能用我微弱的Google搜索能力来分辨。 也许这是在苹果公司秘密进行的。 如果是这样,俗话说,除了拥有蛋糕,我们还可以吃蛋糕。 现在该怎么办? 暂时,实际上已经达成一致,如果要使用情节提要来可视化地设计View Controller,则应将每个View Controller分成自己的情节提要。 这样,如果给定的故事板文件中存在任何合并冲突,则将它们限制在单个View Controller中,而不是整个应用程序中的所有View […]
8月1日,星期三 在MVC中的视图控制器之间共享状态(第2部分) 8月2日,星期四 参考周期和所有权 选装件 8月3日星期五 平等的 建立表单库:简介 SQL —基本培训 构建Swift代码 将Objective-C类迁移到Swift:零碎的方法 8月6日星期一 构建表单库:简化IndexPath逻辑 快速提示:使用compactMap构建数组 加快Swift编译时间 8月21日,星期二 扑 气压测量 星期三八月22 建立一支优秀的工程团队:第一部分-从您开始 有效的远程通讯 PSPDFKit内部 切换到站立式办公桌 8月23日,星期四 时间表 星期五八月24 改善Xcode工作流程的提示 适用于开发人员的最佳开源工具 iOS的入门库 8月27日星期一 先进的iOS编程概念—真的是“高级”吗? iOS程序员纪律的重要性 快速文章改变了我的生活 如何在Xcode中轻松找到未使用的Swift代码 颤动-我的想法和印象-第一部分 亚搏体育app 让我们来谈谈建筑 错过其他 流利 星期四八月30 打字稿 Heroku 星期五八月30 溅 The Swift by Sundell通讯 MySQL事务 重构时,您是否在使用小步骤? 实施编码类型的自定义关键策略 真正杀死大多数创业公司的是什么 建立一支优秀的工程团队:第三部分-招聘 Arty […]
本文是关于UIView , UIViewController和UIWindow如何连接的。 我将说明如何遍历视图,视图控制器和响应者链的层次结构。 我们将通过推送,模式和嵌入演示来探索应用程序的结构外观。 并在Xcode中构建控制台版本的Debug View Hierarchy工具。 UI工具 Xcode中的Debug View Hierarchy捕获用户界面的快照,并允许浏览和检查视图对象。 有时控制台更方便。 我们可以使用私有方法对UI进行内部检查。 -[UIView recursiveDescription] -[UIViewController _printHierarchy] 您可以暂停应用程序执行,并在控制台中使用表达式来调用recursiveDescription和_printHierarchy 。 (lldb) expr -l objc -O — [[[[UIApplication sharedApplication] keyWindow] recursiveDescription] (lldb) expr -l objc -O — [[[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy] -l objc -O –用于将上下文从Swift切换到Objective-C。 View Hierarchy 应用程序通常包含许多视图和一个以上的视图控制器,从而建立了两个层次结构: UIView层次结构是一棵树,它的根位于窗口中( UIWindow是UIView的子类)。 我们可以使用subviews和superview属性遍历此树。 UIViewController层次结构从窗口的rootViewController开始。 视图控制器可以提供其他视图控制器或作为其他视图控制器的容器,从而创建两个不同的层次结构。 呈现的视图控制器 当我们使用Present […]
Swift 4带来了一种更加原生的方式来编码和解码实例,并内置了对每个人最喜欢的基于文本的格式的支持:JSON! 我们不使用所有的编码和解码源代码,而是采用一种不同的方法,并逐步通过一个简单的示例:单个Int实例如何通过JSONEncoder变成JSON数据? 从那里,我们应该能够更进一步,了解其他原始类型,数组,字典等是如何编码的。 封存 NSCoding作为Cocoa的一部分已经存储和检索数据很长时间了。 令人振奋的消息是,由于NSKeyedArchiver已有15年的历史了,Apple终于宣布弃用NSArchiver 。 😜 一个好主意是,如果可以对诸如字符串和数字之类的单个实例进行编码和解码 ,则可以存档和取消存档整个对象图。 编码所有事物 在Swift标准库中,除了编码 器之外,还有一些可编码的东西。 可编码是一种协议。 符合类型可以将自身编码为其他表示形式。 编码器也是一种协议。 编码器负责将可Encodable内容转换为其他格式,例如JSON或XML。 Encodable类似于NSCoding但作为Swift协议,您的Swift结构和枚举也可以加入聚会。 类似地,尽管Encoder还是协议而不是抽象类,但它与NSCoder对应。 一个简单的整数 您不能使用JSONEncoder编码裸标量,而是需要顶级数组或字典。 为简单起见,让我们从编码包含单个整数[42]的数组开始。 let encoder = JSONEncoder() let jsonData = try! encoder.encode([42]) 首先,我们实例化JSONEncoder ,然后使用数组在其上调用encode() 。 那里发生了什么事? // JSONEncoder.swift open func encode(_ value: T) throws -> Data { let encoder = _JSONEncoder(options: self.options) encode()方法采用一些Encodable值,并返回原始JSON Data 。 […]
协议和扩展是快速发展的组成部分。 到目前为止,您可能已经使用了很多时间。 您可能出于各种原因为您的班级或结构创建了扩展。 这里我将给出一些示例,其中您可以为几个现有的类进行扩展。如果你们还记得在Objective-C上工作,那么您将与Catagories交叉。 在这里,约束扩展是一种类别,您可以在不知道其内部工作的情况下扩展现有对象的功能。 在这里,我将以数组为例,数组是同质元素的集合,在进行实时项目时,您需要处理很多需要不断操作的数组,您可以提出扩展一样的 字符串数组 让我们假设一个场景,其中您有一个字符串数组,并且需要事先存储少量数据,例如 总字符数 字数 每个单词中的字符数 让我们来看一个数组示例,如下所示 let arrayString:[String] = [“教父”,“肖申克的救赎”,“辛德勒的名单”,“愤怒的公牛”,“乱世佳人”,“绿野仙踪”,“阿拉伯劳伦斯”,“阿甘”] 现在,假设您在整个项目中具有与上述所需的实现相同的数组。 为了避免重复并扩展现有Array的功能,我们可以编写如下扩展 通过在Array上实施受约束的扩展,您可以轻松避免代码重复,并且Array操作很容易。 让我们继续测试实施 让characterCount = arrayString.totalCharacterCount() 让wordCount = arrayString.wordCount() 让eachCharacterCount = arrayString.elementCharacterCount() 打印(“ characterCount = \(characterCount)”) 打印(“ wordCount = \(wordCount)”) print(“ eachCharacterCount = \(eachCharacterCount)”)//这将打印characterCount = 128 wordCount = 22 eachCharacterCount = [13、24、16、11、18、16、18、12] 这是数字的另一个例子 这是数字数组的另一个例子 在上面的示例中,这里以计算为例 数组元素的总和 将数值数组转换为字符串数组 这可以在任何数字数组上无缝运行,但在数组中的其他元素上同样会出错。 […]
惰性存储的属性是直到首次使用才计算其初始值的属性。 您可以通过在声明之前编写lazy修饰符来表示一个惰性存储属性。 除了存储的属性外,类,结构和枚举还可以定义计算的属性 ,而实际上并不存储值。 相反,它们提供了一个getter和一个可选的setter,以间接检索和设置其他属性和值。 编码一段时间后,您的大脑可能会告诉您它们是相同的。
我最近创建了一些按月划分的表视图。 这就是我按照对象的date属性对它们进行分组的方式。 我们将使用Doctor Who剧集演示该功能。 这是一种按日期对事件进行分组的方法: 我们使用reduce(into:)将我们的情节数组转换为以日期为键的情节字典。 在此示例中,当月播放的剧集将被分组在一起。 对于每个情节,我们从播出日期的年和月部分创建日期。 我们将当前情节追加到现有数组或空数组中,并将其设置为该日期键处的字典值。 不好意思的解释是抱歉,这篇文章更多地是关于算法的发展,而不是算法的细节。 😅 我们可以将此代码提取到一个函数中: 现在将这些情节归类如下: 让分组= groupedEpisodesByMonth(episodes) 我们可以采取几个步骤,使该方法可用于带有日期的任何模型对象。 首先,我们将创建一个带Dated协议。 然后,我们的函数将接受实现我们协议的任何内容,而不是接受Episode 。 基本上,我们只是将Episode类型替换为Dated 。 现在,我们的呼叫站点如下所示: 让分组= groupedByMonth(episodes) 差别不大,但现在我们可以使用date属性对任何内容进行分组。 我采取了一些额外的步骤来使它看起来更“快捷”。我没有将其保留为函数,而是在Array上创建了扩展名,并参数化了将要分组的日期组件(因此您可以按天分组,或年份等)。 让分组=情节.groupedBy([。year,.month]) 通过用常见情况的枚举来表示日期部分,我们可以使使用起来更加容易。 让分组=情节.groupedBy(.month) 但是我认为我所拥有的足以满足我的需求。 ☺️ 将我们的数据按这种方式分组后,将其以表格视图的形式呈现相对来说比较简单,但是我会再保留一天。 谢谢阅读。 🤲
在Twitter上关注我: @ kiranjasvanee 在开始深入研究无主且虚弱的事物之前,让我们先谈谈关于ARC的一些知识。 弧 当然,许多人都知道ARC(自动引用计数),当您创建任何类的实例时,它都会分配一块内存来存储有关该实例的信息。 当对象的引用计数等于0时,它将释放内存,因此其他对象可以使用同一内存。 那么,任何对象的引用计数如何变为0? 当没有任何变量指向该对象的引用(内存地址)时,这很简单。 关于保持对象引用的变量数量是该对象的引用计数。 好吧,这是一个基本概念,可以了解有关ARC的更多信息-Swift.org语言指南ARC 无主与弱 简单来说,“无主”和“弱”的工作方式相同,可以解决内存管理的保留周期问题。 两者都不会牢牢抓住它所引用的实例,在门后面都不会增加被引用对象的保留计数。 要了解有关保留周期的更多信息,请浏览相同的文档-Swift.org语言指南ARC。 那么,有什么区别呢? 无主引用不能为零,弱引用可以为零。 听起来很酷,但是实时有什么不同呢? 让我们通过示例来理解这一点。 从这里下载演示项目,如果您只是想了解这个概念,可以不用演示项目就可以继续。 演示中的内容-我们有两个控制器,一个是ViewController ,第二个是UnownedVsWeakViewController 。 可以通过URLSession调用从UnownedVsWeakViewController服务器下载图像。 我从ViewController -> UnownedVsWeakViewController ,然后立即导航(弹出)以了解在UnownedVsWeakViewController已经弹出时,在某些情况下,如[unowned self] UnownedVsWeakViewController [unowned self]或[weak self] ,闭包是如何反应的。 推送到UnownedVsWeakViewController并立即弹出,断点激活后检查调试内存图。 UnownedVsWeakViewController中仍然存在UnownedVsWeakViewController ,而您已经从UnownedVsWeakViewController弹出了。 这只是一个闭包调用,如果有很多闭包完成,您将最终将控制器保存在内存中。 错误的编码方案。 2.让我们尝试通过[weak self]实现这一目标 推送到UnownedVsWeakViewController并立即将UnownedVsWeakViewController弹出,一旦激活断点,检查调试内存图。 UnownedVsWeakViewController中不存在UnownedVsWeakViewController ,当您从中弹出时,它会立即释放。 注意: [weak self]无法阻止完成调用或在完成块内执行语句,只有在self不为nil时,它才会执行那些语句。 不要将自身包装在块中,如果自身为零,它会崩溃。 self !.imageView.image = UIImage.init(data: data!) 3.使用时间[unowned self] […]
Infelizmente -ou felizmente-nãotem magianão,一种可实现API的实现,它依赖于必需的对象和对象。 在GPS导航系统中,需要通过示例性的注册和维护。 Mas,se eujáconsegui suprair todas作为必需品,以及其他API的简单用法或… … Bom,nem semper \ _(ツ)_ /¯ Saber escolher是“功能强大的API”,其性能和功能都将在无损保护的情况下发生,包括制式,测试标准和无线网络。 第一件事: CoreLocation框架 确定地理定位的位置,海拔高度或灯塔位置。 可以使用Wi-Fi,GPS,蓝牙,barômetro,magnetômeeo硬件等框架来进行信息收集。 一个苹果公司的可替代性框架,它可以在地理上与当地环境隔绝,也可以在基础服务框架上提供良好的定义,并具有必要的作用。 O的核心位置,可以用特殊的方式在当地使用通用的本地化服务。 1.标准位置服务 主要控制权是本地化,高级配置,常规和正常使用的准证。 由中高级消费者提供的中高级预防法和中性服务 互联网的基础设施。 使用中或永远 使用时的必要条件。 Quando utilizar:必须对语言进行必要的复制,例如,必须对示例进行复制。 2.重大变更位置服务 递归消费者关系的决定性条款决定了当地使用权。 Ele notificamudançasdelocalizaçãoquando ousuáriotem um deslocamentothinkável,quetambémpode ser configurado,porémcomvalormínimode 500地铁。 Essa API要求永久使用。 Quando utilizar:在da s das上的aplicativos que precisam de mass commenosfrequênciaouprecisão。 举例来说,使用复制品进行分析的目的是要证明自己的目的。 3.拜访定位服务 为获得重大成就而进行的地点续集,请使用我们的临时机票。 […]