3

何が起こっているのかわからないことに気付いたときのその沈む感じ...

私はこのコードをネットワークコードでほぼ2年間問題なく使用しています。

if (!CFReadStreamOpen(myReadStream)) {
    CFStreamError myErr = CFReadStreamGetError(myReadStream);
    if (myErr.error != 0) {
    // An error has occurred.
        if (myErr.domain == kCFStreamErrorDomainPOSIX) {
        // Interpret myErr.error as a UNIX errno.
            strerror(myErr.error);
        } else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
            OSStatus macError = (OSStatus)myErr.error;
            }
        // Check other domains.
    }
}

私はそれがもともとここに与えられたコードサンプルに基づいていたと信じています:

http://developer.apple.com/library/mac/#documentation/Networking/Conceptual/CFNetwork/CFStreamTasks/CFStreamTasks.html

ただし、最近、CFReadStreamOpenがfalseを返すが、エラーコードが0であるため、一部の接続が失敗していることに気付きました。上記のリンクをもう少し見つめた後、CFRunLoopRun()ステートメントに気づき、次のように追加しました。

if (!CFReadStreamOpen(myReadStream)) {
    CFStreamError myErr = CFReadStreamGetError(myReadStream);
    if (myErr.error != 0) {
    // An error has occurred.
        if (myErr.domain == kCFStreamErrorDomainPOSIX) {
        // Interpret myErr.error as a UNIX errno.
            strerror(myErr.error);
        } else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
            OSStatus macError = (OSStatus)myErr.error;
            }
        // Check other domains.
    } else
        // start the run loop
        CFRunLoopRun();
}

これにより、接続の問題が修正されました。しかし、私のアプリはランダムな問題を示し始めました-インターフェイスが応答しない、または描画されない、テキストフィールドが編集できない、そのようなものです。

私はCFReadStreamOpenと実行ループについて読みました(具体的には、メインの実行ループはそれ自体で実行され、セカンダリスレッドで自分で設定しない限り、実行ループを実行するべきではありません-私はそうではありません、私の知る限りでは)。しかし、私はまだ上で実際に何が起こっているのかについて混乱しています。具体的には:

1)CFReadStreamOpenがFALSEとエラーコード0を返すことがあるのはなぜですか?それは実際にはどういう意味ですか?

2)CFRunLoopRun呼び出しは、上記のコードで実際に何をしますか?サンプルコードがその呼び出しを行うのはなぜですか?このコードがメインスレッドで実行されている場合、実行ループを実行する必要はありませんか?

4

1 に答える 1

1

できる限り自分の質問に答えると思います。

1)私のコードでは、少なくともCFReadStreamOpenは常にfalseを返すようです。 ドキュメントは少し紛らわしいですが、ストリームがまだ開かれていないことを意味するように読んでいますが、実行ループの後半で開かれます。

2)私が行っていた呼び出しのほとんどは、実行ループがすでに実行されているメインスレッドで行われていたため、CFRunLoopRunを呼び出す必要はありませんでした。私に問題を与えていた呼び出しは、明らかに新しいスレッドを生成したブロック内で発生していました。この新しいスレッドは新しい実行ループを開始しませんでした。そのため、新しいスレッドの実行ループを明示的に実行しない限り、ストリームは開かれません。

すでに実行ループが実行されているスレッドでCFRunLoopRun()を呼び出すとどうなるかについては、まだ100%明確ではありませんが、明らかに良くありません。

結局、自作のネットワークコードを捨てて、とにかくやろうと思っていたASIHTTPRequestに切り替えました。

于 2011-09-29T15:19:23.330 に答える