使用 Swift 时如何将 CFSocket 回调函数传递给 self 的引用?

How do you pass a CFSocket callback function a reference to self when using Swift?

我下面的函数创建了一个 CFSocket 并尝试以原始函数的所有者作为委托来创建输入和输出流。

@objc
public class BonjourPublisher: NSObject, NSNetServiceDelegate, NSStreamDelegate {
    private func hookUpSocket(fd: CFSocketNativeHandle) throws {
        var context = CFSocketContext()

        var selfPtr = self
        withUnsafeMutablePointer(&selfPtr) {
            context.info = UnsafeMutablePointer<Void>([=11=])
        }

        serviceSocket = withUnsafePointer(&context) {
            CFSocketCreateWithNative(nil, fd, CFSocketCallBackType.AcceptCallBack.rawValue, CallbackListen, UnsafePointer<CFSocketContext>([=11=]))
        }

        guard serviceSocket != nil && CFSocketIsValid(serviceSocket) else {
            throw BonjourServerError.CreatingNativeSocket
        }

        serviceRunLoopSource = CFSocketCreateRunLoopSource(nil, serviceSocket, 0)

        guard serviceRunLoopSource != nil && CFRunLoopSourceIsValid(serviceRunLoopSource) else {
            throw BonjourServerError.CreatingSocketRunLoopSource
        }

        CFRunLoopAddSource(CFRunLoopGetCurrent(), serviceRunLoopSource, kCFRunLoopCommonModes)
    }
}

func CallbackListen(s: CFSocket!, callbackType: CFSocketCallBackType, address: CFData!, data: UnsafePointer<Void>, info: UnsafeMutablePointer<Void>) {
    let fd = UnsafePointer<CFSocketNativeHandle>(data)
    var readStream: Unmanaged<CFReadStreamRef>?
    var writeStream: Unmanaged<CFWriteStreamRef>?

    CFStreamCreatePairWithSocket(nil, fd.memory, &readStream, &writeStream)

    let inputStream: NSInputStream = readStream!.takeRetainedValue()
    let outputStream: NSOutputStream = writeStream!.takeRetainedValue()

    inputStream.setProperty(kCFBooleanTrue, forKey: kCFStreamPropertyShouldCloseNativeSocket as String)

    let publisherPtr = UnsafeMutablePointer<BonjourPublisher>(info)
    let publisher: BonjourPublisher = publisherPtr.memory
    inputStream.delegate = publisher
    outputStream.delegate = publisher

    inputStream.open()
    outputStream.open()
}

但是引用 publisherPtr.memory 的第一行得到一个 EXC_BAD_ACCESS 异常。这里有什么问题?是 ARC 问题,还是我弄乱了我的指针传递?

(来自上面的评论:)这里有几个问题:

  • 你把局部变量var selfPtr的地址传给回调。一旦 hookUpSocket() 函数 returns,该地址就会失效。有关将指针传递给 self 的方法,请参阅 到回调,更多信息在这里:.

  • inputStreamoutputStream 必须使用 运行 循环注册。

  • inputStreamoutputStream是回调的局部变量 函数,因此它们在函数 returns 时被释放。 它们应该是您的 class 的属性。