Tag: swift

带有枚举的Nifty,Bug-Safe URL

这是一个分为四部分的系列文章的第二篇,该文章名为: Nifty,Swifty,API支持的App 。 您可以在 此处 分叉最终项目 。 第1部分:具有GitHub Pages的Nifty静态内容托管 第3部分:具有可分解功能的漂亮自构对象 第4部分:带有NSCache的漂亮的自动缓存ImageView 介绍 在上一篇文章中,我们设置了静态内容宿主,并在Xcode项目中创建了一个非常简单的APIService,下载了一些json内容。 调用下载json的方法如下: 我们可以在第一行看到传递的字符串相当长,这是在根目录中获取数据。 想象一下,当我们导航到层次结构中更深的文件时,字符串将得到多长时间! 显然,URL路径越长,我们的代码就越容易受到拼写错误的影响。 在本文中,我们将创建一个枚举,以最简单,最安全的方式处理所有文件路径。 创建URL枚举 在我们的应用程序中,URL将仅由我们在上一篇文章中构建的APIService使用。 因此,有意义的是,处理我们不同的url大小写的枚举位于同一实体中。 这是我们的两种情况: 您会注意到baseURL存在于枚举之外,这在每种情况下都是必需的(第3行) 。 我们的枚举有两个变量: path (第9行)和url (第16行) 。 这是因为我们要使用字符串构建路径,然后使用该路径来初始化我们的URL。 注意,在url结构(第18-19行)中 ,我们可以简单地调用self.path来获取所需的字符串。 因为objectData.json是我们唯一需要的根文件,所以其路径构造非常简单(第11行) 。 另一方面,获取我们的图像需要一个图像文件名作为关联值,作为我们的终点。 要提取关联的值并将其用于我们的字符串构造中,请使用let (第12行) 。 使用URL枚举 现在,我们可以将输入参数更改为新的APIURL类型,而不是将冗长的字符串传递到fetchData方法中。 文件1:在方法定义中,我们以枚举形式作为输入参数,因此我们需要使用apiURL.url (第3行)来获取URLSession的url。 文件2:现在,当我们可以调用方法时,可以使用非常简单的点表示法.json (第1行) 包起来 这就是每次提供安全网址的简单程度! 使用具有关联值和计算变量的枚举非常强大,并且可以最大程度地确保您的URL可以正常使用,从而使您可以灵活地获取所需的任何端点。 请单击此处阅读第3部分: 具有Decodable的Nifty自构造对象 ,在这里我们使用json安全构建对象并且没有疯狂的解析。 谢谢阅读!

使用RxDataSources的TableView中的节和动画

仅使用RxSwift,就很难实现TableView动画,并且很难用Header文本配置表视图部分。 同时配置多种类型的单元也是一个挑战。 Rx社区非常庞大,并且对RxSwift有很多有用的扩展。 RxDataSources就是其中之一,它可以解决上述所有问题。 您可以在重新加载,插入,更新或删除时为Tableview单元设置动画。 您可以根据需要自定义和配置不同的单元。 您可以将节添加到TableView并配置Header。 这可以用很少的代码来完成。 这一集展示了所有这一切。 如果您喜欢这些教程的质量,请喜欢,订阅和分享。 请观看以下链接提供的所有剧集: 第1集-https://youtu.be/fH9paWpCvQs 第2集- https://youtu.be/qLbUzwZrQjc 第3集- https://youtu.be/qLbUzwZrQjc 第4集- https://youtu.be/b1GadsUtB9s 第5集- https://youtu.be/EZtCOQyRK7w 第6集- https://youtu.be/T0yT6J_Mp9U 第7集- https://youtu.be/ur-U9nzazbc 第8集- https://youtu.be/6KC1GdLnez0 第9集- https://youtu.be/fT_VI1SiapQ 观看其他TOP编程教程,网址为: youtube.com/c/letscodeeasy 请关注我们: http://letscodeeasy.com www.facebook.com/letscodeeasy https://twitter.com/letscodeeasy

快速失败的初始化器

简短而详细地介绍了失败的初始化程序。 Apple docs :初始化是准备使用的类,结构或枚举实例的过程。 此过程涉及为该实例上的每个存储属性设置一个初始值,并执行新实例准备使用之前所需的任何其他设置或初始化。 定义类 , 结构或枚举值时,如果初始化程序失败,应通知用户。 由于以下原因,以下变量的初始化有时可能会失败: 无效的参数值。 缺少必需的外部源。 阻止初始化成功的条件。 为了捕获初始化方法引发的异常,Swift生成了一个灵活的初始化,称为“ failable initializer”,以在初始化结构,类或枚举实例时通知用户发生了问题。 通过在init关键字( init? )后面放置问号,可以编写失败的初始化程序。

构建Foursquare克隆iOS应用-第5部分:网络层

第1部分:简介和设置 第2部分:位置数据和管理依赖项 第三部分:持续集成 第4部分:流媒体位置 第5部分:网络层 第六部分:国家管理 在详细说明此应用程序的范围时,我不希望主数据源是一个简单的API调用,而是要更复杂一些,这取决于两个数据源的集成。 这样,测试将更加复杂,并且需要更多的计划和研究。 在这种情况下,显示给用户的最终数据取决于iOS SDK提供的用户位置,该位置将用于请求附近地点的Foursquare API。 现在,我们有了获取用户位置的可靠方法,我们可以在Foursquare Places API请求中使用此信息来获取附近的位置。 Moya依赖关系将帮助我们完成此任务,特别是通过将HTTP响应自动包装到Observable 。 我们感兴趣的端点是“获取场地建议”。 通过阅读文档,我们需要发送的请求参数为: v :我们要使用的API版本。 我使用的是本文撰写的当前日期。 venuePhotos照片:布尔值,以在响应中包括照片 limit :结果数 ll :经度和纬度 client_id和client_secrent :您通过在Foursquare开发人员平台中注册获得的凭证 为了将所有这些翻译成Moya可以理解的语言,我们需要创建一个enum ,每种case都将代表给定URL的终结点。 然后,该enum需要符合Moya的TargetType协议。 然后将此文件添加到XCode项目。 我决定将其添加到名为“ Stubbed Responses”的文件夹中,您可以在其中检查Github存储库。 现在,您可以指示PlacesApi使用此文件的内容来创建sampleData方法的返回: 您可以通过在构造函数中传递以下行为来指示MoyaProvider使用存根响应,而不是执行实际的网络请求: let provider = MoyaProvider(stubClosure: MoyaProvider.immediatelyStub) 存根响应使我们能够实现上述第一个测试用例,从而确保应用程序将为预期的JSON响应创建有效的模型实例。 现在我们需要一个数据结构,该结构允许我们在存根响应(用于测试)和实际实现之间进行切换。 Moya官方文档中描述的包装适配器模式将非常适合此操作。 我们的包装器结构将称为PlacesService : 现在,第一个测试用例的实现非常简单。 Moya还提供了终结点关闭支持,我们可以使用它来模拟网络故障。 首先,我们在PlacesApi文件中声明此关闭: 然后,我们只需要将此方法传递给MoyaProvider构造函数即可: 现在,我们可以将所有内容粘合在一个测试用例中: 预期会传递相同的错误 经过一些工作,我们现在有了一个使用Foursquare API提取附近地点的类,以及另一个可以获取用户位置的类。 […]

斯威夫特-封闭第2部分

Merhabalar👋封闭部分-2 ilekaldığımızyerden devam ederek,捕获值,尾随,逃逸ve自动关闭函数konularınagözatacağız。 哈迪(Hadi)Başlayalım。 👊 捕捉价值 捕获işlemidıştakibloğaaitdeğişkenlerinveyadıştakifonksiyonun parametrelerininkullanılmasınaolanaksağlayanbir derleyici optimizasyonişlemidir。 我们是一家出版物,创建有关iOS开发的帖子。如果您喜欢它并想加入我们,请填写表格! tinyurl.com/jointowhoknows 闭包– Swift编程语言(Swift 4.2) 注意如果您不熟悉捕获的概念,请不要担心。 下面在捕获中详细说明… docs.swift.org Swift 3中的转义和不转义闭包-Swift未装箱 函数和闭包是Swift中的一流对象:您可以存储它们,并将它们作为参数传递给函数,然后… swiftunboxed.com 尾随闭包语法–免费的Swift黑客教程 通过这些免费教程学习iOS的Swift编码 www.hackingwithswift.com

iOS NotificationCenter以更好的方式

应用程序开发中的常见模式是通知( NSNotification和NotificationCenter )。 通过通知,您可以将消息广播到多个侦听器。 在许多情况下这可能很有用。 一个常见的示例是,如果您有许多UIViewControllers都需要在模型更改时进行更新。 但是,我觉得使用NotificationCenter的标准方法是容易出错,复杂且冗长。 我主要使用另一种方法,您可以在其中创建自己的NotificationCenter版本。 首先,以NotificationCenter的正常使用为例: 扩展Notification.Name { 静态让didUpdateCar = Notification.Name(“ didUpdateCar”) 静态让didReceiveData = Notification.Name(“ didReceiveData”) } 类MyViewController:UIViewController { 覆盖func viewDidLoad(_动画:布尔){ super.viewDidLoad(动画) setupNotifications() } 私人功能setupNotifications(){ NotificationCenter.default.addObserver(自身,选择器:#selector(didUpdateCar(_ :)),名称:.didUpdateCar,对象:无) NotificationCenter.default.addObserver(自己,选择器:#selector(didReceiveData(_ :)),名称:.didReceiveData,对象:无) // …一长串清单 } deinit { NotificationCEnter.default.removeObserver(自己) } @objc私人函数didReceiveData(_通知:NSNotification){ //如果您在发送方更改了userInfo,则此操作无提示。 崩溃喜欢? 如果让数据= notification.userInfo为? [String:Int] { 用于数据{中的(name,ageInYears) print(“ \(名称)是\(ageInYears)岁。”) } } } } 类AnotherViewController:UIViewController { […]

带有`default`参数值的Swift协议

在一个非常常见的情况下,您有一个类 ,其中包含带有默认参数值的方法,并且您要对其进行测试。 Baz类{ func foo(bar:BarType,camp:CampType = CampType())->字符串{ 返回“世界” } } 首先编写协议,以便可以为类实现模拟,如下所示: 协议BazProtocol { func foo(bar:BarType,camp:CampType)->字符串 } 和模拟 : struct BazMock:BazProtocol { func foo(bar:BarType,camp:CampType)->字符串{ 返回“” } } 您希望模拟共享默认值,因此首先要在协议定义中设置默认值,最后得到类似这样的内容。 协议BazProtocol { func foo(bar:BarType,camp:CampType =“ Hello”)->字符串 } 但是您得到以下错误: default argument not permitted in a protocol method 有一种方法可以解决该限制。 扩展程序可以解救! 我们不会在Baz或BazMock上定义默认参数,但将使用协议扩展名 ,这是将定义默认值的唯一位置。 这样,同一协议的两个实现都具有相同的默认值。 扩展名BazProtocol { func foo( bar:BarType, camp:CampType = […]

扩展,私有和文件私有

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

Swift中的总编程

编辑:在这个主题上,我接受了Corecursive播客的采访。 您可以在这里找到播客插曲,以及大量其他采访https://corecursive.com/007-total-programming-using-swift-with-andre-videla Swift是一种非常好的语言,因为它试图使程序员从一开始就做正确的事情。 它鼓励的好处之一就是整体性。 总计多少? 总体程序是一种不会卡住,崩溃或陷入无限循环的程序。 它始终会在有限的时间内正确终止。 如果您的程序是完整程序且类型正确,则不会出现程序崩溃或卡住的情况¹。 程序有多种可能是不完全的。 这里有一些例子: 由于死锁或无限循环而陷入困境 边缘情况不予处理,将使程序崩溃 输入格式错误会使程序处于损坏状态 因此,总体上体现了“打字正确的程序不会出错”的短语²。 此属性在日常编程中非常有用,因为它可以减轻(但不能消除)对测试的需求,可以增加对代码的信心,并可以将代码库视为可信任的小块。 大多数正在使用的程序都不是完整的,例如,大多数程序旨在永久运行(Web服务器,移动应用程序,恶魔)。 但是,即使整个程序不是全部,将部分内容汇总也是很有用的。 尽管我将讨论“全部程序”,但实际上它们将是“全部功能”,因此我将可互换地使用两个词。 在这篇文章中,我将介绍空指针和未检查的异常如何针对整体性工作,然后,我将展示Swift如何通过解决这两个问题来鼓励整体性。 之后,我们将看到如何使用!默默地打破Swift的承诺! 运算符在不同的上下文中,并给出一些如何避免编写简单安全代码的示例! 。 尽管总体主题与非终止有着深深的联系,但我不会谈论它。 (注1:这一切都很好,但是Swift绝对不会检查您的程序是否完整。它只是鼓励几乎偶然地使程序完整的做法。Swift不检查整体性有很多原因,但最引人注目的是从数学上讲这是不可能的。 实际上,检查整体性意味着检查程序将始终终止(无无限循环),并终止于“良好”状态(无崩溃)。 终止问题通常被称为“停止问题”,该问题已被推广,并被艾伦·图灵(Alan Turing)使用其图灵机证明无法解决。 现有的编程语言具有有限的终止检查形式,例如Idris或Agda,但是给定了任意程序,他们无法决定它是否终止。 因此,他们将无法判断该程序是否完整。) (脚注2:此短语的原始来源 来自Milner的 这篇论文 。此声明的上下文是该特定类型系统存在健全性证明,因此,任何类型良好的表达都是声音。) 空引用在低级语言中找到其起源,程序员在该语言中操纵指向内存³中值的指针。 这种语言大量使用指针来访问内存中的地址,这些地址保存了程序中使用的所有数据结构。 例如,在链接列表中,通常将每个节点表示为一对指针:指向当前保存的值的指针和指向列表中下一个节点的指针。 此外,这也使得在列表末尾添加元素变得更加麻烦,因为您将不得不创建一个中间节点,将最后一个节点的值放在新的中间节点中,并使最后一个节点的前任指向新的中间节点,用新值替换最后一个节点中的值,使新的中间节点指向最后一个节点。 实现最后一个元素的另一种方法是使最后一个指针“悬空”而不指向任何东西。 例如,它可以指向未在内存中初始化的特殊保留值(例如0)。 由于所有这些“悬挂”指针都是相同的,因此我们可以轻松地对其进行比较。 因为我们经常使用此类指针,所以我们给它指定了一个名称,并将其称为null 。 现在,我们可以通过简单地将最终空指针替换为指向新的最后一个元素的指针,并将最后一个元素的尾部指针设置为null来在列表的末尾添加元素。 这使我们的LinkedList API更简单,更优雅,但代价是安全。 实际上,取消引用这样的指针通常会导致程序崩溃,因为您正在访问未初始化的内存。 空引用继承给其他编程语言(如Java,C#和其他语言),以便以与C完全相同的方式表示诸如链表之类的数据结构。在这些语言中,指针不再是一等公民,但我们仍然可以拥有NullPointerException或尝试使用引用而没有意识到它为null NullReferenceException 。 (注3:空指针被Tony Hoare称为“十亿美元的错误”,他于1965年在Algol W中引入了空引用。我鼓励您在 https://www.infoq 上听听他关于空引用的论述 。 […]

如何不急于MVVM实现

假设您有一个小项目,过去仅在两天内就交付了新功能。 然后,您的项目将变得更大。 交货日期变得不受控制,从2天到1周,然后是2周。 它使您发疯! 您一直在抱怨:一个好的产品应该没有那么复杂! 那正是我所面对的,对我而言确实是一个糟糕的时刻。 现在,在该领域工作了几年之后,与许多优秀的工程师合作,我意识到产品设计并没有真正使代码变得如此复杂。 是我让事情变得如此复杂。 我们可能有编写意粉代码的经验,这严重损害了我们项目的性能,问题是如何解决它? 好的架构模式可能会有所帮助。 在本文中,我们将讨论一种好的架构:Model-View-ViewModel(MVVM)。 MVVM是一种流行的iOS体系结构,其重点是将用户界面的开发与业务逻辑的开发分开。 术语“好的架构”听起来可能太抽象了。 也不知道从哪里开始。 这里有个提示:我们可以将重点放在如何提高代码的可测试性上,而不必关注体系结构的定义。 有太多的软件架构,例如MVC,MVP,MVVM,VIPER。很明显,我们可能无法掌握所有这些架构。 但是,我们仍然可以牢记一条简单的规则:无论我们决定使用哪种架构,最终目标都是使测试变得更简单。 使用这种方法,我们在编写代码之前就开始思考。 我们强调如何直观地区分责任。 而且,按照这种思维方式,体系结构的设计似乎清晰合理,我们不再局限于琐碎的细节 TL; DR 在本文中,您将学习: 我们选择MVVM而非Apple MVC的原因 如何调整MVVM以设计更清晰的架构 如何基于MVVM编写一个简单的实际应用程序 您不会看到: MVVM,VIPER,Clean等之间的比较 解决所有问题的灵丹妙药 所有这些体系结构都有优点和缺点,但是它们都旨在使代码更简单明了。 因此,我们决定专注于为什么我们选择MVVM而不是MVC, 以及我们如何从MVC转向MVVM。 如果您对MVVM的缺点感兴趣,请参考本文末尾的讨论。 因此,让我们开始吧! 苹果MVC MVC(模型-视图-控制器)是Apple推荐的体系结构模式。 定义可以在这里找到。 MVC中对象之间的交互如下图所示: ViewController包含视图并拥有模型。 问题是我们曾经在ViewController中编写控制器代码以及视图代码。 它使ViewController过于复杂。 这就是为什么我们称其为Massive View Controller。 在为ViewController编写测试时,您需要模拟视图及其生命周期。 但是很难嘲笑观点。 而且,实际上,我们只想测试控制器逻辑就不想模拟视图。 所有这些使编写测试变得如此复杂。 因此,MVVM随时可以挽救。 MVVM —模型—视图— ViewModel MVVM由John Gossman在2005年提出。MVVM的主要目的是将数据状态从View移到ViewModel。 […]