2019 年 4 月 10 日
使用函数作为 onComplete 监听器
Corona API 是业内设计最完善的 API 之一。我们一直努力使其保持一致且易于使用。Lua 也遵循类似的设计思路,力求保持一致且语法规则最少。但有时,对于刚接触新语言和 API 生态系统的新手开发人员来说,某些概念可能并不明显。
最近,论坛中讨论的一个问题就属于这些“陷阱”类别之一。
调用函数与提供函数地址
让我们看一个基本的 Corona API,即 timer.performWithDelay() API。此函数需要两个参数和一个可选的第三个参数。让我们看看它的定义:
1 |
timer.performWithDelay( delay, listener [, iterations] ) |
第一个参数 delay
是在作为 listener
传递的函数触发之前的时间(以毫秒为单位)。最后,您可以设置此函数运行的次数。从根本上说,您希望在 listener
运行之前等待一段时间。
让我们为此示例创建一个简单的监听器函数:
1 2 3 |
local function myListener( value ) print( "timer fired", value ) end |
它只是将计时器和值打印到控制台日志中。您的代码现在可能如下所示:
1 2 3 |
local myValue = 10 print( "timer start" ) timer.performWithDelay( 5000, myListener( myValue ) ) |
您会期望在控制台日志中看到消息 “timer start” 显示,然后在 5 秒后,您会期望看到 “timer fired”。但是,如果您运行此代码,您将看到两条消息同时打印,没有任何延迟。
发生了什么?
在 Lua 和许多其他语言中,有两种需求:
- 调用函数
- 获取函数的内存地址
对于 Corona API,它期望传递给它的函数,或者像 audio.play() 或 transition.to() 这样的函数上的 onComplete
选项,Corona 期望的是“函数的地址”。当您调用函数时,它会立即执行并返回一个值,如果您的函数没有返回值,则返回 nil。
如何“调用函数”与“获取函数的地址”
这非常简单,如果在函数名称后放置括号,则会运行该函数。如果您省略括号,则会获得该函数的地址。
因此,在我们上面的示例中,由于我们包含了 myListener( value )
,该函数会立即返回并返回任何返回值。因此,我们从 myListener()
获取消息,并且生成的计时器调用被编译为:
1 |
timer.performWithDelay( 5000, nil ) |
由于 myListener()
不返回值,因此返回 nil。然后,5 秒后,timer.performWithDelay()
尝试运行空操作。要使此工作,您必须将地址传递给函数。您可以通过省略括号并且不传递任何参数来实现:
1 |
timer.performWithDelay( 5000, myListener ) |
现在,在 5 秒后,将调用 myListener()
,消息将按预期打印。
您可能注意到,以这种方式永远不会传递该值。这就是 Corona 的工作方式。您不能在不使用 () 的情况下传递值,这将立即运行该函数。有一种使用匿名函数轻松解决此问题的方法,但这将是另一天的主题。
请记住,如果您要将函数提供给 onComplete
参数或监听器的函数,则必须传递函数的地址。
梦想!构建!发布!
抱歉,评论表单目前已关闭。