Question

So I have had extensive experience reading rendered html source code of a website in Java. However I have researched thoroughly regarding how to do the exact same thing in Objective-C and have been able to come up with a solution that should work, but it doesn't. The idea is that i want to read each line, for example:"view-source:www.apple.com", i want the read the result of that page line by line. I don't want any Html parser etc. This is what i have:

NSString *s = [NSString stringWithFormat:@"http://www.apple.com"];
NSURL *url = [NSURL URLWithString:s];

NSInputStream *iStream= [[NSInputStream alloc] initWithURL:url];

[iStream setDelegate:self];

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

[iStream open];
NSLog(@"stream successfully opened");



NSInteger result;
uint8_t buffer[1024];
    while((result = [iStream read:buffer maxLength:1024]) != 0) {       
    if(result > 0) {
        NSLog(@"Buffer is %@",buffer);

        // buffer contains result bytes of data to be handled
    } else {
        NSLog(@"ERROR: %@",buffer);
        // The stream had an error. You can get an NSError object using [iStream streamError]
    }
    NSLog(@"end of while loop: %@",buffer);

}
// Either the stream ran out of data or there was an error


NSLog(@"Either the stream ran out of data or there was an error");

This runs and compiles fine, but the result is always 0. Again i have done a a lot of research and i don't understand why the result is 0. Any help is appreciated.

Was it helpful?

Solution 2

This other solution worked...

NSString *s = [NSString stringWithFormat:@"http://www.apple.com"];
NSURL *url = [NSURL URLWithString:s];


NSData *data = [NSData dataWithContentsOfURL:url];
NSString* newStr = [[NSString alloc] initWithData:data
                                         encoding:NSUTF8StringEncoding];
NSArray *arr= [newStr componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

although, i would have rather read the page line by line as this seems inefficient-but i'll settle with this for now until i can find a better answer.

OTHER TIPS

You may wish to check whether your NSInputStream is actually non-nil after this line:

NSInputStream *iStream= [[NSInputStream alloc] initWithURL:url];

Mainly what I see is that you open an NSInputStream but you never make any HTTP request with it. I think you need to open up a stream pair, and send an HTTP GET request over the NSOutputStream then listen on the NSInputStream.

Here's a illustrative code fragment:

#import <Foundation/Foundation.h>

@interface CCFStreamReader : NSObject <NSStreamDelegate>
- (void)readStream;
@end

@implementation CCFStreamReader {
    NSInputStream *_inputStream;
    NSOutputStream *_outputStream;
}
- (void)readStream {
    NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)[url host], 80, &readStream, &writeStream);

    _inputStream = (__bridge_transfer NSInputStream *)readStream;
    _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];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
    NSLog(@"input stream = %@",_inputStream);
    printf("read something");
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent {
    printf("stream event: %d\n",(int)streamEvent);
    switch( streamEvent ) {
        case NSStreamEventHasSpaceAvailable:
        {
            if (aStream == _outputStream) {
                NSString *str = [NSString stringWithFormat:
                                  @"GET / HTTP/1.0\r\n\r\n"];
                const uint8_t *rawstring = (const uint8_t *)[str UTF8String];
                [_outputStream write:rawstring maxLength:str.length];
                [_outputStream close];
            }
            break;
        }
        case NSStreamEventHasBytesAvailable: {
            printf("Bytes available\n");
        }
    }

}

@end

int main(int argc, char *argv[]) {

    @autoreleasepool {
        CCFStreamReader *reader = [CCFStreamReader new];
        [reader readStream];
    }
}

Usual caveats - this fragment may well be riddled with errors. It isn't intended to be a fully developed solution. For example, I don't actually fetch any data from the stream, etc. The run loop is left running forever, etc. etc.

Finally, this assumes that you really really want to deal with the HTML in this way, for whatever reason.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top