NSMutableDictionary getObjects_andKeys_

I’m working on an app that uses a NSMutableDictionary to store a key value pair. I would like to get the data out of the dictionary and printed to a file with both keys and values. I have been trying to make getObjects_andKeys_ work for me but can seem to get the terminology correct. The documentation states that it “Returns by reference C arrays of the keys and values in the dictionary”. Maybe I’m not dealing with this correctly or am I misusing the dictionary and should be using something else?

Can anyone direct me on how to get keys and value pairs out of a dictionary??

You should look into either one of these methods of NSDictionary:

- (BOOL)writeToURL:(NSURL *)aURL atomically:(BOOL)flag
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag

NSMUtableDictionary being a subclass, it is fully compatible. You can use any extension you wish, and retrieve the file’s contents with these methods:

+ (id)dictionaryWithContentsOfURL:(NSURL *)aURL
+ (id)dictionaryWithContentsOfFile:(NSString *)path

But they create an immutable dictionary, you’ll need to use the mutableCopy method to save it inside an NSMutableDictionary object.

Of course, this will only work with standard objects: NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary. Other than that you need to create custom encoders or convert the data to NSData, which is a bit more complex.

Does this answer your question?

Browser: Safari 537.78.2
Operating System: Mac OS X (10.8)

I have tried writing automatically to a file earlier with…

theDict's writeToFile_atomically_((path to desktop as string) & "theFile.txt", true)

…but never see the file… and no error.

My keys are being created automatically so I wont know what the are but need them with the value to have any meaning. Values are being continuously updated on the keys.

I see I can get just the keys with…

set myKeys to theDict's allKeys() as list

Then maybe step thru each one to get the value for that known key…

AppleScriptObjC expects always POSIX paths, and writeToFile of NSDictionary writes out in property list format


theDict's writeToFile_atomically_((POSIX path of (path to desktop) & "theFile.plist"), true)

You should resolve the path before you put it inside the method, something like this:

set filePath to ((path to desktop as string) & "theFile.txt") as string
tell me to log filePath
theDict's writeToFile_atomically_(filePath, true)

Coercing applescript types inside an Objective C method is not always fruitful. It has to be a simpler object for ObjC method to be able to convert it, in my experience.

Plus, you should log the result of the filePath (like I did in the example), see if it is a comma-separated file path (Finder style) or slash-separated path (POSIX style). You need the latter for this to work, I just never remember which one the applescript version returns. Check also if there is a separator between the path to desktop and the filename, you never know.

By the way, the correct way in Objective C to get the path to desktop is this:

NSArray* paths = NSSearchPathForDirectoriesInDomains ( NSDesktopDirectory, NSUserDomainMask, NO );
NSString *theDesktopPath = [paths objectAtIndex:0];

But not sure if it is possible to translate this to AppleScriptObjC, NSSearchPathForDirectoriesInDomains being a function and all… Search these forums on how to get a POSIX-style path in ASOC or convert Finder-style paths to POSIX-style paths, just to be sure. It has been covered in the past for sure.

Setting the file path to POSIX path created the file but I guess I’m getting more than what I want with all the tags…

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Convert Items</key>
	<integer>10</integer>
	<key>Diversified Items</key>
	<integer>6</integer>
	<key>Model Downloader</key>
	<integer>6</integer>
	<key>idleAppTime</key>
	<integer>11</integer>
</dict>
</plist>

… Basically all I need is tab and returns separating the items. I’m not seeing how pulling it back into another dictionary is going allow me to work with it to create the format I want in a text document for importing into a db. When I write to a file I just want to keep it simple with.
key value
key value
key value

Oh, well then that’s different. You didn’t mention wanting a tab-delimited file.

That’s rather easy. You need to cycle through the objects in your NSArray of NSDictionary and input each one as a sequence like this

the key + a tab + the value + a return

inside an NSMutableString, which you then save with NSString’s writeToFile:atomically:encoding:error: or writeToURL:atomically:encoding:error: methods using a .txt extension.

I’m sure there’s examples lying around in these forums.

Good luck!

How to get the keys out along with the value was what I’m was asking… I’m getting it to do what I want with the following code but still think there probably was an easier way to get the key and value in one shot.


set myKeys to theDict's allKeys() as list
 set logData to {}
   repeat with i in myKeys
      set thisKey to i as string
      copy thisKey & tab & theDict's valueForKey_(thisKey) to end of logData
    end repeat
       set applescript's text item delimiters to return
       set logData to logdata as string
        
        tell application "Finder"
        set theFile to (open for access file ((path to desktop as string) & "theFile.txt") with write permission)
        write logData to theFile
        close access theFile
        end tell

Again, you’re mixing plain Applescript and ASOC in a way that might cause problems. One thing that is important when mixing both is to coerce, coerce, coerce. Try this (untested):

set myKeys to theDict's allKeys() as list
set logData to "" -- no need for a list. A string will do fine.
repeat with currentKey in myKeys
set thisKey to currentKey as string
set theValue to (theDict's valueForKey_(thisKey)) as string -- coercing an NSString object to a plain applescript string is mandatory here. I am assuming the values in your NSDictionary are NSStrings of course.
set logData to (logData & (thisKey & tab & theValue & return)) as string -- this way applescript only deals with native AS strings.
end repeat
--Just so you know, you need to save the text item delimiter before changing it and return it to what it was before, you might end up causing problems down the road otherwise.
--But this is no longer necessary because a string is used instead for logData
--set {oldATID, applescript's text item delimiters} to {applescript's text item delimiters, return}
--set logData to logdata as string 
--set applescript's text item delimiters to oldATID
set logData to (character 1 thru -2 of logData) as string -- (to remove the last return character. Try -1 if it doesn't work, I may be mistaken here.

-- For this part I would strongly recommend using ASOC instead of plain Applescript. There is for sure an example already in these forums somewhere.
tell application "Finder"
set theFile to (open for access file ((path to desktop as string) & "theFile.txt") with write permission)
write logData to theFile
close access theFile
end tell

Unfortunately that’s one method you can’t use from ASObjC. Instead, get the keys with allKeys() and the objects with allValues().