Ios &引用;“向下投射”;Swift中的C结构

Ios &引用;“向下投射”;Swift中的C结构,ios,swift,Ios,Swift,核心MIDI是一个C API,它提供了其他地方找不到的功能 当用户的MIDI设置发生更改(例如,您插入了设备)时,会发出通知 这是所调用函数的类型 typealias MIDINotifyProc = CFunctionPointer<((UnsafePointer<MIDINotification>, UnsafeMutablePointer<Void>) -> Void)> 您可以这样实现回调: struct MIDINotification {

核心MIDI是一个C API,它提供了其他地方找不到的功能

当用户的MIDI设置发生更改(例如,您插入了设备)时,会发出通知

这是所调用函数的类型

typealias MIDINotifyProc = CFunctionPointer<((UnsafePointer<MIDINotification>, UnsafeMutablePointer<Void>) -> Void)>
您可以这样实现回调:

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
如您所见,此结构具有附加信息。例如,“child”可能是设备的端点,因此您需要这些字段

问题是从MIDINotification结构(回调签名所需)转换为MIDIObjectAddRemoveNotification。我显示的使用“as”的行不起作用


您对这种“向下转换”有什么建议吗?

我建议您研究一下标准库函数。

因为
MIDINotification
MIDIObjectAddRemoveNotification
没有任何继承或契约关系,所以Swift不能在这些结构之间执行任何安全转换

您需要使用
unsafeBitCast
函数显式强制转换它:

case MIDINotificationMessageID(kMIDIMsgObjectAdded):
    let m = unsafeBitCast(np.memory, MIDIObjectAddRemoveNotification.self)

请注意,此函数始终可以在Swift中用于执行强制转换,但它非常不安全,您只能将其用作最后一种可能的解决方案。

您忘记了一件事。即使是Obj-C,投射也总是发生在指针上。你不能将记忆转换为记忆(好吧,有时候你可以,重新解释它,但这不是很安全)

let notification=np.memory
开关(notification.messageID){
案例midNotificationMessageId(kMIDIMsgObjectAdded):
//投下指针!
设addedNp=UnsafeMutablePointer(np)
//现在你可以直接访问内存了
var m=已添加的内存
}

Update:好吧,它工作了一段时间。它现在在Swift 2.0测试版中被打破。
case MIDINotificationMessageID(kMIDIMsgObjectAdded):
    let m = unsafeBitCast(np.memory, MIDIObjectAddRemoveNotification.self)
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
}