[Catalina] NSData in NSDictionary decoded as NSMutableData??

FB7324582


Is it me or when you encode a NSDictionary dictionary that contains a NSData object, decoding the NSDictionary decodes the NSData as a NSMutableData?


This is on Catalina b9, Xcode 11.1, using NSSecureCoding protocol and keyed archivers/unarchivers.


This is a bit problemetic since NSSecureCoding complains when you try to encode a NSMutableData. So you can't encode -> decode ->encode because of this issue.

Replies

Also, unless I'm missing something, the last print should say Data, not Mutable Data in this sample code:


#import <Foundation/Foundation.h>

void printKindOfClass(id inObject)
{
    if ([inObject isKindOfClass:[NSMutableData class]]==YES)
        NSLog(@"Mutable Data");
    else if ([inObject isKindOfClass:[NSData class]]==YES)
        NSLog(@"Data");
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        NSData * tData=[NSData dataWithContentsOfFile:@"/bin/ls"];
        
        printKindOfClass(tData);
        
        NSMutableData * tMutableData=[tData mutableCopy];
        
        printKindOfClass(tMutableData);
        
        tData=[tMutableData copy];
        
        printKindOfClass(tData);
        
        // Here comes a bug
        
        NSData * tBookmarkData=[[NSURL fileURLWithPath:@"/bin/ls"] bookmarkDataWithOptions:0 includingResourceValuesForKeys:@[] relativeToURL:nil error:NULL];
        
        printKindOfClass(tBookmarkData);
        
        tData=[tBookmarkData copy];
        
        printKindOfClass(tData); // <--- Here is a bug
        
    }
    return 0;
}


2019-09-26 15:34:10.146480+0200 FoundationHasFallen[91673:242685] Data
2019-09-26 15:34:10.146697+0200 FoundationHasFallen[91673:242685] Mutable Data
2019-09-26 15:34:10.146735+0200 FoundationHasFallen[91673:242685] Data
2019-09-26 15:34:10.151079+0200 FoundationHasFallen[91673:242685] Mutable Data
2019-09-26 15:34:10.151098+0200 FoundationHasFallen[91673:242685] Mutable Data

It has never been safe to examine the dynamic class of an object to detect the difference between mutable and immutable. For example, data objects may be represented by an instance of some private internal class which uses a flag to govern its mutability. In order to be usable as either an immutable or mutable data object, that internal class would have to derive from NSMutableData. (This is not hypothetical, it's actually how some Foundation classes have actually been implemented historically.)


The secure coding round-trip issue does sound like a problem with this, though.

Regarding bookmarkDataWithOptions:… returning a NSMutableData "contrary" to what its prototype states, I'm not really suprised. But I'm a bit disappointed that there are still cases like that nowadays considering all the annoying changes made in the Cocoa APIs to make Swift happy.


I'm more annoyed by the last copy not returning a real NSData because this then requires to re-create a NSData with initWithBytes:length: .