hi
I'm hoping someone might help I feel if its a simple fix but keep banging my head against the wall
I'm trying to get a rectangle to move following a midi input using note values. I have broken down the program to it's bear essentials to hilight the problem.
I'm using xcode 8 swift 3 and this is a mac os app
my program contains
one slider : named slider001
one button: named needsDisplayButton
one custom view named "GBV" using custom class called "gateBoxView"
here is the mainWindowController
import Cocoa
import CoreMIDI
var globalVariable = 40.0
class MainWindowController: NSWindowController {
@IBOutlet weak var GBV: gateBoxView!
override func windowDidLoad() {
super.windowDidLoad()
GBV.needsDisplay = true
//MIDI SETUP
var midiClient: MIDIClientRef = 0;
var inPort:MIDIPortRef = 0;
var src:MIDIEndpointRef = MIDIGetSource(0);
MIDIClientCreate("MidiTestClient", nil, nil, &midiClient);
MIDIInputPortCreate(midiClient, "MidiTest_InPort", MyMIDIReadProc, nil, &inPort);
MIDIPortConnectSource(inPort, src, &src);
}
@IBAction func slider001(_ sender: AnyObject) {
let data = sender.doubleValue!
globalVariable = data
print("data", data)
GBV.needsDisplay = true
}
@IBAction func needsDisplayButton(_ sender: AnyObject) {
globalVariable = 250.0
test(data: globalVariable, dataBool: true)
}
func test(data: Double, dataBool: Bool){
print("data", data)
globalVariable = data
//condition test
if GBV != nil {
print("Contains a value!",GBV)
} else {
print("Doesn’t contain a value.")
}
GBV.needsDisplay = dataBool
}
// MIDI INPUT USING OBJ C
let MyMIDIReadProc: MIDIReadProc = {pktList, readProcRefCon, srcConnRefCon in
let packetList:MIDIPacketList = pktList.pointee;
let srcRef: MIDIEndpointRef = UnsafeMutablePointer(srcConnRefCon!).pointee
var packet:MIDIPacket = packetList.packet;
for _ in 1...packetList.numPackets
{
let bytes = Mirror(reflecting: packet.data).children;
var dumpStr = "";
var i = packet.length;
for (_, attr) in bytes.enumerated()
{
dumpStr += String(format:"$%02X", attr.value as! UInt8);
i -= 1;
if (i <= 0)
{
break;
}
}
let mySendString = dumpStr
midiInput(midiInString: mySendString)
packet = MIDIPacketNext(&packet).pointee;
}
} /
}//end of the worldWhen I move the slider this updates the globalVariable and uses GBV.needsDisplay = true to refresh the view in my custom class gateBoxView: NSView
as shown here
// GateBox.swift
import Cocoa
class gateBoxView: NSView {
override func draw(_ dirtyRect: NSRect) {
let mybackgroundColor = NSColor.init(colorLiteralRed: 0.9, green: 0.4, blue: 0.4, alpha: 0.2)
mybackgroundColor.set()
NSBezierPath.fill(bounds)
let myY = globalVariable * 0.85
Swift.print("myY",myY)
let myRectangleColor = NSColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0)
let myRectangle = NSMakeRect(75.0, CGFloat(myY),40.0 , 20.0)
let cPath: NSBezierPath = NSBezierPath(rect: myRectangle)
myRectangleColor.set()
cPath.fill()
}
}the result is my rectangle moves up and down which is great so i know that IBOutlet connections are working
When I press the button It sets the globalVariable and then passes that information to the test function on line 38 of the mainWindowController
which then draws the rectangle at point 250 and using GBV.needsDisplay = true refreshes then view. This works and the rectangle is drawn. So i know now that the test func is working.
Using the midi code i send the program notes valued 1 to 10 and the program receives everything fine here is the MidiIn
I then send that data to the test function on line 38 of the mainWindowController expecting it to draw the rectangle according to the midi note values
Firstly if i delete line 49 on the mainWindowController i can see the midi data getting to the function so i know thats working and the numbers look good
BUT if GBV.needsDisplay = dataBool is included which it needs to refresh the custom view I get the usual error of fatal error: unexpectedly found nil while unwrapping an Optional value
which usually means the IBOulet is not setup correctly but the slider and button code prove that it is
I have tried working round the error using if Let.
using the condition test on line 43 of the mainWindowController i can see that when using the button or the slider GBV has a value
and if i use midi it says GBV has no value which really confuses me
I pretty sure it has nothing to do with midi
I have been stuck on this for a number of days. And would really appreciate any help
thanks for reading if you got this far
// MidiIn.swift
import Foundation
// This grabs the Midi in from the C code and Converts it to numbers
func midiInput(midiInString:String){
let parts = midiInString.components(separatedBy: "$")
let pitch = parts[2]
let pitchWrapped = Int(pitch, radix: 16)
/ //unwrap to Int
let pitchInt = pitchWrapped!
/
///Send Midi note Number to function test()
let myData = Double(pitchInt)*20.0
let InstanceOfMain = MainWindowController()
InstanceOfMain.test(data: myData, dataBool: true)
}//eo midiInputHere is the complete error
fatal error: unexpectedly found nil while unwrapping an Optional value
Current stack trace:
0 libswiftCore.dylib 0x00000001002d97c0 swift_reportError + 132
1 libswiftCore.dylib 0x00000001002f6300 _swift_stdlib_reportFatalError + 61
2 libswiftCore.dylib 0x000000010024f9e0 partial apply for thunk + 63
3 libswiftCore.dylib 0x00000001002a5b40 partial apply for thunk + 14
4 libswiftCore.dylib 0x00000001000e6a00 specialized StaticString.withUTF8Buffer<A> (invoke : (UnsafeBufferPointer<UInt8>) -> A) -> A + 351
5 libswiftCore.dylib 0x0000000100268fc0 partial apply for (_fatalErrorMessage(StaticString, StaticString, StaticString, UInt, flags : UInt32) -> ()).(closure #2) + 158
6 libswiftCore.dylib 0x000000010024f9e0 partial apply for thunk + 63
7 libswiftCore.dylib 0x00000001002a5b20 partial apply for thunk + 14
8 libswiftCore.dylib 0x00000001000e6a00 specialized StaticString.withUTF8Buffer<A> (invoke : (UnsafeBufferPointer<UInt8>) -> A) -> A + 351
9 libswiftCore.dylib 0x0000000100228cb0 specialized _fatalErrorMessage(StaticString, StaticString, StaticString, UInt, flags : UInt32) -> () + 143
10 Imaginator_001 0x0000000100002000 MainWindowController.test(data : Double, dataBool : Bool) -> () + 1012
11 Imaginator_001 0x0000000100009b40 midiInput(midiInString : String) -> () + 414
12 Imaginator_001 0x0000000100002710 MainWindowController.(MyMIDIReadProc).(variable initialization expression).(closure #1) + 16256
13 Imaginator_001 0x00000001000082d0 @objc MainWindowController.(MyMIDIReadProc).(variable initialization expression).(closure #1) + 9
14 CoreMIDI 0x0000000100066c70 LocalMIDIReceiverList::HandleMIDIIn(unsigned int, unsigned int, void*, MIDIPacketList const*) + 120
15 CoreMIDI 0x000000010006400e MIDIProcess::RunMIDIInThread() + 260
16 CoreMIDI 0x0000000100049cf8 XThread::RunHelper(void*) + 10
17 CoreMIDI 0x00000001000498de CAPThread::Entry(CAPThread*) + 80
18 libsystem_pthread.dylib 0x00000001009c3782 _pthread_body + 131
19 libsystem_pthread.dylib 0x00000001009c3782 _pthread_body + 0
20 libsystem_pthread.dylib 0x00000001009c0f94 thread_start + 13
(lldb)
My only interest in "correcting" your naming conventions is to make it easy to people to understand — and therefore answer — any forum questions you ask. The "power" of an initial miscapital is amazingly strong, and confusing.
My mistake about the code. 'oneAndOnlyWindowController' is a type ("class", "static") variable, but 'windowDidLoad' is an instance method, so class variable names must be fully qualified:
MainWindowController.oneAndOnlyWindowController = selfThat's what the compiler was trying to tell you. 🙂