NSView subview blocking drag/drop event

原文链接

近期在Mac项目中有一个处理鼠标拖拽事件的需求, 大致处理流程是这样的:

  1. 从 NSView 继承得到一个子类
  2. 覆盖处理拖拽事件相关方法
  3. 注册拖拽事件

开始的时候一切都很正常,直到某次发现拖拽到屏幕边缘响应较为灵敏,而拖拽到屏幕中间则不响应事件,APP页面大致是这样的:

问题分析

开始我一直以为是系统事件不太灵光, 后来发现只有在拖动到屏幕中间时候出现这个问题, 这个现象十分奇怪, 后来联想到页面中间有一张图片,猜测是否是因为图片截获了拖拽事件。

那么如何验证呢?其实也很简单,在自定义的NSView 中重载draggingEnded:方法,同时添加 log,发现鼠标拖拽到页面中间时, 该方法就不再被调用。因此可以得出结论,在自定义的 NSView 中添加的NSImageView作为 subview 会阻止拖拽事件的传递,原因是 NSImageView本身可以处理拖拽事件,于是截获了本该自定义NSView处理的消息。

解决方案

在网上搜索了一下这个问题,发现已经有人给出了解决方案,具体链接:http://stackoverflow.com/questions/5892464/cocoa-nsview-subview-blocking-drag-drop

提供的解决方案有以下几种:

  1. 不使用 NSImageView,而是采用自定义 NSView的方式,然后重写drawRect:方法进行图片渲染。这个办法十分笨拙,并且不太方便。
  2. 调用unregisterDraggedTypes 方法,这样 NSImageView就不会监听拖拽事件了,完美解决。

参考文档