子类化 NSControl,在 Swift 中不调用 IBAction

Posted

技术标签:

【中文标题】子类化 NSControl,在 Swift 中不调用 IBAction【英文标题】:Subclassing NSControl, IBAction is not called in Swift 【发布时间】:2016-08-04 23:29:20 【问题描述】:

我已经对 NSSlider 进行了子类化,无论是否按下选项键,它的行为都会有所不同。为了做到这一点,我覆盖了 mouseDown 函数。它似乎完成了这项工作。 问题是,我注意到我的 ViewController 中连接的 @IBAction 仅在未按下选项键时触发(即当 mouseDown 方法传递给 super 时)。为了让@IBAction 执行,我缺少什么?

非常感谢 除了问题之外,欢迎对代码提出改进建议... :-)

乔什

class ViewController: NSViewController 

    @IBOutlet weak var theSlider: MySlider!
    @IBAction func moveSlider(sender: NSSlider) 
        print(sender.floatValue) //works only with optionKey unpressed
    


class MySlider: NSSlider  //Implemented in another source file

    @IBInspectable var multiplier: Float = 0.5
    private var modifierKeys = NSEventModifierFlags.AlternateKeyMask
    private var optionKeyPressed = false
    private var previousSliderPosition: Float = 0.0

//MARK: Init with NSCoder
    required init?(coder: NSCoder) 
        super.init(coder: coder)
        Swift.print("init Coder called")

        self.continuous = true
        NSEvent.addLocalMonitorForEventsMatchingMask(.FlagsChangedMask)  (theEvent) -> NSEvent? in
            self.flagsChanged(theEvent)
            return theEvent
        
    

//MARK: Mouse tracking
    override func mouseDown(theEvent: NSEvent) 

        if optionKeyPressed 

            var keepOn = true
            previousSliderPosition = self.floatValue * Float(self.bounds.width) / Float(self.maxValue)

            while keepOn 
                if let nextEvent = self.window?.nextEventMatchingMask(Int(NSEventMask.LeftMouseUpMask.rawValue) | Int(NSEventMask.LeftMouseDraggedMask.rawValue))
                
                    switch nextEvent.type
                    
                    case .LeftMouseDragged:
                         let mouseInnerLocationX = Float(self.convertPoint(nextEvent.locationInWindow, fromView: self.superview).x)
                        let mouseDelta = mouseInnerLocationX - previousSliderPosition
                        let newSliderPosition = previousSliderPosition + (mouseDelta) * multiplier

                        self.floatValue = newSliderPosition * Float(self.maxValue) / Float(self.bounds.width)
                        break

                    case .LeftMouseUp:
                        keepOn = false
                        break

                    default:
                        break
                    
                
            
         else 
            super.mouseDown(theEvent)
        
    

//MARK: Option key handling
    override func flagsChanged(theEvent: NSEvent) 
        if (theEvent.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == NSEventModifierFlags.AlternateKeyMask.rawValue 
            optionKeyPressed = true
         else 
            optionKeyPressed = false
        
    

【问题讨论】:

【参考方案1】:

如果您不调用super.mouseDown,则需要自己发送操作:

sendAction(action, to: target)

sendAction(_:to:)actiontargetNSControl 的现有成员。

【讨论】:

有效! self.sendAction(self.action, to: nil) 谢谢!

以上是关于子类化 NSControl,在 Swift 中不调用 IBAction的主要内容,如果未能解决你的问题,请参考以下文章

Layer-Backed NSControl 仍然调用 NSCell 绘图例程

在swift中子类化'PDFView' - 找不到接口声明

在 Swift 中子类化 PFObject

使用 Swift 子类化 UIApplication

想知道如何以编程方式在 swift 3.0 中对 UITableViewCell 进行子类化?

UIViewController 的 Swift 子类化子类