Tag: iOS应用程序开发

Swift 4.0中的网络层

每当我开始一个新项目时,都会出现相同的问题。 如何实现网络层? 使用Moya,Alamofire等外部库或从头开始编写它。 我对这个问题的回答是–使用不带任何第三方库的纯Swift。 当然,实现面向协议的层非常简单,使用enum键入safe来配置端点并完全可测试。 在这几点中,您将学习如何编写可定制的面向协议的网络层。 在开始之前,了解URLSession及其组成类很重要。 通常, URLSession负责发送和接收HTTPRequests 。 对于基本请求,您可以使用没有配置对象的shared会话。 它不像您自己创建的会话那样可定制,但是如果您有非常有限的要求,它可以作为一个很好的起点。 对于其他类型的会话,您URLSession使用以下三种配置之一实例化URLSession : .default –会话表现为共享会话,但允许进行更多配置并使用委托增量获取数据。 .ephemeral –会话也类似于共享会话,但是不要将缓存,cookie或凭据写入磁盘。 .background –会话使您可以在应用程序未运行时在后台执行内容的上载和下载。 URLSession以两种方式返回数据: 完成处理程序 在委托上调用方法 在会话中,您可以创建URLSessionTask以从服务器检索数据,上传照片或下载文件。 此外,您还可以继续,暂停和取消任务。 URLSessionTask提供了暂停运行任务的机会,例如,当用户离开应用程序时暂停任务,并在返回时恢复任务。 URLSession提供三种类型的任务: data –使用Data对象发送和接收数据。 数据任务旨在向服务器发出简短的,经常是交互式的请求。 upload –与数据任务相似,但通常用于在应用程序不运行时上传文件并支持后台上传。 download –以文件形式检索数据,并在应用程序未运行时支持后台下载和上传。 在本教程中,您将仅使用第一种URLSessionTask来发送请求并处理服务器的响应。 简要回顾一下URLSession可以做什么URLSession ,现在让我们进行一些练习。 首先,您必须将网络层划分为小型服务。 将所有请求都保存在一个类/枚举中是很难维护的,并且可能会变成一个庞然大物。 ServiceProtocol将帮助创建URLRequest 。 ServiceProtocol包含构成组件,例如baseURL,路径,方法,标头,任务和parametersEncoding。 继续创建您的第一个简单网络层文件。 HTTPMethod是一个枚举,负责设置请求的HTTP方法。 URLRequest具有.httpMethod属性以设置方法的字符串类型。 Task是一个枚举,负责为特定服务配置参数。 您可以添加适用于您的网络层要求的情况。 例如upload(Data) , download(parameters: Parameters)等。该示例只有两种情况可以发送普通请求或带有参数。 ParametersEncoding是负责设置编码类型的枚举。 在此示例中,您必须使用最流行的:URL和JSON。 瞧! 创建网络层的第一部分已经完成。 […]

带角半径的UIView阴影

大家好, 感谢您将宝贵的时间花在我的教程故事上。 我将在2019年提出更多更好的方案。我希望您和所有人的成功。 一个自定义IBDesignable类,用于渲染阴影和角半径: 阴影始终需要附加或绑定到视图的边界。 更改拐角半径时,阴影也应正确应用于那些蒙版的拐角。 为此,我们在带有视图边界的Rect中创建一个shadowPath,并将设置视图层上所有必需的属性以及所需的拐角半径值。 例子:- 注意:要为视图蒙版特定的角,我们可以在视图的图层上使用maskedCorners属性传递所需的角以及图层上的角半径。 view.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner] — — — — — — — — — — ************************** — — — — — — — — — 您可以在推特和链接上与我联系/关注我 帐户。 谢谢阅读… ****************************!!!再见!!!************** **************

Swift中的App架构和对象组成

对象组合是面向对象编程的核心概念。 对象可以包含其他对象,有时会创建复杂的层次结构。 在本文中,我想展示如何设计这种架构。 在一个实际的示例中,您将看到处理复杂的层次结构很简单,而对象和层次结构可以重用。 面向对象的设计过程包括规划对象如何连接和交互以创建零件或完整系统。 我们都习惯了Model-View-Controller体系结构,该体系结构定义了包含视图和模型的控制器对象。 这些组成部分共同构成了应用程序的基础。 形成树结构的递归类型使事情变得有趣。 递归组合很简单,可以用来表示任何潜在的复杂层次结构。 组合模式是“设计模式:可重用的面向对象软件的元素”一书中描述的结构模式。 它描述了如何构建由两种对象的类组成的类层次结构:原始对象和复合对象。 将对象组合到树结构中以表示部分整个层次结构。 复合可以使客户统一对待单个对象和对象组成。 设计模式:可重用的面向对象软件的元素 复合模式定义了下一个参与者: 组件是一个抽象接口。 它声明函数并由客户端使用。 Leaf实现了由Component接口声明的功能。 复合工具组成。 它包含子组件数组。 Composite通过委派(转发)对其子级的调用来实现Component接口声明的功能。 客户端是通过Component接口使用合成的代码。 我们可以像这样实现Composite模式: 现实生活中的实现可能会略有不同。 常见的变化是Component,Leaf和Composite是同一对象。 使用树结构进行组合是一种非常强大的模式,它对应用程序体系结构具有很多好处: 将复杂的任务分解为小部分。 组件解决小任务。 组成一棵树以解决更大的任务。 与复杂结构进行交互的方式与与单个实例进行交互的方式相同。 组件树具有与单个组件相同的接口。 单一责任原则。 组件负责单个功能。 它可以是特定于域的,也可以是特定于组成的(例如按特定顺序安排孩子)。 可重用性。 组件是可重用的,可以在更大的层次结构中使用组件树来解决更大的任务。 可测试性。 由于组件和组件树是独立的,因此可以进行单元测试。 应用各种设计模式的机会。 树结构可以很好地与各种创建,结构和行为设计模式配合使用。 简单。 最后但并非最不重要的。 在特殊情况下,复合模式只需要一个类即可实现。 树和树上的操作对于开发人员是众所周知的。 难以置信? 让我们看一些例子。 UIView UIView的层次结构可能是树结构最突出的示例。 视图是应用程序用户界面的基本构建块。 可以将视图嵌套在其他视图中以创建视图层次结构。 例如,我们使用小的UIView节点构造复杂的树。 我们可以按功能对视图进行分组: 基础UIView类。 它定义了所有视图共有的行为,呈现内容以及处理与该内容的任何交互。 显示内容。 […]

在iOS中设计实体层次结构:类继承v组成

设计不佳的实体层次结构可能像这座塔一样不稳定。 不灵活的设计可能无法接受新的实体或特征,并且可能导致大量的代码复制和粘贴。 层次结构中更下层的实体可能会导致不必要的行为或意外的实现,并且大量的覆盖可能导致较差的动态调度。 简而言之,正确设计很重要! 设计这种层次结构有两种常用方法: 类继承 和 组合 ,您可能会惊讶地发现一种方法明显优于另一种方法。 在本文中,我们将使用这两种方法设计一个简单的层次结构,以讨论它们的优点和缺点。 让我们开始吧! 方法1:类继承 类继承是在OOP中设计实体层次结构的经典方法,即使是初学者,也将很快熟悉本节中的概念。 作为一点点回顾,让我们提醒自己,继承是一种基本行为,已植入到类中,但未在结构中找到。 出于本文的目的,我们将构建以下层次结构的代码表示形式: 在代码中,它看起来像这样: 在这种情况下,不能将任何功能放在Bird超类中,因为它们都不是所有四个Bird子类都通用的。 相反,我们有不同的组合。 为了使这些功能在需要的地方可用,我们被迫做这样的事情: 即使一眼就能看出这是一个糟糕的解决方案,原因有几个。 首先,有很多重复,将相同的方法实现复制到不同的类中。 试想一下,如果我们需要对这些方法之一进行更改,那么现在我们需要在多个位置进行相同的更改。 接下来,它也打破了单一责任原则。 就Puffin而言,我们在单个类中实现了所有三种方法。 为了代码的可维护性,我们理想地希望看到封装在不同实体中的这些不同职责。 有人可能会争辩说,可以通过一些“创造性”子类来减少复制的数量,但这不可避免地导致了继承杂耍行为,这种行为只会随着新方法的引入而变得更加复杂,或者新类仅需要某些继承的方法而变得更加复杂。 。 我们最终得到了一个非常脆弱的层次结构,在该层次结构中,超类的单个更改可能在继承链的更下方产生无法预测的结果。 除此之外,当我们查看开始的层次结构图时,我们被提醒,我们的理想是将所有鸟子类都置于同一级别,这是用这种方法无法实现的。 那么为什么类继承不能给我们想要的结果呢? 构架此讨论的一种有用方法是考虑“是”与“具有”的关系。 类继承仅限于表示“ is-a”关系:很好地描述了海雀 “ is-a” Bird和Bird “ is-a(n)” Animal 。 但是,当我们尝试表示“具有”关系时,通常会达不到要求。 在这种情况下,我们可以将“具有”表示为一种属性(“具有喙”)或一种方法(“具有飞行能力”)。 我们看到想要添加swim() , walk()和run()的功能未在我们的鸟子类中一致地应用,这并不罕见。 在您脑海中越是用“ is-a”和“ has-a”观察世界,您就越会意识到自然世界并不是那么容易装箱。 方法2:通过协议组成 因此,现在让我们通过合成解决相同的问题。 以下方法由四人帮提出,用一种优雅的方式描述了这种方法: 编程到接口,而不是实现。 在iOS中,我们通过使用协议定义接口。 任何采用协议的实体都必须在合同上遵守所要求的接口,这实质上就是上述短语要求我们执行的操作。 现在,我们的基本设置如下所示: […]

协调员:复审

驯服无节制的应用程序架构 返回协调员 因此,距离我写上一篇关于协调员的文章已经几个月了。 在此期间,发生了很多事情! 我发布了一个名为PodCatch的新应用程序(我使用协调器概念构建了该应用程序-仍在进行中): chriswebb09 / podcatcher podcatcher –播客应用 github.com 我参加了尝试的活动! 纽约市Swift会议: 在此过程中,我有机会更详细地探讨了这个概念,并找出了对我有用的功能。 背上盘旋 我觉得现在是时候回过头来,完成我关于协调员的系列讨论的好时机。 在我走得太远之前,我想先拥有一件事。 我认为我的第一篇文章不是对该主题的出色介绍。 它缺乏重点,因为我试图将太多概念引入范围更窄的事物中。 除了这篇文章之外,本系列文章很可能是第三部分,因为这篇文章本身并不完整,我对我最初写的内容不满意。 我知道现在回过头来是我在CoreLocation上写的系列以及我希望退出的示例项目中的一个不切实际的话题(下周暂定)。 我现在写这本书是因为我想在尝试有关该主题的对话时记下来! 上周在纽约召开的Swift大会仍然让我记忆犹新。 ¯\ _(ツ)_ /¯ 应用程序控制器/协调器 因此,让我们对第一部分进行一些回顾,如果您已经阅读了该文章,那么这似乎有点多余。 视图控制器的问题之一是,随着应用程序开发的进行,它们可能变得庞大而笨拙。 这是因为它们的目的可以得到广泛的解释。 如果您的大多数应用程序都在视图中工作并且视图控制器“控制”视图,那么将许多应用程序逻辑放在其中似乎是完全合理的。 显然,这种方法存在严重的缺陷。 如果您已经阅读了Soroush Khanlou关于协调员的博客文章,那么这是多余的,如果您还没有,我只是简单地谈谈一些背景信息。 不幸的是,以视图控制器为中心的应用程序开发方法不可扩展。 协调器是将您的代码隔离为易于替换的小块的好方法,并且是解决控制器不适的解决方案的另一部分。 — Khanlou:协调员 协调器模式是一种企业软件设计模式,已适应iOS世界: 您可以通过将所有流逻辑放在应用程序控制器中来删除重复项。 然后,输入控制器向应用程序控制器请求适当的命令,以根据模型和要根据应用程序上下文使用的正确视图来执行该命令。 —马丁·福勒 我喜欢他们在顶部发布的tl; dr,它对协调员要完成的工作的定义很简洁: 处理屏幕导航和应用程序流程的集中点。 出于这篇文章的目的,我想尽可能地强调应用程序的流程和导航。 观察结果 我尝试了一些开发人员! 在纽约召开的Swift大会上,他们对协调员的使用以及与我交谈过的每个人都对他们的职责和限制有不同的解释。 我与之交谈的一些开发人员已经定义了功能,这些功能要求将任何东西标记为诸如start方法之类的协调器。 其他人则使用协调器协议,而无需任何方法来将控制其应用程序体系结构的类绑定在一起。 从我与Soroush的对话中收集到的信息,解释的范围是设计使然的。 那么什么是协调员? 协调器是使一个或多个视图控制器周围的对象。 将所有驱动逻辑从视图控制器中移出,并将这些内容向上移动一层,将会使您的生活变得更加美好。 […]

iOS黑暗主题

显然,如果我们计划支持更多主题,则我们必须选择其他数据类型(例如,您可以选择Integer类型并创建带有所有主题的枚举类型)。 另外,我还创建了一个简单的帮助程序类来获取/保存设置。 我有一个动作连接到Dark mode开关。 现在,当用户更改主题时,我们可以在应用程序中的任何地方捕获该通知。 基本控制器 当然,如果我们在每个视图中分别捕获通知,那将不是最佳选择。 我们可以在这里创建基本控制器类并自定义大多数内容。 当我们在视图中有特定的东西时,我们可以重写方法之一: enableDarkMode或disableDarkMode 。 表格视图的基本控制器。 用于视图的基本控制器。 现在,当用户更改主题时,我们的通知将捕获到我们的基本控制器之一中,并且应用程序正在更改视图样式。 您可以在GitHub存储库中检查整个解决方案: 姆恰楚斯基/ vcoin 通过在GitHub上创建一个帐户为vcoin开发做出贡献。 github.com 我希望这可以帮助你!

运营和中央调度的面试问题(第二部分)

iOS面试问题,gcd面试问题,多线程ios面试问题,iOS 在本文中,我将介绍一些与Dispatch相关的问题,但是解决方案以目标C语言给出,并且可以在Swift上移植。 为这些问题在目标C中提供解决方案的原因是我在Citrix等公司接受采访的一位朋友,他们之所以要求在目标C中编写解决方案,是因为开放是面向同时了解obj C和Swift的开发人员的。 希望它也能帮助其他开发人员,让我们开始吧。 Q1。 dispatch_once和dispatch_once_t的用途是什么,用示例写下代码? 解决方案 : 单身人士 Q2。 dispatch_after的用途是什么,用示例写下代码? 解决方案 :如果您需要在特定的时间点运行某些内容,那么dispatch_after可能是正确的选择。 一定也要检查NSTimer。 Q3。 什么是目标队列,用示例写下代码? 解决方案 : 惊喜:您已经在使用它们! 您创建的任何队列都必须具有目标队列。 默认情况下,它设置为DISPATCH_QUEUE_PRIORITY_DEFAULT全局并发队列。 Q4。 下面的代码有什么问题,如何解决? 解决方案 : dispatch_set_target_queue使从firstQueue或secondQueue执行的每个块都表现得“好像”已使用dispatch_async提交给并发队列。 成为目标队列不会影响dispatch_barrier_ *函数的语义。 屏障保证在屏障块运行时队列中没有其他任何执行。 Q5。 编写用于创建所有类型的队列的代码,还让我们知道优先级吗? 解决方案 : Q6。 编写一个资源,多个读取器和一个写入器的代码(基本上是用于多线程读取和单线程写入的读取器写入器)? 解决方案 :同步/异步模式的一种优化是读写器模式,在该模式下,允许并发读取,但不允许并发写入。 因此,您将使用并发队列,dispatch_barrier_async进行写操作(实现写操作的类似串行行为),但是使用dispatch_sync进行读操作(就其他读取操作而言,享受并发性能)。 Q7。 编写死锁条件代码? 解: Q8。 什么是dispatch_apply ? 为用例编写代码? 解决方案: dispatch_apply —迭代执行性能的改进,请查看下面的示例以更加清楚。 Q9。 编写DispatchGroup用例的代码? 解: Q10。 编写DispatchGroup用例的代码? 解: […]

2019年和2020年iOS应用开发的十大趋势

繁荣的技术一次又一次地为移动平台带来了新的进步。 物联网,增强现实和虚拟现实是一些未来派概念,无论操作系统如何,它们都会给移动应用程序开发过程带来根本性的变化。 这些概念的集成将帮助开发人员带来具有所需功能的下一代移动应用程序。 在谈论iOS时,苹果公司已经使该平台成为进化和创新的缩影。 如何经历一些会影响iOS应用开发过程的主要趋势? 每年,库比蒂诺公司(Apple)都会在硬件和软件方面进行新的升级。 与这些更新一致,新的iOS版本具有更多改进。 物联网,AR和VR等新兴技术的出现为iOS应用开发开辟了新的可能性。 我们已经在2018年的开发过程中目睹了这些技术的实现。现在,让我们列出iOS的应用程序开发趋势,并展望未来……了解更多

Swift 3的MVC架构简介

MVC背后的梦想 MVC是用于强大的面向对象编程的强大iOS体系结构模式。 它可以将应用程序的数据/逻辑,视图和控制器清晰地分开。 理想情况下,模型和视图不应直接交互,而控制器应进行调解。 如果使用后端或本地存储系统,则更新模型对象的逻辑应在这些模型文件中。 视图应该是“哑”的,并且只能处理与演示文稿相关的任务。 现实 大规模视图控制器。 通常,遵循MVC设计模式的应用程序具有绝对庞大的视图控制器文件,可以执行所有操作。 另外,您的应用程序一定会违反MVC规则,这几乎是不可避免的。 视图可能会直接与您的应用程序数据交互,或者模型可能会更新用户在屏幕上看到的内容。 根据MVC和Apple的说法,这是不容忽视的,但它一直都在发生。 我应该为我的应用程序使用MVC吗? 如果您只是刚入门或正在构建相对简单的应用程序,则MVC很可能是完美的。 让UIViewController对象做很多不同的事情是创建简单应用程序的一种非常简单的方法。 MVC已建立并且有据可查,因此很容易找到很好的例子。 Apple关于MVC的文档: https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html 一些替代方案: MVVM —模型,视图,ViewModel Swift中的MVVM – Artsy工程 模型视图ViewModel已成为我在iOS上编写应用程序的默认方式–它使编写iOS应用程序变得很有趣。 我写了…… artsy.github.io VIPER —视图,交互器,演示者,实体,路由 使用VIPER构建iOS应用程序·objc.io objc.io出版有关iOS和OS X开发的高级技术和实践的书籍 www.objc.io 对于初学者来说,其他设计模式可能较难入手,但是,如果您要开发复杂的应用程序,那么从长远来看,了解和采用MVVM或VIPER可能对您和您的团队有所帮助。 当今,大多数流行的应用程序都使用自己的设计模式-通常是传统模式的混合。 给那些使用MVC的人一些最终提示 给您的对象明确的责任,不要偏离他们。 使您的视图可重用,灵活且可测试。 尽量保持控制器清洁。 调试会容易得多。

自定格单元

使用Swift在iOS中使用TableView和CollectionView App Store上的大多数iOS应用程序都有一个项目列表的UI表示形式,因此很明显,iOS开发人员在整个开发过程中花费了大量的时间使用TableView和CollectionView。 自2009年以来,在AppIt Ventures,我们一直在开发iOS应用,并适应iOS提供的所有技巧,改进和新功能。 在本文中,我们希望共享一个称为“自调整大小的单元格”的概念。 尽管这不是一个新话题(iOS 8宣布了这一话题),但我们希望通过Self-Sizing Cells帮助初学者了解更多详细信息和用例。 在iOS 8之前,在具有不同高度的单元格的TableView或CollectionView中显示动态内容并不是一个容易的过程。过去,我们不得不以编程方式计算每个单元格的高度并增加相应单元格的高度。 使用自调整大小的单元格时,显示高度可变的动态内容是一个简单的过程。 将自动布局用于tableview单元内的UI元素。 将Tableview rowHeight设置为UITableViewAutomaticDimension 。 设置estimatedRowHeight或实现高度估计委托方法,并且此estimatedRowHeight将是单元格的默认高度。 设置这两个属性后,系统将使用“自动布局”来计算行的实际高度。 EstimateRowHeight是情节提要中原型单元格的高度,当rowHeight属性设置为UITableViewAutomaticDimension我们告诉tableview根据单元格中添加的其他约束来计算单元格高度。 让我们看一下如何演示如何将tableview告知自身大小的快速演示 。 创建一个示例报价列表演示,以在表格视图中显示带有作者姓名的报价,并使用自定义单元格将表格视图单元格设置为自定义表格视图单元格。 在此示例演示中,我们将展示如何创建支持动态类型的自定义TableView单元格 。 由于动态类型使用户可以控制在单元格中显示的文本的大小,因此,必须根据文本大小调整单元格的大小,这一点很重要。 在情节提要中 ,使用tableview单元格并在其中添加两个标签。 2.我们必须在View控件r中添加以下两个Tableview委托方法。 要么 我们可以在viewDidLoad方法中添加以下两行代码。 3.在数组中加上一些引号,然后将其分配给indexPath()方法中cellForRow中的引号描述标签,有关结果,请参见下文。 在上面的结果屏幕中,我们没有得到预期的结果,因为我们需要将报价描述标签的行数设置 为零 。 设置好之后,最终结果如下。 与tableview演示类似,我们必须按照以下步骤将自定义集合视图单元格设置为自定义大小的 collectionView单元格 。 对UI CollectionView单元内的UI元素使用自动布局 。 设置UICollectionViewFlowLayout的EstimatedItemSize 。 设置systemLayoutSizeFitting为 UI CollectionView单元格。 estimatedItemSize是CollectionView中原型单元格的估计大小。 当我们将systemLayoutSizeFitting属性设置为CollectionView单元时,CollectionView根据其当前约束返回最佳视图大小。 就像我们对TableView所做的一样,让我们​​为CollectionView创建一个报价列表演示,并使用自定义单元格显示作者照片的报价。 我们必须在CollectionView自定义单元格类中添加以下方法。 在情节提要中将行数设置 为零 在CollectionView单元格(如TableView单元格)中获取报价描述标签。 最后,看到用于自定义UICollectionView单元格的结果屏幕。 注意:上面创建的CollectionView演示在UI和空格方面存在问题。 […]