事情是这样的,我想让继承自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
合理。我们继续。
新建一个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
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end
然后myNode:ctor()中添加代码:
--myNode.luafunction 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