Tag: 编码风格

以正确的方式处理Swift第1部分

扩展,委托,黑盒,覆盖 不要这样 MyViewController类:UIViewController,UITableViewDelegate,UITableViewDataSource,UIPickerViewDelegate,UIPickerViewDataSource {…} 为什么? 这是不好的编码,您可能会继续向MyViewController添加更多的委托类,并使该类变得可怕。 记住规则:模块必须少于400行代码,包括注释。 像这样 制作一个名为MyViewControllerTableExt的新Swift文件,并将其添加 扩展MyViewController:UITableViewDelegate,UITableViewDataSource {…} 制作另一个名为MyViewControllerPickerExt的新Swift文件,并将其添加 扩展MyViewController:UIPickerViewDelegate,UIPickerViewDataSource {…} 为什么? 这些文件的名称将使代码更易于阅读和调试。 在小模块中跟踪错误比千行模块容易得多。 这也是良好的编码习惯。 几个月后,回顾一下代码,您会发现它们仍然易于阅读和维护。 不要这样 从父控制器 self.present(childViewController,animation:true){} 然后从该子控制器中按一个按钮 self.dismiss(动画:true){} 为什么? 这是错误的编码。 父母失去了控制。 它打电话给孩子,直到孩子决定解散自己才知道工作何时完成。 在最坏的情况下,父母可能会叫几个孩子,却不知道哪一个仍在记忆中。 这是不对的。 除非子控件是类似于box的单按钮屏幕,否则不要使用它。 像这样 创建一个名为globalStruct的快速文件,并添加此文件 协议ChildDelegate:类{ func childResult(数据:字符串) } 在子viewController中,添加委托 class ThisChildViewController:UIViewController { 弱var委托:ChildDelegate? … } 当孩子完成工作后,将控制权和数据传回给父母,然后它将做 自委托。 childResult(结果); 请注意, 孩子不会调用self.dismiss。 然后从父目录创建一个名为MyViewControllerChildExt的新Swift文件,并执行以下操作 扩展MyViewController:ThisChildDelegate { func childResult(data:String){ self.dismiss(animated:true){//父级在其控件中关闭子级 […]

MVC-组织代码的模式

MVC代表模型,视图和控制器。 它是一种体系结构,您可以使用该体系结构来组织代码,以便任何人以及您每次引用代码时都可以轻松理解它,因为那样的好代码可以被包括您在内的任何人轻松阅读。 有两种方法可以执行任何工作:要么在开始时就没有任何计划/架构,要么只是想到一个想法,然后就着手进行工作(尽管这是一个糟糕的方法),或者先计划好工作,例如您将如何实现该想法或创建一种架构类型,以便您可以轻松地分析自己在做什么以及您将如何进一步发展(这是一种更好的方法)。 也许您将能够使用这两种方法来完成您的工作,但是使用第二种方法,完成任务的可能性将会增加,并且最终结果将是效率更高的理想结果。 例如,如果我们谈论建造一座建筑物,那么我们都知道,首先,建筑会绘制一张正确的地图,因此建造者会建造该建筑物。 我们将通过日常生活示例来了解MVC的概念,以便您可以轻松地将其关联起来,并且可以更轻松地理解该概念。 有什么看法? 顾名思义,这是最终用户可见的应用程序部分(在阅读本文时,您是最终用户),该用户可以与应用程序的所有功能进行交互,并且可以能够输入一些数据以及以往的数据。 在应用程序的视图部分中定义了负责用户界面的所有代码。 让我们举个例子,假设您非常饿(您当时在吗?哈哈,开玩笑),然后您去一家餐馆浏览菜单并为您点菜,点菜在技术上是在您的数据中输入数据应用程序,您想要根据您的订单结果。 一段时间后,食物就在您面前,这与根据您的需要显示数据相同。 什么型号? 显然,如果您正在开发将处理大量数据的应用程序,则数据处理是主要问题之一。 处理和处理如此大量的数据有时会令人头疼,但是这要归功于MVC模式的模型部分。 在这一部分中,我们定义数据的类型,即,如果我们要向用户询问用户名和密码,那么期望用户输入哪种数据类型(或者可以说,应用程序中处理数据的部分)相关功能定义模型)。 例如,如果我们的应用程序要求密码,并且密码必须至少包含7个字符,但是如果用户输入6个字符作为密码,则该密码将不被接受,因为这与我们的模型设计背道而驰。 继续我们的餐厅示例,在接受您的订单后,订单将发送给厨师以准备食物。 现在准备食物,厨师将打开冰箱,放所有配料。 在这里,您可以将冰箱与一个数据库相关联,该数据库将包含烹饪食物的所有成分,而此处cook是一个模型,该模型将根据他/她准备食物的需求从数据库/冰箱中获取数据。 什么是控制器? 您所有的应用程序逻辑,即如何处理数据或如何访问用户请求或向用户显示什么,所有这些都在应用程序的控制器部分中定义。 它就像视图和模型之间的桥梁,或者顾名思义,它充当应用程序的视图和模型之间的控制器。 在我们的餐厅示例中,服务员充当控制器。 当食物准备好时,服务员将把食物从厨房拿到顾客那里,而厨师可能会拿着其他一些餐桌上的订单,因此服务员/控制器的工作是将正确的订单送达正确的桌子。 随着对MVC模式读取的越来越多的使用,代码的共享和可重用性也得到了提高。 想象一个应用程序,您在其中编写了所有代码(意味着没有代码分区),也就是说,所有代码都写在同一位置,并且相信我会造成很大的混乱。 同样,如果您在应用程序中使用MVC模式,那么可以在同一应用程序上一起工作的人很多,一个人处理视图部分,一个处理逻辑部分,依此类推。 MVC模式不仅限于特定的语言,该体系结构可用于任何技术。

使用MVVM使UITableView和UICollectionView更轻便

有时,同时使用UITableView和UICollectionView会导致膨胀的视图甚至是控制器。 当我们需要动态更改数据类型时,事情变得更加复杂。 可以说我们有如下两个部分: 在屏幕下方,有两个单独的部分,这意味着我们需要两个单独的模型,并且这两个模型是一致配置的。 如果选择“订单”,则必须使用“订单”模型在表格视图中准备单元格。 相反,当我选择“已完成订单”时,我还必须在表格视图中准备带有相关模型的单元格。 对于这种情况,我创建了两个不同的模型,第一个模型用于活动订单,第二个模型用于完成的订单,例如 对于这种情况,分离数据源会更加有益。 我们不应该将数据源文件重新使用到同一应用程序中。 相反,我们应该按表和集合视图创建数据源。 这样,我们可以测试我们的视图模型,模型甚至数据源! 为了使我们的模型不可变,我使用struct而不是class。 我的ViewModels现在有非常简单的工作。 我们的数据源仅实现UITableViewDataSource或UICollectionViewDataSource 最后,我们的视图控制器只做一件事; 在视图和视图模型之间进行调解! 通常,我们应该保持视图控制器的亮度。 这样,如果我们可以对视图模型进行单元测试,则可以增加我们的测试覆盖率和应用程序关联性,并执行一点SRP(单一责任原则)规则。 如您所见,我的视图控制器仅执行与视图相关的工作。 就像将我的数据源类绑定到表视图中一样。 当采用这种方法使red-green-refactor标准变薄时,我们可以测试几乎所有的业务逻辑。 我们可以像我之前说过的那样测试模型,查看模型甚至数据源。

扩展,私有和文件私有

封装是面向对象编程的四个基本原理之一。 访问控制是启用封装的设备的一部分[1]。 私有,文件私有,内部和开放是Swift中可用的四个访问控制。 这篇文章是关于我将如何使用扩展以及private和fileprivate来组织我的代码的简短说明,这导致了抽象。 在项目开始时很难进行抽象,尤其是在产品的所有功能和要求不清楚时。 在这里,我们组织代码的方式非常方便。 我从中受益的一件事就是使用扩展来组织我的代码。 随着项目的发展,这些扩展趋向于成为单独的类,结构或协议(在我的情况下主要是协议),并帮助我将自己的意图清楚地传达给其他开发人员。 让我们看一下这个新闻应用程序的示例,该示例具有两个集合视图选项卡,每个选项卡都显示某种类型的内容列表 TabA —显示来自某些集合的列表,但是没有完全定义需求。 TabB-显示最近添加的新闻文章,基于文章中嵌入的内容,UICollectionViewCell中将有一个媒体指示器(视频或音频)。 在本文中,我将重点介绍媒体指示器功能。 我们知道TabB的要求,此处显示了一个名为ArticleTeaser的视图模型(以1为例)。 它具有标题,文章的简短摘要以及文章中嵌入的媒体。 有一个计算属性mediaDisplayType ,它显示媒体是什么类型。 现在,让我们看一下另一个示例,该示例说明我们如何使用一些扩展来组织代码 现在,此扩展程序提供了从媒体列表中找到嵌入的媒体类型的功能。 这也使其他开发人员可以清楚地使用mediaThumbnailType fileprivate函数,该函数是此扩展的接口。 我的一位同事总是问我为什么您只有一个功能的扩展名? 答案是我倾向于将提供类/结构的特定行为的函数归类为扩展,即使它只是一个函数。 随着代码库的增加,这很方便。 现在,当TabA的要求到达时,我们注意到它还必须显示一些有关媒体类型的信息。 如果我们注意到扩展,我们使用的函数没有副作用,因此我们可以轻松地将其移入协议。 我们可以想到具有文件私有功能的这些扩展,就像我们编写的任何其他接口一样,但也可以作为在单个类/结构中使用的接口。 编码愉快! [1] https://en.wikipedia.org/wiki/Access_control

可解码的JSON解析—迅速的爱情故事

这些天哪个应用程序不解析JSON数据(可能是基于Firebase的应用程序)。 通过所有展开和错误处理,对JSON响应的解码会变得非常激烈。 借助Decodable协议,Swift使得开发人员最常见的任务变得简单,只需几行。 可以从外部表示形式解码的类型-Apple 可以将JSON对象或属性列表中的任何数据解析为符合标准的Struct或Class ,而不会造成任何麻烦。 优点 易腐烂是标准的,因此更多的人会知道如何使用它们,它将流行起来 具有一些不错的枚举用法,有助于提高代码的可读性 较小的代码 花费更少的时间编写和修改代码 解码数据(JSON或任何其他属性列表)时,catch块完成的错误处理 缺点 您可以通过反射实现所有这些新功能。 必须为所有子类实现另一个必需的init 仅支持Swift 4及更高版本 在我看来,利弊大于利弊,Decodable是一个轻松的赢家。 我建议经常使用它。 现在最重要的是,如何使用它!