【quick遇到的陷阱】node的onExit()和onEnter()

事情是这样的,我想让继承自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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值