I cannot initialize a NSInputStream

1.8k views Asked by At

Please help me, im going insane. I need to create an NSInputStream so i can read a live preview from a camera over wifi. liveViewStream is an NSInputStream-Instance-Variable that is declared in my implementation like so:

@implementation MKSonyCamHandler{
    NSInputStream *liveViewStream;
}

liveViewURL is a valid URL that i can open in my browser when i connect to the camera's network (although i dont think that this makes any difference). I have checked that it exists, is not nil and holds the value that i expect. But when i do this:

liveViewStream = [[NSInputStream alloc] initWithURL:liveViewURL];
DLog(@"%@", liveViewStream);

The DLog after the alloc-init commands will log "(null)" every time, and ill be damned if i know why. Has anybody ever encountered this? Am i missing something glaringly obvious here? Its my first time working with NSStreams, is there a common pitfall that might be the reason? The docs clearly state that -initWithURL:

Creates and returns an initialized NSInputStream object that reads data from
the file at a given URL.

Any ideas? Im starting to feel really stupid here.

EDIT: i am using ARC.

2

There are 2 answers

0
katzenhut On BEST ANSWER

Thanks everyone, i found it.

The thing is, my question already had all the clues i would have needed, because, like i wrote, NSStream`s -initWithURL: will

Create and return an initialized NSInputStream object that reads data from
the file at a given URL.

What I didn't see is that this is only true for local sources. If you want a remote host, (i had a wireless network connection) you need to use something else, because, and i quote the docs again here:

The NSStream class does not support connecting to a remote host on iOS.

Well, for what its worth, you need to create a CFReadStreamRef and a CFWriteStreamRef, and then use the magic function CFStreamCreatePairWithSocketToHost to connect them to your host. After that, you can cast them to NSInputStream and NSOutputStream respectively, and they will work as intended. Heres a code example from the docs:

    CFReadStreamRef readStream;

    CFWriteStreamRef writeStream;

    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 80, &readStream, &writeStream);



    NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;

    NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;

    [inputStream setDelegate:self];

    [outputStream setDelegate:self];

    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream open];

    [outputStream open];

Hope this helps someone at some point.

@leparlon:

Im upvoting your answer, since you were definitly on the right track, suggesting the use of initWithData.

2
paulonogueira On

If you are using ARC, that might fix it:

EDIT: Downloading it into a NSData first might fix it

NSInputStream *tempStream;
NSData *tempData = [NSData dataWithContentsOfURL:@"Your Url"]; 
tempStream = [[NSInputStream alloc] initWithData:tempData]; 
liveViewStream = tempStream; 
DLog(@"%@", liveViewStream);