开发过程中遇到的,发出来和大家一起讨论。
新建了一个简单的 Demo 也可以重现。
1,用 Xcode 新建一个新的 CocoaApplication,语言选 swift,使用 storyboard
2,往窗口上随便拖一个控件,比如 NSTableView,然后把 NSTableView 拉线到 ViewController,并命名为 tb
3,简单修改 ViewController,完整代码 gist 地址如下:
https://gist.github.com/anonymous/d0b2d458b58a74d9ef97307f0fa9f834
4,可以看到 Action 和 WhatEver 是除了名字外完全相同的两个类
在 menuWillOpen 里也是相似的两段代码,分别使用 Action 和 WhatEver 来创建 NSMenuItem 的 Action
5,奇怪的现象来了,同样的两个代码段顺序不同产生了不同的情形
5.1,情景 1
let item2 = NSMenuItem()
item2.title = "Item_2"
let closure = WhatEver({print("xxx")})
item2.target = closure
item2.action = #selector(closure.invoke)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), closure, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
menu.addItem(item2)
let item1 = NSMenuItem()
item1.title = "Item_1"
let action = Action({print("xxx")})
item1.target = action
item1.action = #selector(action.action)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), action, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
menu.addItem(item1)
ContextMenu 的两个子项第一次打开都是正常的,但是点过一次后,Item2 变灰
5.2,情景 2
将两块代码顺序互换,则一切正常
let item1 = NSMenuItem()
item1.title = "Item_1"
let action = Action({print("xxx")})
item1.target = action
item1.action = #selector(action.action)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), action, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
menu.addItem(item1)
let item2 = NSMenuItem()
item2.title = "Item_2"
let closure = WhatEver({print("xxx")})
item2.target = closure
item2.action = #selector(closure.invoke)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), closure, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
menu.addItem(item2)
5.3,两段代码的 target 注释掉(这样闭包不会执行),无论哪段代码在前,Item2 都是灰色不可点
let item2 = NSMenuItem()
item2.title = "Item_2"
let closure = WhatEver({print("xxx")})
//item2.target = closure
item2.action = #selector(closure.invoke)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), closure, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
menu.addItem(item2)
let item1 = NSMenuItem()
item1.title = "Item_1"
let action = Action({print("xxx")})
//item1.target = action
item1.action = #selector(action.action)
objc_setAssociatedObject(self, String(format: "[%d]", arc4random()), action, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
menu.addItem(item1)
6,Xcode8.3.3 + Swift3