重视我,每天共享一个关于 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
这个参数,从代码效率上来说这时分 Person
的 description
特点履行便是无效的(如果 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新知”,每天按时共享一个新知识,这里只是同步,想要及时学到就来重视我吧!