23

アプリを Objective-C から Swift に移植していますが、次の方法を使用する必要があります。

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

古いロジックは次のようになります (いくつかの Web サイトが同意しているようです)。

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;

フリーダイヤルのブリッジングのおかげで、これはうまく機能します。ただし、「Swift-space」には ARC が存在せず、型システムが変更されています。

ストリームをインスタンスに変換するにはどうすればよいですか

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

そして、呼び出しNSStream後にそれらをサブクラスに変換しますか?CFStreamCreatePairWithSocketToHost

4

5 に答える 5

42

私はそれを機能させました。これが私のコードです:接続クラスの参照をどこかに保持していることを確認してください:-)

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")
    }
}
于 2014-06-04T17:46:56.603 に答える
28

このスレッドで他の人が提供した例を機能させることができませんでした。確かに、それらはコンパイルされましたが、接続が開かれるとすぐにクラッシュしました。

しかし、WWDC 2014 の議論 (および iOS 8 リリース ノート) で、イン/アウト ストリームのバインドされたペアを作成するために NSStream を初期化する新しい方法があることに気付きました。

下記参照:

var inputStream: NSInputStream?
var outputStream: NSOutputStream?

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

これにより、厄介な CFStreamCreatePairWithSocketToHost 呼び出しの必要性がなくなり、アンマネージ リソースの必要性もなくなります。

于 2014-07-02T19:21:04.067 に答える
2

やり方を工夫しました。いくつかの重要な注意事項:

  1. CMutablePointers& 演算子を使用すると、自動的に作成されます。
  2. andTUnmanaged<T>を取得できます(これは に似ているようです) 。.getUnretainedValue()getRetainedValue().getUnretainedValue()__bridge_transfer
  3. オプションは自動的に に初期化されnilます。
  4. オプションの場合はnil、条件に変換されfalseます。

これまでのところ(テストされていません):

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

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

if (readStream && writeStream) {
    inputStream = readStream!.takeUnretainedValue();
    outputStream = writeStream!.takeUnretainedValue();
}
于 2014-06-05T03:14:50.027 に答える