我如何处理 Swift 中的 CFSocketCallBackType.dataCallback?

How do I handle CFSocketCallBackType.dataCallback in Swift?

All documentation and examples say that if a socket's CFSocketCallBack 标注被赋予 .dataCallback 作为其第二个参数 (callbackType),这意味着第四个参数 (data) 可以转换为 CFData 包含从套接字中预读的所有数据的对象。

但是,当我尝试这样做时,它失败了:

private func myCallout(socket: CFSocket?,
                       callBackType: CFSocketCallBackType,
                       address: CFData?,
                       callBackTypeMetaData: UnsafeRawPointer?,
                       info: UnsafeMutableRawPointer?) -> Void {

    // Behavior inferred from Developer
    // https://developer.apple.com/documentation/corefoundation/cfsocketcallback

    guard
        let info = info,
        let socket = socket
        else {
        return assertionFailure("Socket may have gone out of scope before response")
    }

    // <REDACTED>


    if callBackType == .dataCallBack {
        guard let data = callBackTypeMetaData?.load(as: CFData.self) else {
            return assertionFailure("Data Callback's metadata was not a CFData object")
        }

        foo(data as Data) // Crashes here
    }

    // <REDACTED>
}

我遇到的崩溃是这样的:

Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0).

在调试器中,当我键入以下内容时:

(lldb) po callBackTypeMetaData!.load(as: CFData.self)

它只是打印一个指针地址(也相当高;只有两个重要的 0s)。但是,当我键入以下内容时:

(lldb) po callBackTypeMetaData!.load(as: CFData.self) as Data

它打印这个:

error: Execution was interrupted, reason: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0).
The process has been returned to the state before expression evaluation.

所以看起来我得到的并不是真正的 CFData,但它足够接近,表面上看起来很相似,直到有人真正尝试这样阅读它。

这是怎么回事,我的数据在哪里,我该如何解决?

data = callBackTypeMetaData!.load(as: CFData.self)

callBackTypeMetaData! 指向的内存位置读取一个 CFData 指针。你想要的是 "reinterpret" 作为 CFData(或 NSData)指针的原始指针:

if callBackType == .dataCallBack {
    if let rawPointer = callBackTypeMetaData  {
        let data = Unmanaged<NSData>.fromOpaque(rawPointer).takeUnretainedValue() as Data
        // ...
    }
}