I have a large binary resource in my code, converted to an array using a bin2c type program.
Previously, we are using [NSData dataWithBytes:raw length:rawLength]
to read the resource (for example).
This is a very large array (>32KB) and the whole procedure around loading and using this resource is slow at the moment so I am trying to make time savings where I can (no I haven't explicitly profiled the copy vs noCopy at this time).
I am just wondering, since dataWithBytesNoCopy:
takes a void*
and not const void*
, does this mean it is not safe to use this from a constant source (in this case it is compiled into the program executable).
I don't think it is an oversight from the NSData developers since initWithBytes:
and dataWithBytes:
both take const void*
as the parameter - what (if anything) does NSData do to the input data when not const, considering that NSData itself is immutable?
I wonder if perhaps the parameter defined as not const
for forward compatibility with NSMutableData?
In theory, [NSData dataWithBytesNoCopy:…] is mapped to CFDataCreateWithBytesNoCopy() or similar low-level function, whose documentation describes a little more about how it treats original bytes:
Discussion
This function creates an immutable CFData object from a buffer of unstructured bytes. Unless the situation warrants otherwise, the created object does not copy the external buffer to internal storage but instead uses the buffer as its backing store. However, you should never count on the object using the external buffer since it could copy the buffer to internal storage or might even dump the buffer altogether and use alternative means for storing the bytes.
In other words, buffer may be copied, and you can't rely on "propagation" of changes to original buffer to NSData, but that is not the problem. Original question is still unanswered: whether it would modify original bytes in-place (although the hint may be pretty obvious now).
UPDATE:
If situation permits, you may load NSData only once, and then just copy it in hot loop (copy is cheap, because NSData is immutable and shares contents).
static const char *myBytes = "myBytes here...";
static NSData *myData = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
myData = [[NSData alloc] initWithBytes:myBytes length:strlen(myBytes)]; // EDIT: still need to copy to be clean
});
for (int i = 0; ; i++) {
NSData *hotLoopData = [myData copy];
NSData *hotLoopData = [[NSData alloc] initWithData:myData];
}