【quick遇到的陷阱】node的onExit()和onEnter()
2016-01-14 01:21
756 查看
事情是这样的,我想让继承自node的类能在正确的时刻调用onExit()函数,那我们开始吧。
创建了个空项目,然后MainScene.lua弄成下面的样子,嗯,去掉了label然后在加了几个打印函数。
--MainScene.lua
local MainScene = class("MainScene", function()
return display.newScene("MainScene")
end)
function MainScene:ctor()
printInfo("MainScene:ctor()")
end
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end
return MainScene
我们运行一下,然后退出。log是这样的
合理。我们继续。
新建一个lua文件,myNode.lua,写一个简单的继承自node的节点类。
--myNode.lua
local myNode = class("myNode", function()
return display.newNode()
end)
function myNode:ctor()
printInfo("myNode:ctor()")
end
function myNode:onEnter()
printInfo("myNode:onEnter()")
end
function myNode:onExit()
printInfo("myNode:onExit()")
end
return myNode
然后丢到MainScene里
--MainScene.lua
local myNode = require("myNode")
function MainScene:ctor()
printInfo("MainScene:ctor()")
self.mynode = myNode.new()
:addTo(self)
End
运行,退出。log是这样的。
什么,没看到myNode的onExit和onEnter函数。一开始以为哪里代码写错了,啊,这几行代码也能写错?好吧,先试试手动调用onEnter和onExit。在MainScene.lua里面的onEnter和onExit里分别调用myNode的onEnter和onExit。
--MainScene.lua
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
self.mynode:onEnter()
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
self.mynode:onExit()
end
运行,退出。
结果符合预期。那代码确实没错啊。怎么得要我手动调用呢,这不科学。
嗯,翻开\framework\cocos2dx\NodeEx.lua,找到下面的代码。我们看到了熟悉onXxxx函数,不过都是空的,在下面还有一个函数setNodeEventEnabled
--\framework\cocos2dx\NodeEx.lua
function Node:onEnter()
end
function Node:onExit()
end
function Node:onEnterTransitionFinish()
end
function Node:onExitTransitionStart()
end
function Node:onCleanup()
end
function Node:setNodeEventEnabled(enabled, listener)
if enabled then
if self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
if not listener then
listener = function(event)
local name = event.name
if name == "enter" then
self:onEnter()
elseif name == "exit" then
self:onExit()
elseif name == "enterTransitionFinish" then
self:onEnterTransitionFinish()
elseif name == "exitTransitionStart" then
self:onExitTransitionStart()
elseif name == "cleanup" then
self:onCleanup()
end
end
end
self.__node_event_handle__ = self:addNodeEventListener(c.NODE_EVENT, listener)
elseif self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
return self
end
简单看看这个setNodeEventEnabled函数,函数主体有两个分支,if和elseif,没有else。注意看第一行if enabled then,所传的参数enabled仅出现在此处,enabled非空时成立,则enabled应该是个bool值,当然语法角度来说,你传任何(not nil)都是ok的。
紧接着这段,移除self的事件监听。
if self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
你会发现他和elseif分支的代码简直一毛一样
elseif self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
好了,从结果上来说,不管这个self(node)原本有些什么监听器,那么在调用setNodeEventEnabled之后,这些监听器都say goodbye了。
接着if notlistener then这块。listener应该就是回调函数了。可以看到,当事件名为"enter"时候调用self:onEnter(),当事件名……,原来这些回调默认下是没有被调用的(顺便说,-x里面是会的)。if not listener then之后紧接着。self.__node_event_handle__ =self:addNodeEventListener(c.NODE_EVENT, listener)。就是添加事件监听器了。那么,如果我们自己传入listener的话,就可以只指定的开启某个onXxxx的回调。来试试。
首先,MainScene.lua的onEnter和onExit先删掉myNode的两行。
--MainScene.lua
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end
然后myNode:ctor()中添加代码:
--myNode.lua
function myNode:ctor()
self:setNodeEventEnabled(true, function(event)
if event.name = "enter" then
self:onEnter()
end
end)
printInfo("myNode:ctor()")
end
运行,关掉。看看结果。
Nice
我们试试onExit。替换一下代码我就不完全复制了
--myNode.lua
if event.name = "exit" then
self:onExit()
end
很好。
既然自己传入回调,我们监听指定函数可以么。可以。
写个myNode:myOnExit()函数。
--myNode.lua
--myNode.lua
if event.name = "exit" then
self:myOnExit()
end
设想。在本该onExit的时候却onEnter。
也可以(因为现在这几个函数都仅仅是包涵打印语句,所以并没什么区别。所以实际开发中请三思)
if event.name = "exit" then
self:onEnter()
end
啊。跑题了。
写了那么多,懒癌发作了。我就只是想让节点类正常的回调onExit()罢了。
好,那就只加一行代码。加在:ctor()第一行。或者,不影响监听器添加的某一行下(记住NodeEx.lua里setNodeEventEnabled是会清空节点的当前的事件监听器的)。
创建了个空项目,然后MainScene.lua弄成下面的样子,嗯,去掉了label然后在加了几个打印函数。
--MainScene.lua
local MainScene = class("MainScene", function()
return display.newScene("MainScene")
end)
function MainScene:ctor()
printInfo("MainScene:ctor()")
end
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end
return MainScene
我们运行一下,然后退出。log是这样的
合理。我们继续。
新建一个lua文件,myNode.lua,写一个简单的继承自node的节点类。
--myNode.lua
local myNode = class("myNode", function()
return display.newNode()
end)
function myNode:ctor()
printInfo("myNode:ctor()")
end
function myNode:onEnter()
printInfo("myNode:onEnter()")
end
function myNode:onExit()
printInfo("myNode:onExit()")
end
return myNode
然后丢到MainScene里
--MainScene.lua
local myNode = require("myNode")
function MainScene:ctor()
printInfo("MainScene:ctor()")
self.mynode = myNode.new()
:addTo(self)
End
运行,退出。log是这样的。
什么,没看到myNode的onExit和onEnter函数。一开始以为哪里代码写错了,啊,这几行代码也能写错?好吧,先试试手动调用onEnter和onExit。在MainScene.lua里面的onEnter和onExit里分别调用myNode的onEnter和onExit。
--MainScene.lua
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
self.mynode:onEnter()
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
self.mynode:onExit()
end
运行,退出。
结果符合预期。那代码确实没错啊。怎么得要我手动调用呢,这不科学。
嗯,翻开\framework\cocos2dx\NodeEx.lua,找到下面的代码。我们看到了熟悉onXxxx函数,不过都是空的,在下面还有一个函数setNodeEventEnabled
--\framework\cocos2dx\NodeEx.lua
function Node:onEnter()
end
function Node:onExit()
end
function Node:onEnterTransitionFinish()
end
function Node:onExitTransitionStart()
end
function Node:onCleanup()
end
function Node:setNodeEventEnabled(enabled, listener)
if enabled then
if self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
if not listener then
listener = function(event)
local name = event.name
if name == "enter" then
self:onEnter()
elseif name == "exit" then
self:onExit()
elseif name == "enterTransitionFinish" then
self:onEnterTransitionFinish()
elseif name == "exitTransitionStart" then
self:onExitTransitionStart()
elseif name == "cleanup" then
self:onCleanup()
end
end
end
self.__node_event_handle__ = self:addNodeEventListener(c.NODE_EVENT, listener)
elseif self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
return self
end
简单看看这个setNodeEventEnabled函数,函数主体有两个分支,if和elseif,没有else。注意看第一行if enabled then,所传的参数enabled仅出现在此处,enabled非空时成立,则enabled应该是个bool值,当然语法角度来说,你传任何(not nil)都是ok的。
紧接着这段,移除self的事件监听。
if self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
你会发现他和elseif分支的代码简直一毛一样
elseif self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
好了,从结果上来说,不管这个self(node)原本有些什么监听器,那么在调用setNodeEventEnabled之后,这些监听器都say goodbye了。
接着if notlistener then这块。listener应该就是回调函数了。可以看到,当事件名为"enter"时候调用self:onEnter(),当事件名……,原来这些回调默认下是没有被调用的(顺便说,-x里面是会的)。if not listener then之后紧接着。self.__node_event_handle__ =self:addNodeEventListener(c.NODE_EVENT, listener)。就是添加事件监听器了。那么,如果我们自己传入listener的话,就可以只指定的开启某个onXxxx的回调。来试试。
首先,MainScene.lua的onEnter和onExit先删掉myNode的两行。
--MainScene.lua
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end
然后myNode:ctor()中添加代码:
--myNode.lua
function myNode:ctor()
self:setNodeEventEnabled(true, function(event)
if event.name = "enter" then
self:onEnter()
end
end)
printInfo("myNode:ctor()")
end
运行,关掉。看看结果。
Nice
我们试试onExit。替换一下代码我就不完全复制了
--myNode.lua
if event.name = "exit" then
self:onExit()
end
很好。
既然自己传入回调,我们监听指定函数可以么。可以。
写个myNode:myOnExit()函数。
--myNode.lua
function myNode:myOnExit() printInfo("myNode:myOnExit()") end同样的,替换一下代码
--myNode.lua
if event.name = "exit" then
self:myOnExit()
end
设想。在本该onExit的时候却onEnter。
也可以(因为现在这几个函数都仅仅是包涵打印语句,所以并没什么区别。所以实际开发中请三思)
if event.name = "exit" then
self:onEnter()
end
啊。跑题了。
写了那么多,懒癌发作了。我就只是想让节点类正常的回调onExit()罢了。
好,那就只加一行代码。加在:ctor()第一行。或者,不影响监听器添加的某一行下(记住NodeEx.lua里setNodeEventEnabled是会清空节点的当前的事件监听器的)。
function myNode:ctor() self:setNodeEventEnabled(true) printInfo("myNode:ctor()") end
相关文章推荐
- 详解Lua中的表的概念及其相关操作方法
- Lua编程示例(二):面向对象、metatable对表进行扩展
- 把Lua编译进nginx步骤方法
- Lua脚本自动生成APK包
- Lua中的元表(metatable)、元方法(metamethod)详解
- Lua中的metatable介绍
- Lua中ipair和pair的区别
- Lua中的函数精讲笔记
- 浅谈Lua的面向对象特性
- 详解Lua中的变量相关知识点
- Lua脚本语言入门笔记
- Lua脚本调用外部脚本
- 详解Lua中的if语句的使用方法
- Lua中调用函数使用点号和冒号的区别
- Lua中的闭合函数、非全局函数与函数的尾调用详解
- Lua中强大的元方法__index详解
- Lua中调用C++函数示例
- Lua面向对象之类和继承浅析
- Lua性能优化技巧(一):前言
- Lua中获取table长度问题探讨