ByteNoteByteNote
结束通知发出时条目已空
字

字节笔记本

2026年10月7日 · 约 2 分钟读完

结束通知发出时条目已空

API中转
¥120

状态对象里有是否正在拖、拖的是哪条字符串、是否已经离开窗口、起点和计时器。开始拖动时把标记设为真,记下字符串和起点,并启动计时器。计时器间隔 0.1 秒,闭包用弱引用。

清空发生在发送之前

停止函数先把正在拖设为假,离开标记设为假,字符串设为 nil,起点设为 nil,计时器作废。然后打印 Sending dragEnded notification。原来的发送只有名字和空的 object,注释却写着会带上被拖条目。更新后的发送加了 userInfo,键是 item,值却是刚刚被设成 nil 的那个属性。收到通知时,条目已经是空的。要带上原来的字符串,得在清空之前先存一份。

放下的 performDrop 会调用停止函数并返回真。结束通知依赖这次放下。没有发生放下时,停止函数不会从这里被调用,结束通知也不会从这里发出。用户说没有触发,要先确认放下确实走到了这个方法。

计时器发的是另一个名字

检查函数取第一个窗口和起点。用 mouseLocationOutsideOfEventStream 看当前点,再用内容视图的 bounds 判断是否在里面。内容视图用了强制解包,视图不在时会直接崩溃。内外状态和上次不同,才把 isLeavingWindow 改掉,并发送 dragStateChanged,userInfo 里同样有 item。这个名字不是 dragEnded。计时器不会发结束通知。

先清空再放进通知,条目是空的

两个名字注册成 dragStateChanged 和 dragEnded。片段里没有订阅它们的代码。发送成功和有人收到是两件事。没有订阅者时,打印那句仍然会出现,界面却像没收到。

坐标来自窗口,包含判断用的是内容视图的 bounds。两套坐标系不一致时,人还在窗口里也会被算成已经离开,或相反。对话没有做坐标转换。

计时器发的不是结束这个名字

开始拖动不会发结束通知。结束只在停止函数里。停止函数又把计时器废掉,所以离开状态不会在结束之后继续刷。

弱引用在对象释放后是空的。计时器若在对象之后还响,检查不会执行。这和条目被提前清空是两个空。

相关文章

分享: