Search code examples
swiftmacoscocoansslider

nsslider.integerValue requires me to focus on another app before updating the value


I have an NSSlider in my macos app, called wave_mode_slider. What I'm trying to do is update the value of said slider on input. So, what I did is this:

self.wave_mode_slider?.integerValue = ("\(params[2])" as NSString).integerValue

This sets the value of the slider (white dot) to the value of the input as intended. However, before I see any actual result, I have to click outside of the application, which causes the white dot of the slider to jump to it's new value. as shown here:enter image description here

Is there a way to make the slider update immediately?

My slider is created like this:

    self.wave_mode_slider = NSSlider(frame:CGRect(x: 10, y: 100, width: 20, height: 300))
    self.wave_mode_slider?.cell = OWOWSliderVertical()
    self.wave_mode_slider?.maxValue = 127
    self.wave_mode_slider?.target = self
    self.view?.addSubview(self.wave_mode_slider!)

I tried to set the isContinuous property of the slider to true, but that doen't change the outcome.


edit:

    var midiClient : MIDIClientRef = 0
    var inPort : MIDIPortRef = 0
    let observer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())

        MIDIClientCreate("WobClient" as CFString, nil, nil, &midiClient)
        MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, {
            (pktList: UnsafePointer<MIDIPacketList>, readProcRefCon: UnsafeMutableRawPointer?, srcConnRefCon: UnsafeMutableRawPointer?) -> Void in
            let packetList : MIDIPacketList = pktList.pointee
            var packet : MIDIPacket = packetList.packet
            let mySelf = Unmanaged<Wob>.fromOpaque(srcConnRefCon!).takeUnretainedValue()
            for _ in 1...packetList.numPackets {
                let bytes = Mirror(reflecting: packet.data).children
                var params : [UInt64] = []

                var i = packet.length
                for (_, attr) in bytes.enumerated() {
                    let string = String(format: "%02X ", attr.value as! UInt8)
                    params.append(UInt64(strtoul(string, nil, 16)))
                    i -= 1

                    if (i <= 0) {
                        break
                    }
                }

//                print(("\(params[2])" as NSString).integerValue)
                mySelf.setWaveSliderValue(value: ("\(params[2])" as NSString).integerValue)
                packet = MIDIPacketNext(&packet).pointee
            }

        }, nil, &inPort)

        MIDIPortConnectSource(inPort, self.source, observer)

This is fro m where i get the value


Solution

  • In the end it was pretty easy, as soon as i saw Willeke's comment about the threading, I just used the main thread to set the value on:

    DispatchQueue.main.async {
        mySelf.wave_mode_slider?.floatValue = ("\(params[2])" as NSString).floatValue
    }