Is it possible to have an NSdictionary where the keys are NSDates and also have it writeable/archiveable to disk?
Not using property lists, as only string keys are allowed there. You should be able to write it using NSKeyedArchiver, but that has the disadvantage of being a more opaque format. Alternatively, you could of course make a copy of the dictionary where you convert the dates to strings.
Yes, this should work just fine - and NSDate elements are also suitable for plist encoding. Might depend on the value you put in as values, though.
If you experience problems, please update your question with code.
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 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];
First post - hope I'm doing it right!
I have a file, lexicon.plist, containing an array of about 250K words. I want to load all words of length 'n' into an NSArray.
I know about the NSArray instance method:
(id)initWithContentsOfFile:(NSString *)aPath
but I don't see any way to intervene in the process of reading the file into the NSArray. The only solution I can see is to first load the entire lexicon into one NSArray, and then run through it in a loop selecting the elements of length 'n'.
I'm very new at Cocoa, but I have come across some methods that perform some sort of iterative task, that accept a "block" of code that is invoked at each iteration. I was wondering if such a functional variant of initWithContentsOfFile might exist, or how else I might iteratively read an array from a .plist file and filter the elements I'm interested in.
[And if you're wondering if this might be a case of premature optimization - it is ;-) But I'd still like to know.]
.plist files are basically XML files so you can use an NSXMLParser on it and filter out the elements of interest.
If you want to load a filtered selection of a saved data, you should use a SQL repository using SQLite, for example.
Plain files can only be fully loaded in memory.
OK, I'm feeling really REALLY stupid for asking this question, but I've managed to stump myself so hard that I doubt I have the proper detachment to figure out the answer for myself any more. My apologies in advance...
I have been playing around with bindings for a while now and LOVE them. That and the KVO/KVC conventions built into Objective-C 2.0 have allowed me to dramatically slim down my applications while increasing their reliability, flexibility, etc. I say this for no other reason than to illustrate that I am at least moderately comfortable with bindings in general. That being said, my problem is this:
I have an application where I'd like to store an editable set of keywords by way of the preferences controller. Easy, right? Unfortunately, for the life of me I can't figure out how to do it. I set up an array controller and point it to the shared preferences object and give it a keypath for the array. The problem is that the objects being stored in the array are NSStrings and I don't see how NSStrings can be KVC-compliant for this kind of operation due to the lack of any "stringValue/setStringValue" methods. Without those, what keypath do I use in the NSTableView I have set up to facilitate manipulation of that list?
Also, since the shared preferences object is not one that I own, I'm not sure how to go about setting up a new array to represent an unedited/newly installed state. (Registering them as defaults doesn't seem to be working for me.)
So to reiterate my questions more succinctly: How can you bind a table view to an array of NSStrings and how can you store said array in an application's preferences?
Any pointers or advice that you can offer would be VERY much appreciated. The headaches I'm getting from this are starting to get the better of me. :)
You don't. You hold an array of model objects, each with at least one property (that of the string), and you bind the table column through an array controller to this array, with the model key path set to that of the string property.
Assuming your app is not simply a list-of-strings editor, you probably have other things that you can move into this model class. You should do so.
I know this question is pretty old but I had a similar problem and landed to this page. I wanted to contribute with my solution.
What I need is not a big list of strings. In fact a table view looked very ugly for my needs. I then remembered another control, NSTokenField. It binds to an array of string out of the box and looks even better for small list of short strings :)
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.