NSCachedURLResponse / NSKeyedUnarchiver pain

Wed, 27. Jan 2010

Categories: en development Tags: cache Cocoa iPhone NSCachedURLResponse NSKeyedArchiver NSKeyedUnarchiver NSURLCache Objective C

as the iPhone SDK comes with a rather dysfunctional NSURLCache β€” Apple suggests to implement it from scratch yourselfΒ in the code examples about caching β€” I went for just this.

Until I came across the [NSKeyedUnarchiver unarchiveObjectWithData:...] not restoring userInfo, storagePolicy and data of NSCachedURLResponse.

Couldn’t believe it and spent almost the whole day verifying that the error is not within my code but really the unarchiver treats those fields transient.

See yourself:

 1-(void)testiPhoneSDK312NSKeyedArchiver
 2{
 3//  prepare a NSCachedURLResponse
 4    NSCachedURLResponse *src = nil;
 5    {
 6        NSURL *i_url = [NSURL URLWithString:@"http://www.url.example/path/file.html"];
 7        NSString *i_mime = @"text/html";
 8        NSInteger expectedContentLength = 112;
 9        NSString *i_encoding = @"iso-8859-2";
10
11        NSURLResponse *i_response = [[NSURLResponse alloc] initWithURL:i_url
12            MIMEType:i_mime
13            expectedContentLength:expectedContentLength
14            textEncodingName:i_encoding];
15        NSData *i_data = [@"Hello, world!" dataUsingEncoding:NSISOLatin2StringEncoding];
16        NSURLCacheStoragePolicy i_storage =  NSURLCacheStorageAllowed;
17        NSDictionary *i_userInfo = [NSDictionary dictionaryWithObject:
18        [NSDate dateWithTimeIntervalSince1970:13] forKey:@"era"];
19
20        NSCachedURLResponse *src = [[NSCachedURLResponse alloc] initWithResponse:i_response
21            data:i_data
22            userInfo:i_userInfo
23            storagePolicy:i_storage];
24
25//      ensure it's all in place:
26        STAssertEqualObjects(i_url, src.response.URL, @"");
27        STAssertEqualObjects(i_mime, src.response.MIMEType, @"");
28        STAssertEquals((int)expectedContentLength, (int)src.response.expectedContentLength, @"");
29        STAssertEqualObjects(@"file.html", src.response.suggestedFilename, @"");
30        STAssertEqualObjects(i_encoding, src.response.textEncodingName, @"");
31
32        STAssertEqualObjects(i_data, src.data, @"");
33        STAssertEqualObjects(i_userInfo, src.userInfo, @"");
34        STAssertEquals( 0u, src.storagePolicy, @"");
35    }
36
37//  archive + unarchive:
38    NSCachedURLResponse *dst = [NSKeyedUnarchiver unarchiveObjectWithData:
39      [NSKeyedArchiver archivedDataWithRootObject:src]];
40
41//  check whether src == dst
42    STAssertEqualObjects(src.response.URL, dst.response.URL, @"");
43    STAssertEqualObjects(src.response.MIMEType, dst.response.MIMEType, @"");
44    STAssertEquals(src.response.expectedContentLength, dst.response.expectedContentLength, @"");
45    STAssertEqualObjects(src.response.suggestedFilename, dst.response.suggestedFilename, @"");
46    STAssertEqualObjects(src.response.textEncodingName, dst.response.textEncodingName, @"");
47
48//  !!!!!!!!!!
49//  sad information loss after unarchiving:
50    STAssertNil( dst.data, @"" );
51    STAssertNil( dst.userInfo, @"" );
52    STAssertEquals( 2u , dst.storagePolicy, @"" );
53}

When my NSURLCache replacement is ready I think about publishing it a github β€” interested anyone?