2nd Edition "Callbacks" fails without any error


#1

The program compiles and runs without any errors but fails to receive any data from http://www.gutenberg.org/cache/epub/205/pg205.txt
I’m stumped as to why it doesn’t work.

BNRLogger.h:

#import <Foundation/Foundation.h>

@interface BNRLogger : NSObject
    <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
{
    NSMutableData *incomingData;
}
@property (nonatomic) NSDate *lastTime;
- (NSString *) lastTimeString;
- (void) updateLastTime: (NSTimer *)t;
- (void) connection:(NSURLConnection *)connection didRecieveData:(NSData *)data;
- (void) connectionDidFinishLoading:(NSURLConnection *)connection;
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
@end

BNRLogger.m

#import "BNRLogger.h"
@implementation BNRLogger
- (NSString *) lastTimeString
{
    static NSDateFormatter *dateFormatter = nil;
    if (!dateFormatter) {
        dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
        [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
        NSLog(@"created dateFormatter");
    }
    return [dateFormatter stringFromDate:self.lastTime];
}
- (void) updateLastTime:(NSTimer *)t
{
    NSDate *now = [NSDate date];
    [self setLastTime:now];
    NSLog(@"Just set time to %@", self.lastTimeString);
}
// Called each time a chunk of data arrives
- (void) connection:(NSURLConnection *)connection didRecieveData:(NSData *)data
{
    NSLog(@"received %lu bytes", [data length]);
    // Create a mutable data buffer if it doesn't already exist
    if (!incomingData) {
        incomingData = [[NSMutableData alloc] init];
    }
    [incomingData appendData:data];
}
// Called when the last chunk of data has been processed
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Got it all!");
    NSString *string = [[NSString alloc] initWithData:incomingData encoding:NSUTF8StringEncoding];
    incomingData = nil;
    NSLog(@"string received has %lu characters", [string length]);
    // uncomment the next line to see the entire fetched file:
    // NSLog(@"The whole string is %@", string);
}

main.m

#import <Foundation/Foundation.h>
#import "BNRLogger.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        BNRLogger *logger = [[BNRLogger alloc] init];
        NSURL *url = [NSURL URLWithString:@"http://www.gutenberg.org/cache/epub/205/pg205.txt"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        __unused NSURLConnection *fetchConn = [[NSURLConnection alloc] initWithRequest:request delegate:logger startImmediately:YES];
        __unused NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:logger selector:@selector(updateLastTime:) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

#2

Don’t be stumped; check your method names.

You have a typographical error.

Compare:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)data; // Yours

This kind of error can be avoided simply by using the auto-completion feature of Xcode or by copying and pasting from the class reference.

Also, because NSURLConnectionDataDelegate already conforms to NSURLConnectionDelegate, this:

@interface BNRLogger : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate> can be reduced to:

@interface BNRLogger : NSObject <NSURLConnectionDataDelegate>

#3

Thank you so much ibex!! I started all over and got a working version the second time and still couldn’t find the error! It’s been driving me crazy for hours. I’m sort of puzzled as to why there were no complaints or errors of any sort to draw my attention to the mistake. In any event–you’ve saved me a great deal of anxiety and I really appreciate your help! Best wishes-- Scott