V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
nannanziyu
V2EX  ›  Swift

Swift 开发遇到的一个莫名奇妙的 bug

  •  
  •   nannanziyu · Oct 12, 2017 · 5508 views
    This topic created in 3122 days ago, the information mentioned may be changed or developed.

    开发过程中遇到的,发出来和大家一起讨论。
    新建了一个简单的 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 变灰

    S1

    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)
    

    S1

    6,Xcode8.3.3 + Swift3

    No Comments Yet
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   812 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 21:06 · PVG 05:06 · LAX 14:06 · JFK 17:06
    ♥ Do have faith in what you're doing.