cocos2d-x忠CCMenu的setHandlerPriority崩溃的解决方法(转)
(原文:http://www.eoeandroid.com/thread-251449-1-1.html)
因为游戏中需要一些模态化对话框,
设计:
1)Dialog是个Layer,该Layer可点击,并且优先级数值为kCCMenuHandlerPriority-1
2)Dialog里有2个layer,一个CCLayerColor作为mask,一个CCLayer作为容器,CCLayer里添加CCMenu,该CCMenu的优先级数值设为kCCMenuHandlerPriority-2
这样可达到屏蔽dialog下的事件,并且dialog的menu事件可响应。
实现:
1)在Dialog的init里添加所有的layer,
2)然后在onEnter方法中设置CCMenu的优先级
运行时发现,在调用setHandlerPriority时总是报错,findHandler()返回NULL;
断点进去,分析函数调用的流程如下:(点击按钮,弹出对话框)
1)CCTouchDispatcher::touches派发事件,执行pHandler->getDelegate()->ccTouchEnded(即调用到CCMenu)
2)CCMenu调用按钮的回调函数,创见Dialog
3)因为Dialog是添加到一个已经处于running状态的node中,会直接进入onEnter中,此时会处理到Dialog中CCMenu的onEnter,进而执行registerWithTouchDispatcher;此时因为CCTouchDispatcher::touches派发事件才执行一半,变量m_bLocked为true,所以CCMenu指针添加到m_pHandlersToAdd中待处理;
4)待Dialog创建完成之后,CCTouchDispatcher::touches会继续派发事件,派发完成之后,处理m_pHandlersToAdd,将CCMenu指针加到m_pTargetdHandlers或者m_pStandardHandlers中去
懂UML的兄弟帮忙做个时序图吧
如果在Dialog的onEnter中就处理CCMenu的priority的话,因为m_pHandlersToAdd还未处理,所以findHandler就会返回NULL,CCAssert报错。
解决办法就是在下一帧或者一段时间后再处理priority。
this->scheduleOnce(schedule_selector(xxx), 0); // 这个0,是不是代表下一帧执行的意思呢?如果不确定的话,最好给个大于0的时间