Joshua Joshua - 4 months ago 44
Swift Question

Subclassing NSControl, IBAction is not called in Swift

I've subclassed an NSSlider that behaves differently whether the option key is pressed. In order to do that, I overrode the mouseDown func. It seems to do the job.
The thing is, I've noticed the connected @IBAction in my ViewController is only triggered when the option key is unpressed (i.e. when the mouseDown method is passed to super). What am I missing in order to allow the @IBAction to perform?

Many thanks
Besides the issue, improvement advices on the code are welcome... :-)

Josh

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
}
}
}

Answer

If you're not calling super.mouseDown, you need to send the action yourself:

sendAction(action, to: target)

sendAction(_:to:), action and target are existing members of NSControl.

Comments