Tag: viper

VIPER的模块模板:尽量减少忙乱的方法

简介 自从我开始研究iOS已有5年了。 这些年来,我观察到您周围的一切都会随着时间而变化,无论是编程指南,开发语言还是客户(针对敏捷开发过程)给出的初始要求范围。 但是,一件事永远不会改变…… DEADLINE 。 这个词根据情况可能会致命。 如果软件开发有自己的词典,那么DEADLINE一词将始终与之抗争…… 当您在进行可伸缩项目时,通常会使用快捷方式来减少工作量。 其中一些快捷方式只是一段代码 ,可以在网上找到“第三方库”。 另一方面,某些方法只是通过将开发过程中涉及的其他过程最小化/汇总来加速整个开发过程。 与VIPER一起使用,因为您的解决方案体系结构使您熟悉失去分配的每一分钟的痛苦。 在这种情况下,您应该有一些技巧来加快开发过程(如果使用VIPER,与MVC😓相比,您已经在编写3倍的代码了)。 正如我在上一个博客中所承诺的那样,今天我将说明如何为VIPER Project创建模块模板。 入门… 我们需要开发的模块模板将具有与Xcode相同的创建新文件的过程。 为此,您需要转到位置 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/developer/Library/Xcode/Templates/File\ Templates/Source/ 在此位置,您可以找到许多扩展名为.xctemplate文件夹。 复制文件夹Cocoa Touch Class.xctemplate并将其粘贴到您的桌面,然后再开始浏览其内容,因为您不想弄乱Cocoa Touch默认文件模板。 现在,在Cocoa Touch Class.xctemplate (在桌面上)中,删除除TemplateIcon.png , TemplateIcon Cocoa Touch Class.xctemplate和TemplateInfo.plist之外的所有内容。 现在打开TemplateInfo.plist 。 这是目前对您最重要的文件,因为它将包含许多不同的配置。 在文件中,您可以看到许多键值对集。 但是所有这些都没有必要进行讨论。 让我们逐一地介绍一个人的必要条件。 一种。 描述 (类型:字符串)-描述是指您正在制作的模板的目标/最终输出。 选择您想要描述此模板将执行的操作的任何单词。 b。 摘要 (类型:字符串)-与描述相同。 C。 MainTemplateFile (类型:字符串)-用于命名模块文件。 由于VIPER模块中的所有文件均以模块名称作为其前缀,例如LoginView.swift,LoginPresenter.swift等。这将作为一种变量类型,其值为模块名称。 由于此密钥不存在于plist文件中,因此您需要使用___FILEBASENAME___值添加它。 d。 选项 […]

Xcode 9中的VIPER项目模板:当模块模板不够用时…

如今,iOS的要求非常困难(相对于时间)。 这些天的要求就像“我想要像托尼·史塔克(Tony Stark)的钢铁侠西装那样的东西”。但这不是难题。 问题出现了,当在下一行中听到“您有3个星期”,然后您会突然感到吐出这三个神奇的单词的冲动,可惜……..u不能……😕 就像您知道自己可以做到,但另一方面,您对自己的能力提出了质疑……“我能在DEADLINE内完成它吗?” 在满足这些要求时,大多数开发人员更喜欢从头开始工作,他们可以轻松地制定自己的工作策略。 但是,老实说,我们是否有足够的时间……从头开始。 最近,我正在使用新架构VIPER。 在研究了这种面向协议的体系结构之后,我意识到您必须有足够的时间来使用它,因为与MVC相比,几乎必须编写三倍的代码。😟 Xcode Project模板提供的内容是您必须播放的文件的最小限度基本展示。 但是,在进行大型项目时,您需要具有一个良好的结构,其中将包含Enums,Extensions,Constants,Storyboards,Feature Modules等文件。随着您深入了解需求,这种结构会不断发展。 因此,我想到了拥有一个项目模板,该模板将包含一个基本结构以及一些基本模块,例如登录,侧边菜单,仪表板,注销等。至少可以节省两到三天的初始工作时间…😁😁 对于创建项目模板,我想您首先需要了解的是项目模板的外观。 为此,请转到位置/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/developer/Library/Xcode/Templates/Project\ Templates/iOS/Application 在此位置,您可以找到许多扩展名为.xctemplate文件夹。 复制文件夹Single View App.xctemplate并将其粘贴到桌面上,然后再开始浏览其内容,因为您不想弄乱Xcode的默认模板。 首先,将文件夹名称从Single View App.xctemplate更改为Viper Project Template.xctemplate 。 但是更改文件夹名称并不能解决所有问题,而有关TemplateInfo.plist文件的所有操作都位于您必须使用的文件夹下。 打开TemplateInfo.plist 。 现在,像Xcode项目一样,项目模板也具有使它唯一的Identifier 。 对于单一视图应用程序,您可以看到com.apple.dt.unit.singleViewApplication 。 您可以将其更改为任何其他值,例如我使用的“ com.manishKumar.singleViewApplication”。 现在,只需保存TemplateInfo.plist文件,然后复制文件夹Viper Project Template.xctemplate并将其粘贴到复制Single View App.xctemplate 。 退出Xcode,然后重新启动。 现在,当您创建一个新项目时,将有一个类似的选项。 Yippee …😃😃您已经创建了自己的项目模板😎。 但是还没有结束。 根据VIPER结构,我们仍然没有任何内容。 我们现在需要对此进行努力…… 再次打开TemplateInfo.plist (保留在桌面上)。 在该文件中,在Options选项下浏览。 您可以在“ Units下看到两个选项 目标C […]

VIPER设计模式简介(Swift 3)

VIPER是首字母缩略词,代表可被视为干净架构的设计模式示例。 本质上,使用干净的体系结构,您可以将代码抽象为四层:实体(模型),用例(业务逻辑),控制器/网关/表示者(处理UI逻辑),设备/ UI / Web / DB /外部接口(框架)可能会改变)。 VIPER代表: V —查看(向用户显示信息并检测用户交互) I —交互器(通过获取数据和存储数据来操纵实体/模型) P —演示者(不使用UIKit,它包含与UI相关的业务逻辑并准备用于演示的数据) E —实体(您的模型对象) R —路由器(又称线框,负责模块/应用程序中的导航)。 VIPER体系结构可以使关注点更清晰地分离,并将viewController与处理应用程序中的大多数职责分离。 针对每个用例将关注点分为模块(即,为用户提供地图)。 每个模块都有清晰的路由逻辑,表示逻辑和业务逻辑层。 视图(视图控制器): 视图/视图控制器的主要目的是向用户显示信息并检测用户交互。 视图/视图控制器拦截用户事件,并且在VIPER设计模式内具有一个联系点: 演示者。 视图/视图控制器拥有并将用户操作发送给演示者。 例如, 视图/视图控制器将使演示者知道何时开始加载自身以及何时用户点击按钮。 主持人: 演示者从视图/视图控制器接收用户操作信息,并负责与UI相关的业务逻辑数据(但不包括UIKit!)。 演示者准备用于演示的数据。 演示者具有三个联系点: 视图/视图控制器 , 交互器和路由器 。 演示者负责从交互器中获取数据,并准备该数据以进行演示,然后将其传递回视图/视图控制器(以便可以对其进行更新),创建要移交给路由器的对象并确定是否要传递给路由器。需要来自交互器的更多数据。 我喜欢将主持人视为“调解人”。 交互器: 交互器了解我们的模型或实体 ,并从管理器类(即DataStore.swift)中获取并存储数据。 演示者要求交互器获取更新的数据,然后交互器将其提供回去。 交互器可以处理数据(即验证地图位置是否具有有效名称),并且可以调用帮助程序/管理器类(LocationStore.swift)创建实体 。 实体/实体: 实体是我们的数据模型(即MapName,MapCoordinate,MapLocation)。 这些实体由交互器操纵。 交互者完全了解实体及其属性。 路由器/线框: 路由器有一个联系点: 主持人 。 路由器 (又称线框 […]

毒蛇的第一个项目

在完成我在Viper的第一个项目之后,这篇博客文章只是一些个人经验。 如果您以前从未听说过Viper和干净的体系结构,则应该明确地观看此视频: 最初,一切都进行得很顺利,当我独自从事该项目时,我对自己感到非常高兴。 但是随后另一位开发人员加入了🙂他的第一个反应并不令人鼓舞: 男人,这个毒蛇的东西有点冗长。 我在各处写协议和存根…… 因此,我再次查看了代码。 好吧,他是对的。 如果您遵循这本书,最终会得到很多协议,在大多数情况下只能使用一次。 那时的某个地方,我还观看了有关保持代码可持续性的视频: 类由不同颜色的圆圈表示,您在类中的依存性越高,圆圈越大。 中心的蓝色大圆圈是AppDelegate。 好吧,它保留了对某些顶级视图控制器的引用,处理了一些通知,初始化了一些数据访问对象。 似乎其中没有太多代码,但最终仍然有很多讨厌的依赖项。 如果您考虑一下,这是有道理的。 AppDelegate可以引用RootViewController,而RootViewController可以引用MenuViewController,依此类推。因此,依赖关系的增长。 第二张图是我的第一个Viper项目。 AppDelegate做得少得多。 基本上,它只是创建一个根线框并将控制权传递给它。 每个模块仅知道需要直接调用的模块。 当然,这是您在任何项目中都想拥有的东西,但是在Wireframes中进行所有设置会使依赖项更加公开,并有助于使模块具有针对性和隔离性。 我最喜欢的是: 错误少很多。 它们几乎没有,而潜入其中的那些易于修复。 代码变得更像可互换的乐高积木。 使用现有模块组装新模块,重新组装旧模块,引入接口并为某些类添加不同的实现,所有这些都很容易做到。 我认为,这种方式的主要原因是依赖注入以及线框中所有模块的创建/组装。 再一次,重构非常容易。 想象一下,更改应用程序的整个导航树不会再让您感到恐惧🙂 几个月后,我很想再次查看该项目。 但是到目前为止,它看起来非常有前途!

iOS上的UITest轻松完成

我们知道,设计和编写测试并不是世界上最令人兴奋的事情,但是对于您编写的任何应用程序,测试都是绝对必要的。 它们可能是AppStore上闪闪发光的5星级应用程序,或者是漏洞百出的代码集之间的区别。 我们都知道什么是单元测试以及如何编写它们,但是自XCode 7以来,Apple便向我们介绍了其IDE中的UI测试。 通过这些测试,您可以记录用户与应用程序的交互,并检查其是否表现正常。 在本文中,我们将重点关注测试的UI方面,以及如何在iOS应用中记录和编写您的第一个测试。 但是为什么要专注于UI? 您的应用程序可能在后台执行了它需要做的所有事情,并且单元测试可能具有100%的覆盖率,但是对于普通用户来说,如果有什么地方不合适,那么就会出现问题。 通过测试应用程序的用户界面,您可以查看用户与用户界面的交互方式,并检查他们是否看到了应有的样子。 现在,让我们深入研究如何轻松测试UI而不会有任何麻烦。 在开发iOS应用程序时,我们必须首先决定将使用哪种架构。 苹果建议 ,大多数开发人员都使用MVC,但是MVC有其缺点。 我们可能都在某个地方读过或听到过大量的视图控制器笑话 。 可悲的是,在大多数情况下是这样。 当我们不得不将与View或Model逻辑不相关的所有内容放到Controller逻辑中时,控制器中会生成很多代码,而在Model或View中则不会那么多。 让我们快速看一下Viper是什么及其组件。 如果您不熟悉Viper,让我们快速介绍一下。 Viper是View,Interactor,Pentent,Entity和R external的首字母缩写。 这基本上是一种实施“ 单一责任原则”的方法 ,旨在创建一个更清洁,更模块化的结构。 Viper通过具有以下结构来实现此目的: 在上面的插图中,我们可以看到Viper方法以及架构的每一部分如何相互集成。 毒蛇的每个元素都负责完成一项工作,并要求/将任何其他工作发送/发送到负责任的元素。 例如,演示者告诉视图它需要显示什么。 在这种情况下,View的唯一工作就是显示演示者告诉其显示的内容。 为了帮助测试,Viper的每个元素(实体除外)都实现了一个协议,因此您可以轻松模拟类的任何部分并编写零麻烦的测试。 很简单吧? 让我们深入了解Viper的每个主要组件。 视图是被动的,因为它基本上只是等待演示者提供其内容来显示。 它还需要接收来自用户的输入,如果需要处理任何内容,则将其传递给Presenter。 View还具有有关如何显示数据的所有逻辑,例如哪些信息进入UILabel,以及哪些UIImageView将用于显示Presenter发送的图像。 输入想要用于测试目标的名称并创建它。 XCode会将这个新目标添加到您的项目中,并自动创建一个与目标名称相同的新文件。 在此文件中,您将已经创建了一些功能。 在每个测试之前和之后都有setUp()和tearDown()运行,还有一个testExample()。 您可以根据需要删除它们,但是为了简单起见,您可以选择函数testExample()并开始测试。 然后,XCode将允许您通过页面底部的红色圆圈按钮记录测试。 单击它,XCode将构建您的应用程序并启动模拟器。 您在此模拟器上执行的每项操作都将记录并记录在所选功能上。 我为本文创建的页面包含两个元素:UIImage和UIButton。 当我运行记录器并单击两者时,它生成了以下代码: 哇,这是很多用于点击图像的代码,不是吗? UIButton更好,因为它具有文本并且XCode知道如何搜索它,这意味着您可以找到所需的内容。 那么,如何处理图像呢? 嗯,有一个accessibilityLabel可以帮助您在屏幕上找到任何元素。 我将图像的acessibilityLabel设置为profileImage ,这使您的测试代码更易于编写。 开发iOS应用程序时,可访问性标签是您最好的朋友。 它为听力障碍的用户提供了一种导航您的应用程序的方式,还可以帮助您更好地测试UI。 您必须问自己,为什么我首先向您介绍了Viper。 当然,我们所做的测试可以使用MVC进行,但是如果您必须测试应用程序中更深层次的内容怎么办? […]

VIPER建筑

在软件开发中,我们遇到许多问题。 难以测试的代码,重复的代码或几乎没有分离的代码几乎每天都会让我头疼。 模式尝试解决某些用例的常见问题。 单例是一个简单的例子。 它解决了一个类只必须具有一个状态的问题。 设计模式(例如单例)和体系结构模式之间的区别在于,体系结构模式解决了与关注点分离相关的问题。 问题 我们创造了惊人的应用程序。 以及出色的应用程序,出色的用户界面和复杂的功能。 这意味着我们的功能将随着它们的增长而变得复杂。 我们必须考虑如何使所有内容清晰,可扩展,可维护且易于理解。 解决方案 VIPER正是解决了这个问题:它描述了我们零件的责任以及它们之间如何相互作用。 我将App PursCreate重构为VIPER,并开始在其他一些较大的项目中使用它。 这就是我学到的: 一切都有特定的位置。 您完全知道例如在路由器或演示器中放置了功能。 结构变得更加复杂,但是添加新功能并使它们与其他功能分离非常容易 我减少了副作用 为我的业务逻辑编写UnitTests更容易 让我简要介绍一下VIPER的各个部分: 视图 启动应用程序时,您看到的就是视图。 是带有圆角半径和阴影或某些渐变色药丸的红色按钮。 主持人 表示逻辑处理所有必要的操作,以便在视图中显示所有必需的信息(向数据的交互器询问) 。 它还可以处理所有用户交互,例如显示新屏幕,直观地进入编辑模式或自定义反向操作。 互动者 交互器包含业务逻辑或充当业务逻辑的基础。 在我最近的项目中,常见的用例是CoreData访问,在产品列表(购物应用程序)中过滤产品或触发HTTP请求。 实体 实体代表您的DataModel。 这可能是ManagedObjectModel(用于CoreData)或包含HTTP响应的结构。 路由器 路由器处理所有显示和导航逻辑。 例如,当用户单击一个按钮时:演示者将呼叫路由器并说:displayMyView()。 为什么要提取这种简单的逻辑? 因为它迅速增长。 在我的App PursCreate中,我遇到以下情况: 单击单元格时,将显示您的目标概述。 有两种目标类型。 因此,您必须确定这是经典任务还是连胜纪录。 现在,用户可以编辑他的目标。 如果他进入编辑模式,则必须再次确定类型,但是这次打开对应任务而不是概览的编辑。 当应用增长时,这部分可能会变得非常复杂。 复杂 VIPER具有许多优势。 但是,它带有很多复杂性。 这可能会导致不必要的过度设计。 作为程序员,我们的工作是确定哪种架构模式适合我们的用例。 也许MVC或MVVM非常适合简单的用例。 在更复杂的情况下,VIPER得益于其分离性和可伸缩性。 […]

使用VIPER架构构建Todo List iOS应用

介绍 确定构建iOS应用程序时使用哪种应用程序架构是最具挑战性的任务之一,可以从MVC,MVVM,MVP,View State,VIPER等众多架构中进行选择。 我们选择的体系结构将决定软件的构建方式以及随着软件的扩展而扩展。 本文将介绍的架构之一是VIPER架构。 VIPER以单一职责原则将应用程序结构划分为模块/屏幕内的组件。 这使应用程序变得更加模块化,并且与其他组件的耦合更少。 由于每个组件之间的边界(协议/接口),单元测试和集成测试变得更加简单。 VIPER的基本组件分为5部分: 视图:显示演示者告诉的用户界面,还将用户输入传达回演示者。 交互器:处理应用程序的业务逻辑,它与演示者进行来回通信 演示者:从交互器获取数据,并处理如何在视图中显示数据的逻辑。 它还从视图中继用户输入,并从交互器获取/更新数据。 实体:交互器使用的模型对象。 通常,交互器从单独的数据存储对象中获取实体。 路由/线框:处理演示者对象询问的导航逻辑。 它与要显示的其他模块/屏幕进行通信。 使用VIPER构建我们的待办事项列表应用 在本文中,我们将使用VIPER作为我们的应用程序体系结构构建一个简单的TodoList应用程序。 项目GitHub存储库可在此处获得。 我们将建立: TodoItem实体和TodoStore:TodoItem是代表Todo项的基本Class对象,TodoStore是存储TodoItem数组的DataStore。 TodoList模块/屏幕:向用户显示UITableView中TodoItem的列表,并为用户提供添加新TodoItem,删除TodoItem以及导航至TodoDetail模块/屏幕的功能。 TodoDetail模块/屏幕:显示TodoItem的内容,为用户提供删除和编辑TodoItem的功能。 它导航回到TodoList模块/屏幕。 应用程序委托集成:通过从TodoListRouter实例化TodoListView来设置应用程序的根UIViewController 建筑数据实体 TodoItem实体 TodoItem实体只是代表TodoItem对象的普通类。 它提供2个属性,标题字符串和内容字符串。 TodoItem实体 TodoStore数据存储 TodoStore是存储TodoItem列表的DataStore Singleton对象。 我们的应用程序只是将数组存储在内存中,但是将来我们可以扩展以将数据存储在File或CoreData中。 它通过todos属性和方法公开TodoItem数组,以添加TodoItem并删除TodoItem。 TodoStore 构建TodoListModule / Screen TodoListModule协议 我们为每个组件使用协议来定义每个组件如何在TodoList模块中进行通信的边界。 TodoListModule协议 实现TodoListViewProtocol 我们创建一个子类UITableViewController的TodoListViewController对象,并实现TodoListViewProtocol。 TodoListViewController的职责是按照演示者的指示显示用户界面。 它保留对演示者的引用,以中继用户输入并查看生命周期事件以使演示者做出反应。 当视图出现时,它将调用演示者viewWillAppear方法,以便演示者可以从交互器检索数据。 导航添加栏按钮项触发一个操作,该操作将显示带有2个文本字段的UIAlertActionController,供用户输入TodoItem的标题和内容。 然后,它将用户输入中继回演示者。 当用户滑动UITableViewCell并删除该行时,该视图会将用户输入重定向以将关联的ToDoItem删除回呈现给演示者。 TodoListViewProtocol提供2种方法来实现,showTodos传递ToDoItem数组,该数组将用于在UITableView内部显示TodoItem的列表。 如果演示者发生错误,showErrorMessage会传递一条错误消息,该UIAlertController将显示给用户,其中包含错误消息。 TodoList视图 实现TodoListPresenterProtocol […]

IOS APP的VIPER体系结构优势

众所周知,软件行业的软件体系结构至关重要。 设计代码很重要,这样每一部分都易于识别,具有特定目的并以逻辑方式与其他部分组合在一起。 它应该易于维护,可扩展并具有高质量。 在开发iOS应用时,请务必考虑应使用哪种iOS项目架构。 大多数开发人员使用Apple建议的模式。 但是还有其他! 在本文中,我们将研究VIPER体系结构,它是MVC的一种流行替代方案,它可以帮助您克服其限制,同时保持代码的组织良好,从而改善开发过程。 VIPER是View,Interactor,Presenter,Entity和Router的反义词。 此体系结构基于“单一职责原则”,这导致了干净的体系结构,从而为您的iOS项目提供了更好的结构。 让我们详细了解每个字母的含义: 视图。 视图的职责是将用户操作发送给演示者,并显示演示者告诉其的内容。 交互器。 这是应用程序的骨干,因为它包含应用程序中用例描述的业务逻辑。 交互器负责从模型层获取数据,并且其实现完全独立于用户界面。 主持人。 它的职责是根据用户操作从交互器获取数据,创建一个视图模型实例,并将其携带到视图中以进行显示。 实体。 它包含Interactor使用的基本模型对象。 它具有其他体系结构中模型层的部分职责。 路由器。 它具有用于描述何时显示哪些屏幕的所有导航逻辑。 在Viper架构中,每个块对应一个具有特定任务,输入和输出的对象。 这与装配线中的工人非常相似:一旦工人完成了对某个对象的工作,该对象就会传递给下一个工人,直到完成产品为止。 块之间的连接表示对象之间的关系,以及它们之间传递的信息类型。 从一个实体到另一个实体的通信是通过协议给出的。 这种架构模式背后的想法是隔离应用程序的依赖关系,以平衡实体之间的职责委派。 基本上,Viper架构将您的应用程序逻辑划分为较小的功能层,每个功能层都有严格的预定义职责。 这使得在层之间的边界处测试交互更容易。 它非常适合单元测试,并使您的代码更可重用。 简化复杂的项目。 由于模块是独立的,Viper非常适合大型团队。 使它具有可伸缩性。 使开发人员能够尽可能无缝地同时进行处理 解耦代码以实现可重用性和可测试性 根据角色划分应用程序组件 设定明确的责任,Viper是责任分配的倡导者 轻松添加新功能 由于您的UI逻辑与业务逻辑分离,因此使编写自动化测试变得容易 它鼓励将关注点分离开来,从而更容易采用TDD。 Interactor包含独立于任何UI的纯逻辑,这使得测试驱动变得容易 易于使用 创建清晰且定义明确的界面,独立于其他模块。 这使更改界面向用户呈现各种模块的方式变得更加容易。 借助单一责任原则,可以更轻松地通过崩溃报告跟踪问题 使源代码更清洁,更紧凑和可重用 减少开发团队中的冲突数量 适用SOLID原则 减少合并冲突的次数 您可能想要先创建初始体系结构框架,然后再将模块逐个交给其他开发人员以实现逻辑。 使代码库看起来相似。 阅读他人代码变得更快。 Viper架构具有很多好处,但必须指出的是,最好将其用于大型和复杂的项目。 由于涉及的元素数量众多,该体系结构在启动新的小型项目时会产生开销,因此对于不打算扩展的小型项目而言,Viper架构可能会显得过大。 因此,对于此类项目,最好使用其他内容,例如MVVM。 […]

VIPER 101

Merhaba,buyazıda的她的iOS平台mimilan olan VIPER mimarisini dilimdöndüğünceanlatmayaçalışacağım。 Yazınınhedef kitlesişuşekildedir; OrtamlardaVIPER’ıduymuşama neişeyarar tam emin olamayan,VIPER ile ufak tefek 1-2 projeyapmışamamantığınıtam olarakanlayamamışve yaanladığınıpekiştirmekisteyenkişiler。 Geliştirdiğimiz她的奶奶belirli bir mimariüzerinekurarız。 Seçeceğimizmimarinin kolay entegre edilebilir ve ek ek tigeltitieleelere uyumluolmasınıisteriz。 Aynızamanda kodumuzun okmasbilisolmasınıvearkadaşlarımızagösterdiğimizdehavalıbulmalarınıbekleriz。 Kısacabizyazılımcılarbi mimaridençokşeybekleriz。 在iOS电脑上,您可以下载mimari MVC’dir。 苹果酒,苹果酒,MVC,苹果酒,冰激凌。 ViewController’ınaşırışişmesibuna enbüyükörnektir。

使用VIPER与UITableView的iOS

我有一个视图控制器,其中包含一个表视图,所以我想问问我应该把表视图数据源和委托,如果它是外部对象,或者我可以写在我的视图控制器,如果我们说关于VIPER模式。 通常使用模式我这样做: 在viewDidLoad中,我请求一些来自演示者的stream,比如self.presenter.showSongs() Presenter包含交互器和showSongs方法我要求交互的一些数据,如:self.interactor.loadSongs() 当歌曲准备好传回视图控制器时,我再次使用演示者来确定如何在视图控制器中显示此数据。 但是我的问题我应该怎么做与表视图的数据源?