使用Swift时,如何向CFSocket回调函数传递对self的引用?

使用Swift时,如何向CFSocket回调函数传递对self的引用?,swift,macos,sockets,swift2,foundation,Swift,Macos,Sockets,Swift2,Foundation,下面的My函数创建一个CFSocket,并尝试以原始函数的所有者作为委托创建输入和输出流 @objc public class BonjourPublisher: NSObject, NSNetServiceDelegate, NSStreamDelegate { private func hookUpSocket(fd: CFSocketNativeHandle) throws { var context = CFSocketContext() var

下面的My函数创建一个
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>($0)
        }

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

        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()
}
@objc
公共类BonjourPublisher:NSObject、NSNetServiceDelegate、NSStreamDelegate{
私有函数hookUpSocket(fd:CFSocketNativeHandle)抛出{
var context=CFSocketContext()
var selfPtr=self
带不可配置指针(&selfPtr){
context.info=unsafemeutablepointer($0)
}
serviceSocket=withUnsafePointer(&context){
CFSocketCreateWithNative(nil、fd、CFSocketCallBackType.AcceptCallBack.rawValue、CallbackListen、UnsafePointer($0))
}
guard serviceSocket!=nil&&CFSocketIsValid(serviceSocket)else{
抛出BonjourServerError.CreatingNativeSocket
}
serviceRunLoopSource=CFSocketCreateRunLoopSource(零,serviceSocket,0)
guard serviceRunLoopSource!=nil&&CFRunLoopSourceIsValid(serviceRunLoopSource)else{
抛出BonjourServerError.CreatingSocketUnlopSource
}
CFRunLoopAddSource(CFRunLoopGetCurrent(),serviceRunLoopSource,kCFRunLoopCommonModes)
}
}
func CallbackListen(s:CFSocket!,callbackType:CFSocketCallBackType,地址:CFData!,数据:UnsafePointer,信息:UnsafeMutablePointer){
设fd=UnsafePointer(数据)
var readStream:非托管?
var writeStream:非托管?
CFStreamCreatePairWithSocket(无、fd.memory、读流和写流)
让inputStream:NSInputStream=readStream!.takeRetainedValue()
让outputStream:NSOutputStream=writeStream!.takeRetainedValue()
inputStream.setProperty(kCFBooleanTrue,forKey:kCFStreamPropertyShouldCloseNativeSocket作为字符串)
让publisherPtr=UnsafeMutablePointer(信息)
let publisher:BonjourPublisher=publisherpr.memory
inputStream.delegate=发布者
outputStream.delegate=publisher
inputStream.open()
outputStream.open()
}
但是引用
publisherPtr.memory
的第一行得到
EXC\u BAD\u ACCESS
异常。这里有什么问题?这是一个ARC问题,还是我把指针传递搞砸了?

(以上评论:)这里有几个问题:

  • 将局部变量
    var selfPtr
    的地址传递给回调函数。只要
    hookUpSocket()
    函数返回,该地址就会失效。有关将指针传递到
    self
    有关回调,请参阅此处的详细信息:

  • inputStream
    outputStream
    必须在运行循环中注册

  • inputStream
    outputStream
    是回调函数的局部变量 函数,以便在函数返回时释放它们。 它们应该是类的属性


这可能是您正在寻找的内容:。此处的详细信息:。代码中的问题是将局部变量
var selfPtr
的地址传递给回调函数。只要
hookUpSocket()
函数返回,该地址就变得无效。@MartinR因此,正如第一个链接所建议的,我切换到不透明指针,这样就排除了异常。不幸的是,我还有一些其他的问题,但这似乎回答了问题。您想发布答案吗?如果该链接回答了您的问题,那么我们可以将其作为副本关闭我不确定,但您是否也需要在运行循环中注册输入/输出流?此外,这些都是回调中的局部变量,最好使它们成为BonjourPublisher类的属性。@MartinR Bam,在这两个方面都是正确的。谢谢我投票决定关闭第一个链接的副本,这是一个为我工作的链接。