Domanda

That sinking feeling when you realize you have no idea what's going on...

I've been using this code in my network code for almost two years without problems.

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.
    }
}

I believe it was originally based on the code samples given here:

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

I recently noticed, however, that some connections are failing, because CFReadStreamOpen returns false but the error code is 0. After staring at the above link some more, I noticed the CFRunLoopRun() statement, and added it:

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

This fixed the connection problem. However, my app started showing random problems - interface sometimes not responsive, or not drawing, text fields not editable, that kind of stuff.

I've read up on CFReadStreamOpen and on run loops (specifically, that the main run loop runs by itself and I shouldn't run a run loop unless I'm setting it up myself in a secondary thread - which I'm not, as far as I know). But I'm still confused about what's actually happening above. Specifically:

1) Why does CFReadStreamOpen sometimes return FALSE and error code 0? What does that actually mean?

2) What does the CFRunLoopRun call actually do in the above code? Why does the sample code make that call - if this code is running in the main thread I shouldn't have to run the run loop?

È stato utile?

Soluzione

I guess I'll answer my own question, as much as I can.

1) In my code, at least, CFReadStreamOpen always seems to return false. The documentation is a bit confusing, but I read it to mean the stream wasn't opened yet, but will be open later in the run loop.

2) Most of the calls I was making were happening in the main thread, where the run loop was already running, so calling CFRunLoopRun was unnecessary. The call that was giving me problems was happening inside a block, which apparently spawned a new thread. This new thread didn't start a new run loop - so the stream would never open unless I explicitly ran the new thread's run loop.

I'm still not 100% clear on what happens if I call CFRunLoopRun() on a thread with an already running run loop, but it's obviously not good.

I ended up ditching my home-brewed networking code and switching to ASIHTTPRequest, which I was considering to do anyway.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top