Question

Je suis le portage d'une Application à partir de l'Objective-C, Swift et j'ai besoin d'utiliser la méthode suivante:

CFStreamCreatePairWithSocketToHost(alloc: CFAllocator!, host: CFString!, port: UInt32, \
readStream: CMutablePointer<Unmanaged<CFReadStream>?>, \
writeStream: CMutablePointer<Unmanaged<CFWriteStream>?>)

La vieille logique ressemble à ceci (ce que plusieurs sites web semblent être d'accord):

CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(host), port, \
                                   &readStream, &writeStream);

NSInputStream inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream outputStream = (__bridge_transfer NSOutputStream *)writeStream;

Qui fonctionne très bien grâce au numéro sans frais de transition.Toutefois, l'ARC n'existe pas dans "Swift-espace", et le type de système a changé.

Comment puis-je activer mon flux dans les instances de

CMutablePointer<Unmanaged<CFReadStream>?>, and
CMutablePointer<Unmanaged<CFWriteStream>?>

Et puis les convertir en arrière dans NSStream les sous-classes après la CFStreamCreatePairWithSocketToHost appel?

Était-ce utile?

La solution

Je l'ai eu à travailler, voici mon code:Assurez-vous de garder une référence de la classe de connexion quelque part :-)

class Connection : NSObject, NSStreamDelegate {
    let serverAddress: CFString = "127.0.0.1"
    let serverPort: UInt32 = 8443

    private var inputStream: NSInputStream!
    private var outputStream: NSOutputStream!

    func connect() {
        println("connecting...")

        var readStream:  Unmanaged<CFReadStream>?
        var writeStream: Unmanaged<CFWriteStream>?

        CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream)

        // Documentation suggests readStream and writeStream can be assumed to
        // be non-nil. If you believe otherwise, you can test if either is nil
        // and implement whatever error-handling you wish.

        self.inputStream = readStream!.takeRetainedValue()
        self.outputStream = writeStream!.takeRetainedValue()

        self.inputStream.delegate = self
        self.outputStream.delegate = self

        self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
        self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

        self.inputStream.open()
        self.outputStream.open()
    }

    func stream(stream: NSStream, handleEvent eventCode: NSStreamEvent) {
        println("stream event")
    }
}

Autres conseils

Je n'étais pas en mesure d'obtenir les exemples d'autres, ont apporté dans ce fil de travail.Bien sûr, ils ont compilé, mais ils se sont écrasés dès que la connexion a été ouverte.

Cependant, j'ai remarqué dans la WWDC 2014 discussions (et iOS 8 release notes) qu'il existe une nouvelle méthode pour initialiser un NSStream pour la création d'un bond paire d'entrée/sortie flux.

Voir ci-dessous:

var inputStream: NSInputStream?
var outputStream: NSOutputStream?

NSStream.getStreamsToHostWithName("localhost", port: 1234, inputStream: &inputStream, outputStream: &outputStream)

Ceci élimine le besoin pour le maladroit CFStreamCreatePairWithSocketToHost appel ainsi que la suppression de la nécessité pour les ressources non managées.

J'ai travaillé sur la façon de le faire.Quelques remarques importantes:

  1. CMutablePointers sera automatiquement créé si vous utilisez l'opérateur&.
  2. Vous pouvez obtenir à la T dans un Unmanaged<T> avec .getUnretainedValue() et getRetainedValue() (Il semble .getUnretainedValue() est analogue à __bridge_transfer)
  3. Options sont automatiquement initialisées à nil.
  4. Si une option est nil il va se traduire par une false condition.

Jusqu'à présent j'ai (non testé):

var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, \
&readStream, &writeStream)

if (readStream && writeStream) {
    inputStream = readStream!.takeUnretainedValue();
    outputStream = writeStream!.takeUnretainedValue();
}

Je suis à l'aide de getStreamsToHostWithName fonction de NSStream classe.Il est plus facile et beeter que CFStreamCreatePairWithSocketToHost

func initNetworkCommunication() {

print("connecting...")

let serverAddress = "gzoa.vps.infomaniak.com"
let serverPort = 1234

NSStream.getStreamsToHostWithName(serverAddress, port: serverPort, inputStream: &inputStream, outputStream: &outputStream)

self.inputStream!.delegate = self
self.outputStream!.delegate = self

self.inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

self.inputStream!.open()
self.outputStream!.open()

}

Swift 3 version de CF et NS code.Tant de travail pour moi.

CF:

class Connection: NSObject, StreamDelegate {

private var inputStream: InputStream!
private var outputStream: OutputStream!

var connected = false

func connect(host: String, port: UInt32) {
    var readStream:  Unmanaged<CFReadStream>?
    var writeStream: Unmanaged<CFWriteStream>?

    CFStreamCreatePairWithSocketToHost(nil, host as CFString, port, &readStream, &writeStream)

    self.inputStream = readStream!.takeRetainedValue()
    self.outputStream = writeStream!.takeRetainedValue()

    if let inputStream = inputStream, let outputStream = outputStream {
        inputStream.delegate = self
        outputStream.delegate = self

        inputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
        outputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)

        inputStream.open()
        outputStream.open()

        connected = true
    }
}

func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
    print("stream event, \(eventCode)")
}

}

NS:

class NSConnection: NSObject, StreamDelegate {

private var inputStream: InputStream?
private var outputStream: OutputStream?

var connected = false

func connect(host: String, port: Int) {
    Stream.getStreamsToHost(withName: host, port: port, inputStream: &inputStream, outputStream: &outputStream)

    if let inputStream = inputStream, let outputStream = outputStream {
        inputStream.delegate = self
        outputStream.delegate = self

        inputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)
        outputStream.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)

        inputStream.open()
        outputStream.open()
    }
}

func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
    print("stream event, \(eventCode)")
}

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top