2015-11-10 4 views
1

Моя функция внизу создает CFSocket и пытается создать входные и выходные потоки с владельцем оригинальной функции в качестве делегата.Как вы передаете функцию обратного вызова CFSocket ссылку на себя при использовании Swift?

@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() 
} 

Но первая строка для обозначения publisherPtr.memory получает EXC_BAD_ACCESS исключение. В чем проблема? Это проблема ARC, или я испортил мой указатель?

+1

Это может быть то, что вы ищете: [Swift 2 - UnsafeMutablePointer объекта] (http://stackoverflow.com/questions/30786883/swift-2-unsafemutablepointervoid-to-object). Дополнительная информация здесь: [Как направить себя на UnsafeMutablePointer type in swift] (http://stackoverflow.com/questions/33294620/how-to-cast-self-to-unsafemutablepointervoid-type-in-swift). –

+1

Проблема в вашем коде заключается в том, что вы передаете адрес * локальной переменной * 'var selfPtr' для обратного вызова. Этот адрес становится недействительным, как только функция 'hookUpSocket()' возвращается. –

+0

@MartinR Итак, я переключился на непрозрачные указатели, как рекомендует первая ссылка, и избавилась от исключений. К сожалению, у меня есть некоторые другие проблемы, но похоже, что это ответ на вопрос. Вы хотите опубликовать ответ? – Dov

ответ

1

(Из приведенных выше замечаний :) Есть несколько проблем:

  • Вы передаете адрес локальной переменной var selfPtr обратного вызова. Этот адрес становится недействительным, как только возвращается функция hookUpSocket(). См. Swift 2 - UnsafeMutablePointer<Void> to object для способа передачи указателя на self для обратного вызова, более подробную информацию здесь: How to cast self to UnsafeMutablePointer<Void> type in swift.

  • inputStream и outputStream должны быть зарегистрированы в цикле запуска.

  • inputStream и outputStream локальные переменные обратного вызова функции, поэтому они высвобождены когда функция возвращает. Вместо этого они должны быть свойствами вашего класса.

 Смежные вопросы

  • Нет связанных вопросов^_^