Tag: 闭包

Swift 3中的闭包是什么? (第3部分)

继续第1部分,第2部分,这篇文章将是有关Closures的最后一篇,我们都可以肯定,它可以写成一整本书,只讨论Closures,所以我几乎没有触及任何表面。 这次我要谈的是: 速记参数名称 尾随闭包 速记参数名称 迭代数组的一种方法是使用forEach方法,在以下示例中,该方法将打印其内容: 闭包具有使我们简化代码的功能,而不必通过参数访问其值,而可以使用简写参数名称来访问它们: 您可能会注意到,我们省略了参数名称number甚至省略了关键字in ,并且我们正在通过名称$0访问闭包提供的值,以便减少代码并专注于代码中最重要的部分。 因此,即使闭包有更多的参数,速记名称也将被分配为$0 , $1 , $2 ,以此类推。 尾随闭包 假设我们有一个名为findInteger的函数(不用担心该函数的源代码在结尾),它将使用Integer数组根据条件搜索元素: 因此,在上面的代码中,我们希望获得第一个满足关闭条件的数字,即数字服务器。 我们可以看到我们在第二个参数上收到一个闭包表达式,但是有时像在这种情况下那样,表达式变长了,相反,我们可以这样做: 区别在于,首先我们不需要在函数调用中使用参数标签closure 。 其次,闭包表达式位于函数调用的括号之后,但它仍然是函数的参数。 这种简化方式称为尾随闭合。 让我们来看另一个例子。 这次,我们在Integer的扩展结构中使用了一种称为forEach (末尾的源代码)的方法,该方法将允许我们迭代数字上的数字,如下所示: 该代码本身具有解释性,但是关闭时间较长。 让我们应用一些尾随闭包 。 因此,在这里作为最后一个示例( findInteger function ),我们没有放置称为closure的参数标签,也没有包含括号。 如果闭包表达式是forEach方法中唯一的参数,那么我们也可以消除函数的调用括号。 当闭包表达式很长时, 尾随的闭包可以解脱 。 正如我提到的,示例中使用的方法的源代码: 如果您觉得该文章有用,请帮助我建议单击绿色的心形轮廓图标,以便我可以继续创建更多文章,非常感谢! 我要亲自感谢Bob和Victor激励我与我们的iOS社区分享我的Swift故事。 感谢您阅读我!

我讨厌我爱你:了解关闭和完成

封闭是Swift的一个很棒的小功能,我绝对讨厌。 它们提供了许多好处,当我第一次以正式形式遇到它们时,就被它们让一个类遍历另一个函数的范围来获取和设置我从未见过的变量的能力所震惊。 理论上闭包是如何工作的: 在我自己实施它们之后,我很快意识到它们确实是可怕的生物,使我的生活更加艰难。 闭包在实践中如何工作: 但是,很多……我的意思是大量的练习,阅读和询问一百万个问题,我很快就开始理解它们的工作方式以及何时以及如何使用它们。 之后,我觉得也许是我最初想到它们的方式引起了我的困惑,所以我想用做晚饭的比喻来简单地详细解释它们。 一个简单的关闭函数说明: 现在,当我们调用函数时,就是魔术发生了! 我们从函数makeDinner()上的紫色箭头开始。 当我们调用此函数时,我们需要为其提供两个参数,第一个是一个字符串(我们选择“牛排”),第二个是一个函数。 我们赋予原始功能(makeDinner)的功能是choiceSides。 当我们的makeDinner()实现在调用完成函数时达到其代码中的要点时,我们实际上停止了执行并开始运行传入的函数。 有一些方法可以运行makeDinner()的其余部分,而无需等待第二个完成,但是我没有在此处实现它以保持简单(好像)。 ChooseSides()函数的实质无所谓,只是知道它以字符串作为自己的参数,这是由makeDinner()提供的,当我们在类实例anthony上首次调用它时,我们直接将其提供给makeDinner()。 choiceSides()的结果是一个字符串,该字符串冒泡返回并进入makeDinner,并替换makeDinner()首次调用chooseSides()的位置(在我们打印的字符串的第二个插值处)。 如果这一切看起来都是令人费解的,我常常想知道我这样做时是否没有违反自然法则,但是直到现在仍然有效。 再往前走,我们可以直接从choiceSides()中提取代码,然后将其直接用作makeDinner()作为封闭函数,而不用传入choiceSides()作为参数。 查看上面代码的下半部分,看看原始方法和闭包函数方法都可以打印出相同的内容!

开始Swift编程第15部分-具有泛型和闭包的枚举

在上一篇文章中,我们讨论了错误处理。 开始进行Swift编程第14部分-错误处理 在上一篇文章中,我们讨论了泛型。 medium.com 我们介绍了有关如何创建自己的错误并在代码中使用它们而不只是崩溃的基础知识。 如果您有兴趣知道,我只剩下5个主题,然后向您指出一些我最喜欢的资源,这些资源可以帮助我编写程序。 本文将简短,但是它将结合一些我们已经学到的概念,并可能使您考虑如何以新的方式编写代码。 以前,当我们谈论枚举时,我告诉过您,它将为您提供选择的选项,而我们只限于那些选项。 我们可以在枚举案例中使用关联的值来定义使用枚举时将实例化的类型。 现在,我告诉您有关完全使用闭包,枚举和泛型的信息。 这是我从纳塔莎机器人那里学到的一个很酷的技巧,我在自己的代码中使用了很多。

快速,更优雅的代码:Typealias

您是否在使用长签名功能时遇到麻烦? 您认为重命名某些类型是个好主意吗? 好吧……只是看看 typealias 。 什么是Typealias? 我第一次发现有一种叫做“别名”的东西,对我来说有点奇怪,即使知道它的用途后,在我看来,使用它也没有“好”的意义。 到目前为止,我是它的粉丝! 在开始使用Swift typealias之前,我想指出的是,别名并不是 Swift编程语言的专有术语,实际上它是一个计算术语,您可以在许多其他古老和现代的语言中找到“别名”的逻辑(例如作为Swift)编程语言… Typealias是现有类型的命名别名,这意味着通过使用它,您将能够命名类型,以使程序更方便。 请记住,typealias 不是新类型,它只是现有类型的名称,您可以将其视为类型的替代名称(它可能是“快捷方式”,您将很快阅读)。 如何实现typealias? 简单来说,您可以将typealias实现为: typealias yourCustomName =现有类型 而这一切! 让我们开始做一些非常简单的代码: 实施: typealias Strings = [String] 可让您声明字符串数组( [String] )类型的变量(例如instance),如下所示: var strs: Strings? 现在strs将是[String]类型的变量。 非常有趣! 老实说,对我来说我不这么认为。 如果您想到的是“到目前为止,它是没有用的”,我会同意agree。 毫无疑问,为这种情况创建类型别名在某些情况下将其声明为var strs: [String]?并不是那么有用var strs: [String]? 读起来会更好。。。让它平静下来,让我们尝试另一种方法:将字符串字典的类型别名声明为键,将整数声明为值: typealias CustomDict =字典 在声明字典的泛型参数的具体类型( )时,应该节省一些“精力”,就像“双向2合1保存”! 但是,仍然不是使用typealias的充分理由,对吗? 这导致: 为什么要使用typealias? 实际上,通常在使用非平凡的应用程序时,它应该具有自己的管理器来处理指定功能的任务,例如通过网络连接发送和接收数据,获取设备照片(访问系统资源),从磁盘写入数据或从磁盘读取数据等等。因此,实现这些管理器可能需要为其方法使用“相当长”的签名。 让我们更进一步,为更多“真实世界”案例编写一些代码: 例: 为了使其更简单,我将重点介绍方法的签名,而不管它们的实际内部实现是什么(管理者目的)。 考虑我们有包含foo […]

完成处理程序:Swift

完成其他任务时执行。 介绍: 当我开始学习Swift时,我非常困惑一些概念完成处理程序就是其中之一。 在本文中,我将解释什么是完成处理程序及其工作方式以及为什么需要它。 在学习完成处理程序之前需要了解什么: 为了清楚地了解完成处理程序,我们需要了解闭包的基础,练习闭包,关于同步和异步功能的一点点知识。 您可以在这里聊天我发表的有关闭包的文章。 为什么我们需要完成处理程序: 在函数中,如果我们需要完成另一个任务之后再执行任何任务,而不是如何实现它。就像我们在完成下载后将更新UI那样,如何实现它? 换句话说,我们如何进行有序执行? 所有这些类型的问题解决了完成处理的概念。 制作完成处理程序: 创建一个完成处理程序闭包,然后将其传递给函数。 在这里,我们创建一个完成处理程序闭包,其类型为()→Void。现在,我们将创建一个可以使用此闭包的函数.. 在这里,我们创建一个函数,该函数带有()→Void类型的参数。现在通过调用像这样的函数来实现此功能。 因此,必须先执行takeCompletehandler主体语句,而不是执行编译处理程序。 控制台将像。 从函数主体 从完成处理程序开始! 让我们举另一个例子: 让我们做一个从服务器下载数据,并在完成下载后给用户通知的功能。 首先创建下载功能。 下载完成后,此函数可以使用一个闭包和一个bool参数。完成处理程序参数取真值并发出通知。现在,让create和完成处理程序闭包将采用bool值,但不返回任何内容…… 让我们实现功能 因此,它应该打印从服务器下载的数据..比打印“完全下载数据”要大100倍 //打印此 从sarver 下载数据…从sarver 下载数据…从sarver 下载数据…从sarver 下载数据 …从sarver 下载数据… …… 完整的下载数据 直接将Closure作为完成处理程序传递: 我们知道我们可以直接在函数参数上写闭包,所以让我们实现这个.. 这也打印相同,完成处理程序将在下载完成后执行..并给出通知… 短手 我们也可以这样写得很短: 在这里,我们不使用参数,而是使用swift默认参数。 现在,如果我们使用Trilling闭包,我们也可以像这样使用 因此,最后我们很清楚,抱怨处理程序无非就是在函数中传递闭包,并在其他操作完成后使其执行。 通过完成处理程序传递数据: 我们可以通过完成处理程序传递数据。 首先创建一个可以接受类型([String])→无效的函数 让我们实现这个 现在,控制台应该比完成打印处理程序数组打印“做一些工作”十倍。 做一些工作 做一些工作 做一些工作 做一些工作 …… …… // […]

从封装到协议扩展

假设我们要在Swift中定义一个简单的服务类,如果某些输入为正,则只输出一些输出。 (哇:要求跨度少于2行!) 对象封装 简单地说-容易完成吗? 是的,如果我们不在乎客户端的可扩展性: 使用这种方法,客户端类可以简单地实例化服务,并将doSomething工作委托给它。 非常简单(这很好),但是非常令人讨厌的是,当服务实例本身正在执行工作时,客户端无法干预要执行的输入数据和输出操作。 继承-不错的尝试! 不,继承并不总是我们的敌人。 它确实有(两个?)有效的用例。 但是恕我直言,这不是我们最好的朋友(即使代码确实更短!): 通过仅覆盖需要的内容,客户端可以将实现注入所需的位置。 每当定义时,服务将调用客户端替代而不是其自身的实现。 而且一切都会很顺利,例如,客户端现在不能是自定义的NSView (或UIView ),因为在这种情况下,有必要从所需的Cocoa基类而不是我们的服务中继承它…… 功能编程 哦! 我们正在变得现代化,是吗? 尽管如此,对于Swift而言,我也不认为这也是服务开发人员应该遵循的最佳方法-仅仅是因为这将(可能)需要在客户端开发人员级别上过多的基础设施意识。 确实,我们服务的用户需要执行一些“技巧”(例如,如果要在该处使用客户端状态,则捕获弱者或无主的 自我 ),以确保当他们将自定义闭包传递给我们时,不会在应用程序中引入内存泄漏: 代表和协议扩展 现在我们在说话! 我们最终将有一个真正的解决方案。 不需要继承,也不需要客户端开发人员的ARC知识! 我们只需要: 具有可选扩展名的服务委托协议,以提供我们要使用纯Swift公开的默认实现(即,没有@objc可选成员); 在服务中托管此类委托对象的弱实例或无主实例(尽管要求客户端类型为类,但无需我们的客户端开发人员处理内存管理问题); 并在适用时最终调用委托的(属性和)方法: 一体 最后,让我们看一看适用于我们所有类型客户的服务解决方案:如果喜欢继承,则接受; 否则,人们可以使用函数式编程并传递(设计良好)闭包; 或者,他们可以仅仅依靠(弱)聚集的代表来完成工作;或者 当然,所有这些都是为了防止默认情况下首先出现以下问题: 现在轮到你了。 您不需要上面的(我承认,很丑)多合一解决方案,但是至少您现在可以根据自己项目的需要对其进行调整。 无论如何,我想补充一点,我通常发现它足以支持继承和具有(部分或全部)默认实现的委托,但是有时功能样式也可以很好地工作(当您不希望客户需要在转义它们将通过的闭包)。

Swift4 11日关闭(2)

尾随闭包 如果需要将很长的闭包表达式作为最后一个参数传递给函式,使用尾随闭包来增强函式的初始化性。尾随闭包是写在小括号后面的闭包表达式,函式支持将闭包作为最后一个参数做呼叫 func函式名称((内部参数名:()->()){ 内部执行程序 } //不使用尾随闭包时呼叫功能 函式名称({ 闭包内的程式 }) //闭包型别为:()->()没有参数也没有回传值,可以看到闭包是作为参数放在()里//使用尾随闭包时呼叫功能 函式名称(){ 闭包内的程式 } //如果函式只有闭包这一个参数,可以省略() 函式名称{ 闭包内的程式 } 捕获值 闭包可以在其定义的中间中捕获常数或变数,即使定义这些常数或变数的原使用区域已不在,闭包仍可以在闭包函式体内使用或修改这些值 Swift中,可捕获值最简单的形式是巢状函数,也就是定义在其他函式中的函式。巢状函式可以捕获并访问外部函式内部所有的参数及其锁定亦得常数及变数,,即使巢状函数已回传,导致这些常数或变数的做用已已,闭包仍可对这些已捕获的值做操作。 巢状函式的内部存取了runningTotal及金额两个变数,是因为他从外部函式捕获了这两个变数的参考,而此捕获参考可以runningTotal及金额呼叫完makeIncrementer完后不会消失,并在下一呼叫增量时,runningTotal仍存在 呼叫这个函式的方法: 再上面的呼叫中,可以验证下一呼叫功能时,runningTotal仍存在的事实,因此再另外呼叫一次增量5及增量10,重新验证此表达式 闭包是参考型别 上面的例子中,incrementTen及crementFive都是常数,但这些常数指向的闭包仍可以增加其捕获的变数值 逃逸闭包 当我们宣告一个函式的参数为闭包时,可以再参数的类型前面写@时,我们可以说这个闭包逃逸了,而它可以在函式回传后被调用。逃避表示允许闭包逃逸。 闭包可以逃逸的一种方式为:被保存定义于函数外的变数里。 newFunction会接收一个闭包当做参数,并添加到我们在函数外宣告的Array中,而我们让闭包逃逸意味着要在闭包中用self 自动闭包 是一种自动被建立的闭包,用于包装后传递给函式作为参数的表达式,这种闭包没有参数,当被使用时,会回传被包装在里面表达式的值。简单来说,自动闭包是一种简化后的语法,让我们可以用普通的表达式代替显式的闭包,靴子省略了大括号{}。 自动闭包可以让你延迟求值,我们可以控制程序何时才进行求值: 我们删除了aArray中的第一个元素,但在还没调用removeArray时,aArray的数量仍是6个,也就是延迟求值,如果闭包永远不被调用,那闭包里的表达式就永远不会求值 ・ Swift4 Day-01基本语法・ Swift4 Day-02选项及无 ・ Swift4 Day-03集合类型—数组 ・ Swift4 Day-04集合类型—设置 ・ Swift4 Day-05集合类型—字典 ・ Swift4 Day-06控制流程(1) ・ Swift4 Day-07控制流(2) ・ Swift4 […]

Swift4第10天关闭(1)

闭锁是功能独立的区块链,可以在程序之间被传递和使用。像是之前提到的嵌套状函式(Nested Function),就是一种闭包。 闭包有三种表示方式: ・函式就是一种有名字的闭包・巢状函式是一种有名字且被包在其他函式中的闭包·闭包表达式是使用简洁的语法来描述一种没有名字的闭包,可以在程式之间传递及使用。 Swift提供了一种叫做sorted的方法,根据我们提供的排序闭包,将已知类型数组的值进行排序,再次排序完成,sorted好的。我们可以用sorted()去使用sorted的功能,再没有特别设定之下,sorted的功能就是将Array中的数值从小到大分开,字串则是照字母顺序: 如果我们想要让Array由大到小排序(字串则反之),可以透过定义功能,并使用sorted(by:): 闭包表达式(Closure Expression)是一种用简洁语法建立匿名函式的方式。同时提共了优化语法,可以使程式码变得更好读。 {(参数)->返回值类型别 内部程式 } 从上面的程式看到,与一般函式相同的是闭包同样有一个大括号将程式包起来,不过省略了名称,包着参数的小括号放到大括号里面,然后返回型别,再接一个在执行内部程式中 在这边我们不是建立一个函数,而是将这些参数以及回传值等等包在一个大括号中,最后再用 从总体而言型别 因为排序闭包是实际参数传递给函数,所以Swift可以判断他的形式参数类型及回传型别 单表达式闭包隐式回传 单行表达式闭包可以通过隐藏隐藏return来隐式回传单行表达式的结果 参数名称缩写 Swift为闭包提供参数名称缩写功能,能直接以$ 0,$ 1,$ 2这种方式来依序呼叫闭包的参数。缩写的型别会透过函式型别自动预设,所以在也会同被省略 运算子函式 Swift的String定义了关于大于符号等特定符号的实现,与sorted所需要的相符合 ・ Swift4 Day-01基本语法・ Swift4 Day-02选项及无 ・ Swift4 Day-03集合类型—数组 ・ Swift4 Day-04集合类型—设置 ・ Swift4 Day-05集合类型—字典 ・ Swift4 Day-06控制流程(1) ・ Swift4 Day-07控制流(2) ・ Swift4 Day-08功能(1) ・ Swift4 Day-09功能(2) 电子邮件:albert.Ch1994@gmail.com