Core MIDI是一种C API,提供其他地方找不到的功能。
当用户的MIDI设置发生变化时(例如您插入设备),会有通知。
这是被调用的函数的类型。
typealias MIDINotifyProc = CFunctionPointer<((UnsafePointer<MIDINotification>, UnsafeMutablePointer<Void>) -> Void)>
第一个参数是MIDINotification结构,如下所示:
struct MIDINotification {
var messageID: MIDINotificationMessageID
var messageSize: UInt32
}
您可以像这样实现回调:
func MyMIDINotifyProc (np:UnsafePointer<MIDINotification>, refCon:UnsafeMutablePointer<Void>) {
var notification = np.memory
switch (notification.messageID) {
case MIDINotificationMessageID(kMIDIMsgObjectAdded):
// In Objective-C you would just do a cast here
// This is the problem line
var m = np.memory as MIDIObjectAddRemoveNotification
您可以查看messageID成员,了解您刚刚收到的通知类型。有几个(我只展示一个)。对于每种通知,您将获得传入的不同结构。这是添加或删除设备时获得的结构:
struct MIDIObjectAddRemoveNotification {
var messageID: MIDINotificationMessageID
var messageSize: UInt32
var parent: MIDIObjectRef
var parentType: MIDIObjectType
var child: MIDIObjectRef
var childType: MIDIObjectType
}
如您所见,此结构具有其他信息。例如,“child”可能是设备的端点,因此您需要这些字段。
问题是从MIDINotification结构(回调签名所需)转换为MIDIObjectAddRemoveNotification。我使用“as”显示的行不起作用。
对于这种“向下倾斜”,您有什么建议吗?
答案 0 :(得分:2)
我建议您查看标准库函数unsafeBitCast
。
答案 1 :(得分:2)
由于Vatsal Manot suggested,由于MIDINotification
和MIDIObjectAddRemoveNotification
与任何继承或契约无关,因此Swift无法在这些结构之间执行任何安全投射。
您需要使用unsafeBitCast
函数明确地强制转换它:
case MIDINotificationMessageID(kMIDIMsgObjectAdded):
let m = unsafeBitCast(np.memory, MIDIObjectAddRemoveNotification.self)
请注意,此函数始终可以在Swift中用于执行强制转换,但它非常不安全,您应该仅将其用作最后一种可能的解决方案。
答案 2 :(得分:1)
你忘了一件事。即使是Obj-C,施法总是在指针上发生。你不能把记忆转移到记忆中(好吧,有时你可以,重新解释它,但它不是很安全)。
let notification = np.memory
switch (notification.messageID) {
case MIDINotificationMessageID(kMIDIMsgObjectAdded):
//cast the pointer!
let addedNp = UnsafeMutablePointer<MIDIObjectAddRemoveNotification>(np)
//now you can just access memory directly
var m = addedNp.memory
}