在本文中,我们将给您介绍关于swift柯里化的详细内容,并且为您解答柯里化bind的相关问题,此外,我们还将为您提供关于9:偏函数,高级函数,匿名函数,参数推断,闭包,柯里化,控制抽象、Es6中双箭头
在本文中,我们将给您介绍关于swift 柯里化的详细内容,并且为您解答柯里化 bind的相关问题,此外,我们还将为您提供关于9: 偏函数,高级函数,匿名函数,参数推断,闭包,柯里化,控制抽象、Es6中双箭头函数的含义(柯里化)、iOS Swift 应用程序随机 EXC_BAD_ACCESS 崩溃:swift_bridgeObjectRetain swift_retain swift::RefCounts
- swift 柯里化(柯里化 bind)
- 9: 偏函数,高级函数,匿名函数,参数推断,闭包,柯里化,控制抽象
- Es6中双箭头函数的含义(柯里化)
- iOS Swift 应用程序随机 EXC_BAD_ACCESS 崩溃:swift_bridgeObjectRetain swift_retain swift::RefCounts
- Java Lambda级联表达式(柯里化)与Stream流操作
swift 柯里化(柯里化 bind)
如何将一个接受多参数的函数变换为一系列只接受单个参数的函数,这个过程被称为柯里化 (Currying)
参照:objc.io|objc 中国
/**
1.add0 和 add的例子向我们展示了如何将一个接受多参数的函数变换为一系列只接受单个参数的函数,这个过程被称为柯里化 (Currying),它得名于逻辑学家 Haskell Curry;我们将 add 称为 add0 的柯里化版本
2.首先向函数传递第一个参数 1,然后将返回的函数应用到第二个参数 2
3.我们甚至可以省略 addTheSome函数的一个 return 关键字和返回类型中的某些括号
addTheSome后写为下面这样:函数中的箭头 ->向右结合。这也就是说,你可以将 A -> B -> C理解为 A -> (B -> C)
*/
func add0(x: Int,_ y: Int) ->Int {
return x + y }
func add(x:Int)-> (Int ->Int){
return{y inreturn x + y}
}
func addTheSome(x:Int)->Int -> Int{
return { y in x + y }
}
add(1)(3)
addTheSome(1)(3)
柯里化 应用封装Core Image
//封装Core Image
// Filter 类型定义为一个函数,该函数接受一个图像作为参数并返回一个新的图像
typealias Filter = CIImage -> CIImage
/**
blur 函数返回一个新函数,新函数接受一个 CIImage类型的参数 image,并返回一个新图像(return lter .outputimage)。
因此,blur 函数的返回值满足我们之前定义 的 CIImage -> CIImage,也就是 Filter类型
*/
func blur(radius: Double) -> Filter {
return {image in
let parameters = [ kCIInpuTradiusKey: radius,kCIInputimageKey: image]
guard let lter =CIFilter(name: "CIGaussianBlur",withInputParameters:parameters)else {fatalError()}
guard let outputimage = lter.outputimageelse {fatalError()}
return outputimage
}
}
定义一个生成固定颜色的滤镜
颜色生成 滤镜不检查输入图像。因此,我们不需要给返回函数中的图像参数命名。取而代之,我们使用
一个匿名参数 _ 来强调滤镜的输入图像参数是被忽略的
*/
func colorGenerator(color: NSColor) -> Filter {
return { _ in
guard let c = CIColor(color: color)else { fatalError () }
let parameters = [kCIInputColorKey: c]
guard let lter = CIFilter (name:"CIConstantColorGenerator",
withInputParameters: parameters) else { fatalError() }
guard let outputimage = lter.outputimageelse { fatalError() }
return outputimage
}
}
定义合成滤镜
将输出图像剪裁为与输入图像一致的尺寸严格来说,这不是必须的,而完全取决
于我们希望滤镜如何工作
*/
func compositeSourceOver(overlay: CIImage) -> Filter {
return { image in
let parameters = [ kCIInputBackgroundImageKey: image,kCIInputimageKey: overlay
]
guard let lter =CIFilter (name: "CISourceOverCompositing",
withInputParameters: parameters) else {fatalError() }
guard let outputimage = lter.outputimageelse { fatalError() }
let cropRect = image.extent
return outputimage.imageByCroppingToRect(cropRect)
}
}
结合两个滤镜来创建颜色叠层滤镜
返回了一个接受图像作为参数的函数。colorOverlay函数首先调用了 colorGenerator滤镜。
colorGenerator 滤镜需要一个 color作为参数,然后返回一个新的滤镜,因此代码片段
colorGenerator(color) 是 Filter 类型。而 Filter类型本身就是一个从 CIImage到 CIImage 的 函数;
因此我们可以向 colorGenerator(color)函数传递一个附加的 CIImage类型的参数,最终我们能够得到一个 CIImage类型的新叠层。这就是我们在定义 overlay的过程中所发生的全部 事情事,可以大致概括为 ——首先使用 colorGenerator函数创建一个滤镜,接着向这个滤镜传递一个 image 参数来创建新图像。与之类似,返回值 compositeSourceOver(overlay)(image)由一个通过 compositeSourceOver(overlay)函数构建 的滤镜和随即被作为参数的 image 组成
*/
func colorOverlay(color:NSColor)->Filter{
return { image in
let overlay = colorGenerator(color)(image)
return compositeSourceOver(overlay)(image)
}
}
// 到现在为止,我们已经定义了模糊滤镜和颜色叠层滤镜,可以把它们组合在一起使用:首先将
// 图像模糊,然后再覆盖上一层红色叠层
let url = NSURL(string:"http://www.objc.io/images/covers/16.jpg")!
let image = CIImage(contentsOfURL:url)!
// 链式地将两个滤镜应用到载入的图像上
let blurRadius = 5.0
let overlayColor = NSColor.redColor().colorWithAlphaComponent(0.2)
let blurredImage = blur(blurRadius)(image)
let overlaidImage =colorOverlay(overlayColor)(blurredImage)
// 复合函数
//将上面代码里两个调用滤镜的表达式简单合为一体:可读性差
let result = colorOverlay(overlayColor)(blur(blurRadius)(image))
// 定义一个用于组合滤镜的函数
composeFilters 函数接受两个 Filter类型的参数,并返回一个新定义的滤镜。
这个复合滤镜接 受一个 CIImage类型的图像参数,然后将该参数传递给
lter1,取得返回值之后再传递给lter2.可以使用复合函数来定义复合滤镜
*/
func composeFilters( lter1: Filter,_ lter2 : Filter ) -> Filter {
return { image in lter2 ( lter1 (image)) } }
let myFilter1 = composeFilters(blur(blurRadius),colorOverlay(overlayColor))
let result1 = myFilter1(image)
/// 为了让代码更具可读性,我们可以再进一步,为组合滤镜引入运算符。诚然,随意自定义运算
//符并不一定对提升代码可读性有帮助。不过,在图像处理库中,滤镜的组合是一个反复被讨论
//的问题,所以引入运算符极有意义
infix operator >>> {associativity left }
func >>> ( lter1 : Filter,lter2 : Filter ) -> Filter {
return { image in lter2 ( lter1 (image)) }
}
//与之前使用 composeFilters的方法相同,现在我们可以使用 >>>运算符达到目的:
//由于已经定义的运算符 >>>是左结合的 (left-associative),就像 Unix的管道一样,
//滤镜将以从左到右的顺序被应用到图像上
let myFilter2 = blur(blurRadius)>>> colorOverlay(overlayColor)
let result2 = myFilter2(image)
9: 偏函数,高级函数,匿名函数,参数推断,闭包,柯里化,控制抽象
第十三章 函数式编程-高级
13.1 偏函数(partial function)
13.1.1 提出一个需求,引出思考
给你一个集合 val list = List(1, 2, 3, 4, "abc"),请完成如下要求:
1、将集合 list 中的所有数字 +1,并返回一个新的集合。
2、要求忽略掉 非数字 的元素,即返回的 新的集合 形式为 (2, 3, 4, 5)。
13.1.2 解决方式-filter + map 返回新的集合
13.1.3 解决方式-模式匹配
两种方式的示例代码如下:
示例代码如下:
package com.atguigu.chapter13
/**
* 给你一个集合 val list = List(1, 2, 3, 4, "abc"),请完成如下要求:
* 1、将集合 list 中的所有数字 +1,并返回一个新的集合。
* 2、要求忽略掉 非数字 的元素,即返回的 新的集合 形式为 (2, 3, 4, 5)。
*/
object PartialFunDemo01 {
def main(args: Array[String]): Unit = {
// 思路1:filter + map 方式解决
// 虽然可以解决问题,但是麻烦。
val list = List(1, 2, 3, 4, "abc")
// 先过滤,再map
list.filter(f1)
println(list.filter(f1).map(f2).map(f3)) // List(2, 3, 4, 5)
// 思路2:模式匹配
// 小结:虽然使用模式匹配比较简单,但是不够完美。
val list2 = list.map(addOne2)
println(list2) // List(2, 3, 4, 5, ())
}
// 模式匹配
def addOne2(i: Any): Any = {
i match {
case x:Int => x + 1
case _ =>
}
}
// 将 List 转为 Any
def f1(n: Any): Boolean = {
n.isInstanceOf[Int]
}
// 将 Any 转为 Int [map]
def f2(n: Any): Int = {
n.asInstanceOf[Int]
}
def f3(n: Int): Int = {
n + 1
}
}
输出结果如下:
List(2, 3, 4, 5)
List(2, 3, 4, 5, ())
13.1.4 偏函数的基本介绍
13.1.5 偏函数的快速入门
示例代码如下:
package com.atguigu.chapter13
object PartialFunDemo02 {
def main(args: Array[String]): Unit = {
// 使用偏函数解决
val list = List(1, 2, 3, 4, "hello")
// 定义一个偏函数
// 1. PartialFunction[Any, Int] 表示偏函数接收的参数类型是 Any,返回的类型是 Int
// 2. isDefinedAt(x: Any) 如果返回 true,就会去调用 apply 构建对象实例,如果是 false,就过滤
// 3. apply 构造器,对传入的值 + 1,并返回(新的集合)
val addOne3 = new PartialFunction[Any, Int] {
def isDefinedAt(any: Any) = if (any.isInstanceOf[Int]) true else false
def apply(any: Any) = any.asInstanceOf[Int] + 1 // 将 any 显示转换成 Int
}
// 使用偏函数
// 说明:如果是使用偏函数,则不能使用 map,应该使用 collect
// 说明偏函数的执行流程
// 1. 遍历 list 集合的所有元素
// 2. 然后调用 val element = if(partialFun-isDefinedAt(list单个元素)) {partialFun-apply(list单个元素)}
// 3. 每得到一个符合要求的元素 element,放入到新的集合,最后返回
val list3 = list.collect(addOne3)
println(list3) // List(2, 3, 4, 5)
}
}
输出结果如下:
List(2, 3, 4, 5)
13.1.6 偏函数的小结
13.1.7 偏函数的简写形式
示例代码如下:
package com.atguigu.chapter13
/**
* 偏函数简化形式
*/
object PartialFunDemo03 {
def main(args: Array[String]): Unit = {
// 使用偏函数的简化形式解决
// 第一种简写形式:
def f2: PartialFunction[Any, Int] = {
case i: Int => i + 1 // case 语句可以自动转换为偏函数
case j: Double => (j * 2).toInt
}
val list2 = List(1, 2, 3, 4, 5.6, "hello").collect(f2)
println(list2) // List(2, 3, 4, 5, 11)
// 第二种简写形式:
val list3 = List(1, 2, 3, 4, "ABC").collect { case i: Int => i + 1 }
println(list3) // List(2, 3, 4, 5)
}
}
输出结果如下:
List(2, 3, 4, 5, 11)
List(2, 3, 4, 5)
13.2 作为参数的函数
1、基本介绍
2、快速入门案例
示例代码如下:
package com.atguigu.chapter13
object FunParameterDemo01 {
def main(args: Array[String]): Unit = {
def plus(x: Int) = 3 + x
val result1 = Array(1, 2, 3, 4).map(plus(_))
println(result1.mkString(",")) // (4,5,6,7)
// 1. 在 scala 中,函数也是有类型,比如 plus 就是 <function1>
println("puls的函数类型是" + (plus _))
}
}
输出结果如下:
4,5,6,7
puls的函数类型是<function1>
3、应用案例小结
13.3 匿名函数
1、基本介绍
2、快速入门案例
示例代码如下:
package com.atguigu.chapter13
object AnonymouseFunctionDemo01 {
def main(args: Array[String]): Unit = {
// 对匿名函数的说明
// 1. 不需要写 def 函数名
// 2. 不需要写返回类型,使用类型推导
// 3. = 变成 =>
// 4. 如果有多行,则使用 {} 包括
val triple = (x: Double) => 3 * x
println(triple) // <function1>
println(triple(3)) // 9.0
}
}
输出结果如下:
<function1>
9.0
3、练习题
请编写一个匿名函数,可以返回2个整数的和,并输出该匿名函数的类型。
示例代码如下:
val f1 = (n1: Int, n2: Int ) => {
println("匿名函数被调用")
n1 + n2
}
println("f1类型=" + f1) // f1类型=<function2>
println(f1(10, 30)) // 40
13.4 高阶函数(higher-order function)
1、基本介绍
能够接受函数作为参数的函数,叫做高阶函数 (higher-order function)。可使应用程序更加健壮。
2、高阶函数基本使用案例
扩展代码如下:
package com.atguigu.chapter13
object HigherOrderFunctionDemo01 {
def main(args: Array[String]): Unit = {
// test 就是一个高阶函数,它可以接收 f: Double => Double 和 f1: Double => Int
def test(f: Double => Double, f1: Double => Int, n1: Double) = {
f(f1(n1))
}
// sum 是接收一个 Double,返回一个 Double
def sum(d: Double): Double = {
d + d
}
def mod(d: Double): Int = {
d.toInt % 2
}
val res = test(sum, mod, 5.0)
println("res=" + res) // 2.0
}
}
输出结果如下:
res=2.0
3、高阶函数可以返回函数类型
示例代码如下:
package com.atguigu.chapter13
object HigherOrderFunctionDemo02 {
def main(args: Array[String]): Unit = {
// 说明
// 1. minusxy 是高阶函数,因为它返回匿名函数
// 2. 返回的匿名函数是 (y: Int) => x - y
// 3. 返回的匿名函数可以使用变量接收
def minusxy(x: Int) = {
(y: Int) => x - y // 匿名函数
}
// 分步执行
// f1 就是 (y: Int) => 3 - y
val f1 = minusxy(3)
println("f1的类型=" + f1)
println(f1(1)) // 2
println(f1(9)) // -6
// 也可以一步到位的调用(函数柯里化)
println(minusxy(4)(9)) // -5
}
}
输出结果如下:
f1的类型=<function1>
2
-6
-5
13.5 参数(类型)推断
1、基本介绍
2、应用案例
示例代码如下:
package com.atguigu.chapter13
object ParameterInferDemo01 {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4)
println(list.map((x: Int) => x + 1)) // (2,3,4,5)
println(list.map((x) => x + 1)) // (2,3,4,5) 参数类型是可以推断时,可以省略参数类型。
println(list.map(x => x + 1)) // (2,3,4,5) 当传入的函数,只有单个参数时,可以省去括号。
println(list.map(_ + 1)) // (2,3,4,5) 如果变量只在=>右边只出现一次,可以用_来代替。
println(list.reduce(f1)) // 10
println(list.reduce((n1: Int, n2: Int) => n1 + n2)) // 10
println(list.reduce((n1, n2) => n1 + n2)) // 10
println(list.reduce(_ + _)) // 10
}
def f1(n1: Int, n2: Int): Int = {
n1 + n2
}
}
输出结果如下:
List(2, 3, 4, 5)
List(2, 3, 4, 5)
List(2, 3, 4, 5)
List(2, 3, 4, 5)
10
10
10
10
3、应用案例小结
13.6 闭包(closure)
1、基本介绍
2、应用案例小结
3、闭包的最佳实践
示例代码如下:
package com.atguigu.chapter13
/**
* 请编写一个程序,具体要求如下:
* 编写一个函数 makeSuffix(suffix: String) 可以接收一个文件后缀名(比如.jpg),并返回一个闭包
* 调用闭包,可以传入一个文件名,如果该文件名没有指定的后缀(比如.jpg),则返回 文件名.jpg,如果已经有.jpg后缀,则返回原文件名。
* 要求使用闭包的方式完成。
* String.endsWith(xx)
*/
object ClosureDemo01 {
def main(args: Array[String]): Unit = {
// 使用并测试
val f = makeSuffix(".jpg")
println(f("dog.jpg")) // dog.jpg
println(f("cat")) // cat.jpg
}
// 自定义的函数
def makeSuffix(suffix: String) = {
// 返回一个匿名函数,该匿名函数会使用外部函数的suffix,那么该函数和suffix整体形成一个闭包。
(filename: String) => {
if (filename.endsWith(suffix)) {
filename
} else {
filename + suffix
}
}
}
}
输出结果如下:
dog.jpg
cat.jpg
4、闭包的好处
13.7 函数柯里化(curry)
1、基本介绍
2、函数柯里化快速入门案例
3、函数柯里化最佳实践
示例代码如下:
package com.atguigu.chapter13
/**
* 函数柯里化最佳实践
* 比较两个字符串在忽略大小写的情况下是否相等,注意,这里是两个任务:
* 全部转大写(或小写)
* 比较是否相等
* 针对这两个操作,我们用一个函数去处理的思想,其实也变成了两个函数处理的思想(柯里化)
*/
object CurryDemo02 {
def main(args: Array[String]): Unit = {
// 方式1:简单的方式,使用一个函数完成
def eq(s1: String)(s2: String): Boolean = {
s1.toLowerCase == s2.toLowerCase
}
println(eq("hello")("HELLO"))
// 方式2:使用稍微高级的用法(隐式类):形式为 str.方法()
def eq2(s1: String, s2: String): Boolean = {
s1.equals(s2)
}
// 隐式类:该隐式类扩展了String对象的功能
implicit class TestEq(s: String) {
// 体现了将比较字符串的事情,分解成两个任务完成:
// 任务1:checkEq 完转换大小写
// 任务2.:f函数完成比较任务
def checkEq(ss: String)(f: (String, String) => Boolean): Boolean = {
f(s.toLowerCase, ss.toLowerCase)
}
}
val str1 = "hello"
println(str1.checkEq("HeLLO")(eq2))
// 方式2的简化写法
str1.checkEq("HeLLO")((s1: String, s2: String) => { s1.equals(s2) })
str1.checkEq("HeLLO")((s1: String, s2: String) => s1.equals(s2)) // 代码块只有一行代码时。可以省略{}
str1.checkEq("HeLLO")((s1, s2) => s1.equals(s2)) // 参数类型是可以推断时,可以省略参数类型。
str1.checkEq("HeLLO")(_.equals(_)) // 如果变量只在=>右边只出现一次,可以用_来代替。
}
}
输出结果如下:
true
true
13.8 控制抽象函数
1、看一个需求
2、控制抽象基本介绍
3、快速入门案例
示例代码如下:
package com.atguigu.chapter13
object AbstractControlDemo01 {
def main(args: Array[String]): Unit = {
// myRunInThread 就是一个抽象控制函数,其参数是没有输入,也没有输出的函数 f1: () => Unit
def myRunInThread(f1: () => Unit) = {
new Thread {
override def run(): Unit = {
f1()
}
}.start()
}
myRunInThread {
() =>
println("干活咯!5秒完成...")
Thread.sleep(5000)
println("干完咯!")
}
// 简写形式
def myRunInThread2(f1: => Unit) = {
new Thread {
override def run(): Unit = {
f1
}
}.start()
}
// 对于没有输入,也没有返回值函数,可以简写成如下形式:
myRunInThread2 {
println("干活咯!5秒完成...~~~")
Thread.sleep(5000)
println("干完咯!~~~")
}
}
}
4、进阶用法:实现类似 while 的 mywhile 函数
示例代码如下:
package com.atguigu.chapter13
object AbstractControlDemo02 {
def main(args: Array[String]): Unit = {
var x = 10
while (x > 0) {
x -= 1
println("x=" + x)
}
// 说明:实现类似 while 的 mywhile 函数
// 1 函数名为 mywhile,实现了类似 while 循环的效果
// 2. condition: => Boolean 是一个没有输入值,返回 Boolean 类型函数
// 3. block: => Unit 没有输入值,也没有返回值的函数
def mywhile(condition: => Boolean)(block: => Unit): Unit = {
// 类似 while 循环,递归
if (condition) {
block // x=9 x=8 x=7 ...
mywhile(condition)(block)
}
}
x = 10
mywhile(x > 0) {
x -= 1
println("x=" + x)
}
}
}
输出结果如下:
x=9
x=8
x=7
x=6
x=5
x=4
x=3
x=2
x=1
x=0
-----
x=9
x=8
x=7
x=6
x=5
x=4
x=3
x=2
x=1
x=0
本文同步分享在 博客“SoWhat1412”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
Es6中双箭头函数的含义(柯里化)
const isType =(type: string) => (value: any) =>
typeof(value) === type;
what?
在了解双箭头函数之前可以先了解一下函数式编程中的一个概念:
柯里化:把一个多参数函数转化成一个嵌套的一元函数(只有一个参数的函数)的过程。
可见双箭头函数就是一个多参数函数的柯里化版本。
转化成JavaScript后:
const isType = function (type){
return function (value) {
return typeof(value) === type;
}
}
(这样看就有点闭包的意思了,也可以理解为把其中的每一步骤进行封装,保存每一步的结果,作为下一步开始的条件)
你也可以写成没有柯里化的函数也是可以的:
const isType = function (type,value){
return typeof(value) === type;
}
它的调用方法:
isType (“string”)
//返回一个函数:function (value) {return typeOf(value) === type;}isType (“string”)(“abc”
) //返回:trueconst type = isType("string"); type("abc");
//返回:true
Why?
那问题来了,为什么要柯里化呢?它有什么用?
可读性: isType (“string”)(“abc”)
可复用性 :重复使用const type = isType(“string”); 用来做其他判断type (“def”);
可维护性 :
const fn = (a,b) => a * b; //可修改成a+b
const isType =(fn)=> (type) => (value) =>fn(type,value);
console.log(isType (fn)(2)); //返回函数
console.log(isType (fn)(2)(3)); //6
const type = isType(fn)(2); console.log(type(4)); //8
How?
使用场景
日志:
const curry = (fn) => { if(typeof fn != ''function''){ throw Error(''NO function provided''); } return function curriedFn(...args){ if(args.length < fn.length){ return function(){ return curriedFn.apply(null,args.concat([].slice.call(arguments))); }; } return fn.apply(null,args); }; }; err("ERROR","Error At Stats.js","text1",22); err("ERROR","Error At Stats.js","text2",23); const error = curry(err)("ERROR")("Error At Stats.js"); error ("text1")(22); error ("text2")(23);
- 在数组内容中查找数字
const curry = (binaryFn) => {
return function (firstArg) {
return function (secondArg) {
return binaryFn(firstArg,secondArg);
};
};
};
let match = curry(function(expr, str) {
rerurn str.match(expr);
};
let hasNumber = match(/[0-9]+/);
let filter = curry(function(f,ary){
return ary.filter(f);
};
let findNumbersInArray = filter(hasNumber);
findNumbersInArray(["js","number1"]); //["number1"]
- 求数组的平方
let map = curry(function(f,ary){
return ary.map(f);
)};
let squareAll = map((x) => x*x);
squareAll([1,2,3]); //[1,4,9]
iOS Swift 应用程序随机 EXC_BAD_ACCESS 崩溃:swift_bridgeObjectRetain swift_retain swift::RefCounts
如何解决iOS Swift 应用程序随机 EXC_BAD_ACCESS 崩溃:swift_bridgeObjectRetain swift_retain swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1>
我不断收到来自随机用户的随机崩溃报告。不幸的是,我无法定期重现这一点。用户说崩溃是在 discussionViewController
中随机发生的。所有崩溃报告都有类似的内容:
0 libswiftCore.dylib 0x00000001a53face4 swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::incrementSlow(swift::RefCountBitsT<(swift::RefCountInlinedness)1>,unsigned int) + 60 (atomic:1003)
1 libswiftCore.dylib 0x00000001a53c59e0 swift_retain + 124 (RefCount.h:813)
2 libswiftCore.dylib 0x00000001a5401d60 swift_bridgeObjectRetain + 56 (SwiftObject.mm:585)
3 APPNAME 0x0000000102b59734 closure #1 in discussionViewController.fetchPostData() + 7916
这是完整的崩溃日志和崩溃的线程:
Hardware Model: iphone11,6
Process: APPNAME [11770]
Path: /private/var/containers/Bundle/Application/.../APPNAME.app/APPNAME
Identifier: ----
Version: 62 (62)
AppStoretools: 12E262
AppVariant: 1:iphone11,6:13
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: ---- [1824]
Date/Time: 2021-06-17 12:07:01.4346 +1000
Launch Time: 2021-06-17 12:06:56.4993 +1000
OS Version: iPhone OS 14.6 (18F72)
Release Type: User
Baseband Version: 3.04.01
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x8000000000000010 -> 0x0000000000000010 (possible pointer authentication failure)
VM Region Info: 0x10 is not in any region. Bytes before following region: 4339515376
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 102a7c000-102a94000 [ 96K] r-x/r-x SM=COW ...APPNAME.app/APPNAME
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL,Code 0xb
Terminating Process: exc handler [11770]
Triggered by Thread: 3
Thread 3 name:
Thread 3 Crashed:
0 libswiftCore.dylib 0x00000001a53face4 swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::incrementSlow(swift::RefCountBitsT<(swift::RefCountInlinedness)1>,unsigned int) + 60 (atomic:1003)
1 libswiftCore.dylib 0x00000001a53c59e0 swift_retain + 124 (RefCount.h:813)
2 libswiftCore.dylib 0x00000001a5401d60 swift_bridgeObjectRetain + 56 (SwiftObject.mm:585)
3 APPNAME 0x0000000102b59734 closure #1 in discussionViewController.fetchPostData() + 7916
4 APPNAME 0x0000000102ad09d4 thunk for @escaping @callee_guaranteed (@guaranteed Data?,@guaranteed NSURLResponse?,@guaranteed Error?) -> () + 132 (<compiler-generated>:0)
5 CFNetwork 0x00000001a1b0a3dc __40-[__NSURLSessionLocal taskForClassInfo:]_block_invoke + 540 (LocalSession.mm:687)
6 CFNetwork 0x00000001a1b1c768 __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 244 (LocalSessionTask.mm:584)
7 libdispatch.dylib 0x00000001a10d1a84 _dispatch_call_block_and_release + 32 (init.c:1466)
8 libdispatch.dylib 0x00000001a10d381c _dispatch_client_callout + 20 (object.m:559)
9 libdispatch.dylib 0x00000001a10db004 _dispatch_lane_serial_drain + 620 (inline_internal.h:2557)
10 libdispatch.dylib 0x00000001a10dbc34 _dispatch_lane_invoke + 456 (queue.c:3862)
11 libdispatch.dylib 0x00000001a10e64bc _dispatch_workloop_worker_thread + 764 (queue.c:6589)
12 libsystem_pthread.dylib 0x00000001ed04a7a4 0x1ed047000 + 14244
13 libsystem_pthread.dylib 0x00000001ed05174c 0x1ed047000 + 42828
我已验证 discussionViewController.fetchPostData()
不会强制解开任何可选选项,没有 try!
并且在任何地方都使用 [weak self]
和 self?
。该函数非常大,所以我很难缩小崩溃发生的范围。
Java Lambda级联表达式(柯里化)与Stream流操作
Java Lambda级联表达式
又称柯里化,把多个参数的函数转化为只有一个参数的多个函数级联的形式,目的是函数标准化。
Function<Integer, Function<Integer, Integer>> fun = x -> y -> x + y;
System.out.println(fun.apply(2).apply(3)); // 5
Stream流操作
创建
相关方法 | |
---|---|
集合 | Collenction.stream/paralleStream |
数组 | Array.stream、Stream.of(Array) |
数字Stream | IntStream/LongStream.range/rangeClosed |
Random.ints/longs/doubles | |
自己创建 | Stream.generate/iterate |
中间操作
相关方法的 | |
---|---|
无状态操作 | map/mapToXxx |
flatMap/flatMapToXxx | |
filter | |
peek | |
unordered | |
有状态操作 | distinct |
sorted | |
limit/skip |
终止操作
相关方法 | |
---|---|
非短路操作 | forEach/forEachOrderd |
collect/toArray | |
reduce | |
min/max/count | |
短路操作 | findFirst/findAny |
allMatch/anyMatch/noneMatch |
例子
String str = "my name is 007";
// 找出单词大于2的单词字母数
Stream.of(str.split(" "))
.filter(s -> s.length() > 2)
.map(s -> s.length())
.forEach(System.out::println); // 4 3
// 转换为一个一个字母进行输出
Stream.of(str.split(" "))
.flatMap(s -> s.chars().boxed())
.forEach(i -> System.out.println((char) i.intValue()));
关于swift 柯里化和柯里化 bind的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于9: 偏函数,高级函数,匿名函数,参数推断,闭包,柯里化,控制抽象、Es6中双箭头函数的含义(柯里化)、iOS Swift 应用程序随机 EXC_BAD_ACCESS 崩溃:swift_bridgeObjectRetain swift_retain swift::RefCounts
本文标签: