I have an object containing various NSString objects and variables which I us NSCoding to archive to a file on the disk and later unarchive. So far everything has been working perfectly.
Today, I wanted to add an NSMutableArray to the object and tried to encode using the:
[encoder encodeObject:myArray ForKey:#"myArray"];
and later decode it using:
[self setMyArray:[decoder decodeObjectForKey:#"myArray"]];
It doesn't appear to be working, and while I don't get any errors in the encoding or decoding itself, I do get an error if I try to modify the value of the array after decoding from the file.
I'm sure I'm doing something completely wrong here, but not entirely certain what. I'm thinking perhaps it may have something to do with it not properly allocing during the unarchive.
Anything look blatantly obvious as the source of the problem?
It doesn't appear to be working, and while I don't get any errors in
the encoding or decoding itself, I do get an error if I try to modify
the value of the array after decoding from the file.
Decoding an archive gives you immutable objects regardless of whether they were mutable or immutable when you encoded them. You're not doing anything particularly wrong -- it's working as advertised.
See this answer for another example of a similar problem, and a solution:
[self setMyArray:[[decoder decodeObjectForKey:#"myArray"] mutableCopy];
Related
My goal is to extract the localization keys and strings from a Base.lproj's .nib files.
While most compiled nib files use the binary plist format, I ran into a few that are in a different format, where the file starts with "NIBArchive".
An example (in macOS Monterey) is the file at:
/System/Library/CoreServices/Finder.app/Contents/Resources/Base.lproj/ClipWindow.nib
For "bplist" files, I can easily read them via CFPropertyListCreateFrom… into a NSDictionary, and then find the translatable strings therein (inside the "$classes" entry they're always three consecurity dict, string and string entries, with the dict containing the keys "NS.string", "NSKey" and "NSDev", and the following strings being the key and value of a translation entry, similar to what .strings files contain).
The NIBArchive, however format doesn't seem to be documented anyway. Has anyone figured out how to decode the entries in a meaningful manner so that I could find the translation items in them? Or convert them into the bplist format?
Note that this kind of file is a compiled nib, and ibtool won't work because it gives the error: "Interface Builder cannot open compiled nibs".
I am working with random .nib files, for which I don't know the implementation specifics. All I want is to extract are the .strings contents that were originally compiled into the Base localization file.
I had googled for this format before but found nothing. Now, with a slightly modified search, I ran into some answers.
My best hope to solving this so far is this format description, determined through reverse-engineering:
https://github.com/matsmattsson/nibsqueeze/blob/master/NibArchive.md
I can build a parser based on this, but still wonder if there are easier ways.
Another possible solution is to use NSKeyedUnarchiver to decode the data, after loading it into a NSNib object, as suggested here:
https://stackoverflow.com/a/4205296/43615
This method of decoding keyed archives of unknown types is also shown in the PlistExplorer project:
https://github.com/karstenBriksoft/PlistExplorer
It seems https://github.com/kam800/MachObfuscator does include a NIBArchive-reader NibArchive+Loading written in Swift.
I want to guess a received NSData's encoding. I searched in Stackoverflow and found one answer here which indicates "can't".
However, I noticed a NSString method stringWithContentsOfFile:usedEncoding:error:, and I wanted to know whether I can achieve this goal in sequence below:
1> Get an NSData object
2> Store this NSData object into a file with random file name in directory /tmp
3> Call NSString's stringWithContentsOfFile:usedEncoding:error: method to read from this temporary file.
4> Delete the temporary file.
5> Read the enc parameter to determine the encoding
I know I can experiment by myself, but I have no various data source with different encoding in my hand. Therefore I raised a question here. Could my opinion work? Could this solution find every possible encoding OS X could recognized?
In an encryption tool I am nearly finished with, I can't seem to write the encrypted data to a file.
Here is what I have:
NSData *encryptedData = [data AES256EncryptWithKey:key];
[encryptedData writeToFile:#"~/Desktop/file.txt" atomically:YES];
If 'file.txt' is not found, it should create it.
Thank You
First, -writeToFile:atomically: is the name of the method you are trying to use-- not, as you have written, -writeToFile:automatically:. And second, this method should usually be avoided in favor of one that takes an out NSError parameter.
Try -writeToFile:options:error: if you'd like to be able to log a useful diagnostic when something goes wrong.
I've come across a resource that I would like to use, but I'm not sure how to proceed. The resource is a plist and one of the keys holds an NSData object. However, I don't know what the NSData represents. Is there a way to figure out how I should decode the NSData object to be able to read its contents?
So I assume you can't ask the provider of the resource what the data is for? Try dumping the data out to a file using -writeToFile:atomically:. Then you can use the file command-line tool to see if it knows what format the file is in. Or you can use xxd to look at the bytes and see if you recognise the format. There's no foolproof way to go from 'arbitrary set of bytes' to 'understanding of the context of those bytes', you either need to recognise it or ask someone.
Is there a way to unfilter an NSPasteboard for what the source application specifically declared it would provide?
I'm attempting to serialize pasteboard data in my application. When another application places an RTF file on a pasteboard and then I ask for the available types, I get eleven different flavors of said RTF, everything from the original RTF to plain strings to dyn.* values.
Saving off all that data into a plist or raw data on disk isn't usually a problem as it's pretty small, but when an image of any considerable size is placed on the pasteboard, the resulting output can be tens of times larger than the source data (with multiple flavors of TIFF and PICT data being made available via filtering).
I'd like to just be able to save off what the original app made available if possible.
John, you are far more observant than myself or the gentleman I work with who's been doing Mac programming since dinosaurs roamed the earth. Neither of us ever noticed the text you highlighted... and I've not a clue why. Starting too long at the problem, apparently.
And while I accepted your answer as the correct answer, it doesn't exactly answer my original question. What I was looking for was a way to identify flavors that can become other flavors simply by placing them on the pasteboard AND to know which of these types were originally offered by the provider. While walking the types list will get me the preferred order for the application that provided them, it won't tell me which ones I can safely ignore as they'll be recreated when I refill the pasteboard later.
I've come to the conclusion that there isn't a "good" way to do this. [NSPasteboard declaredTypesFromOwner] would be fabulous, but it doesn't exist.
-[NSPasteboard types] will return all the available types for the data on the clipboard, but it should return them "in the order they were declared."
The documentation for -[NSPasteboard declareTypes:owner:] says that "the types should be ordered according to the preference of the source application."
A properly implemented pasteboard owner should, therefore, declare the richest representation of the content (probably the original content) as the first type; so a reasonable single representation should be:
[pb dataForType:[[pb types] objectAtIndex:0]]
You may be able to get some use out of +[NSPasteboard typesFilterableTo:]. I'm picturing a snippet like this:
NSArray *allTypes = [pb types];
NSAssert([allTypes count] > 0, #"expected at least one type");
// We always require the first declared type, as a starting point.
NSMutableSet *requiredTypes = [NSMutableSet setWithObject:[allTypes objectAtIndex:0]];
for (NSUInteger index = 1; index < [allTypes count]; index++) {
NSString *aType = [allTypes objectAtIndex:index];
NSSet *filtersFrom = [NSSet setWithArray:[NSPasteboard typesFilterableTo:aType]];
// If this type can't be re-created with a filter we already use, add it to the
// set of required types.
if (![requiredTypes intersectsSet:filtersFrom])
[requiredTypes addObject:aType];
}
I'm not sure how effective this would be at picking good types, however.