关于GPUImage3中LuminanceThreshold类使用闭包设置uniform值的疑问
嗨,我来帮你拆解这段代码里的闭包为什么存在,以及它的工作原理~
首先得先理清这段代码的核心矛盾:threshold属性已经在定义时设置了默认值0.5,还加了didSet观察者用来同步值到uniformSettings里,那为什么还要在init里用个看起来多此一举的闭包再赋值一次?
背后的关键:Swift的初始化顺序
这得从Swift的初始化规则说起:
- 子类初始化时,会先初始化自己的存储属性(包括设置默认值),之后才会调用父类的初始化方法。
- 而
uniformSettings是从父类BasicOperation继承来的属性,它的初始化是在super.init(fragmentFunctionName:numberOfInputs:)这个调用里完成的。
当threshold的默认值0.5被设置时,父类还没完成初始化,uniformSettings根本还不存在!这时候如果触发didSet,里面的uniformSettings["threshold"] = threshold就会直接崩溃——因为你访问了一个还没初始化的属性。
闭包的作用是什么?
在init方法里,我们先调用了super.init,这一步确保父类的所有属性(包括uniformSettings)都已经准备就绪了。
接下来的({threshold = 0.5})()是一个立即执行的闭包:它刚被定义就立刻执行,本质就是给threshold重新赋值一次0.5。这次赋值会触发didSet观察者,而此时uniformSettings已经存在,所以能安全地把阈值同步到GPU着色器需要的uniform变量里。
额外补充:其实闭包是多余的
你可能会好奇,那直接写threshold = 0.5不行吗?当然可以!这段代码里用闭包完全是写法上的选择,可能是作者的个人习惯,或者是早期版本遗留的写法。直接赋值和用闭包的效果完全一致,都会触发didSet,而且代码更简洁。
总结一下:核心逻辑是必须等父类初始化完成后,才能安全地更新uniformSettings,闭包在这里只是一种“立即执行代码”的写法,本质和直接赋值没区别。
备注:内容来源于stack exchange,提问作者Heylvj

