重视我,每天共享一个关于 iOS 的新知识

前言

在 Swift,有一种不常用的闭包类型 — @autoclosure这个关键字能够让咱们将一个表达式封装到一个闭包中,在需求该表达式成果的时分才履行该闭包(类似于懒加载)。这为咱们提供了一种推迟履行代码的方法,能够有用提高性能。

尽管业务开发中不常常运用,但是在 swift 标准库中运用场景非常多,关于怎样运用咱们来用一些示例来具体聊聊。

运用方法

举个比如,在此示例中,咱们创立了一个 log 方法和一个 Person 结构体,当调用 description 特点时,将会打印日志:

structPerson{
letname:String

vardescription:String{
print("调用了Persondescription.")
return"Personnameis\(name)"
}
}
funclog(_message:String){
iffalse{
print("\(message)")
}
}
letperson=Person(name:"iOS新知")
log(person.description)

履行上边的代码,将会看到控制台输出“调用了 Person description.

由于我的代码中写了 if false,所以永远不可能履行 if 条件下的打印,也就不会拜访 message 这个参数,从代码效率上来说这时分 Persondescription 特点履行便是无效的(如果 description 中有大量的运算,会导致性能下降)。这是由于调用 person.description 的时分就直接履行了 description 这个核算特点。

让咱们改一下代码,把 message 参数改成一个闭包,只有函数内调用这个闭包才履行 description 函数:

structPerson{
letname:String

vardescription:String{
print("调用了Persondescription.")
return"Personnameis\(name)"
}
}
funclog(_message:()->String){
iffalse{
print("\(message())")
}
}
letperson=Person(name:"iOS新知")
log({person.description})

我把 log 函数的 message 参数由 String 类型,改成了 () -> String 闭包类型,调用的时分也改成了 log({ person.description }),此时再运行代码,没有履行 description 特点,符合咱们的预期。

但是每次调用 log 函数都要将参数用大括号包裹,用起来非常的不便,这时分 @autoclosure 就要登场了,在 log 函数的 message 参数中增加这个关键字,调用的时分就不需求大括号了,最终代码如下:

structPerson{
letname:String

vardescription:String{
print("调用了Persondescription.")
return"Personnameis\(name)"
}
}
funclog(_message:@autoclosure()->String){
iffalse{
print("\(message())")
}
}
letperson=Person(name:"iOS新知")
log(person.description)

这份代码看起来就清新多了,既完成了咱们的需求(拜访 message 的时分才调用 description),调用方法又和之前一样。

一些其他比如

1、推迟实例化目标

structCanvas{
letwidth:CGFloat
letheight:CGFloat

funcdrawShape(){}
}
funcdraw(canvas:@autoclosure()->Canvas){
ifshouldDraw{
canvas().drawShape()
}
}
//调用时才创立Canvas实例
draw(canvas:Canvas(width:200,height:100))

Canvas 目标只在需求制作时才创立调用 init 方法创立。

2、削减内存运用

funcdecode(image:@autoclosure()->UIImage)->Image?{
ifshouldDecode{
returndecodeImage(image())
}else{
returnnil
}
}
letimg=decode(image:loadImageFromDisk())

图片解码可能很占内存,应该只在需求时(shouldDecode)解码图片,防止不必要的内存占用。

3、防止冗余核算

funchash(value:@autoclosure()->String)->Int{
iflethashValue=self.hashValue{
returnhashValue
}
returnhashFunction(value())
}
lethash1=hash(value:someString)
lethash2=hash(value:someString)

有些操作开销比较大,能够运用 @autoclosure 防止重复核算。

4、字典取值时的默认值核算

之前的文章中介绍过字典取值时能够设置默认值,其实在 swift 底层就用到了 @autoclosure

publicsubscript(key:Key,defaultdefaultValue:@autoclosure()->Value)->Value

由于在字典取不到 key 对应的值的情况下,才需求核算默认值,而不是每次都核算。

这里每天共享一个 iOS 的新知识,快来重视我吧

本文同步自微信公众号 “iOS新知”,每天按时共享一个新知识,这里只是同步,想要及时学到就来重视我吧!