Using writeToFile_atomically_ to write contents of array controller?

Hi folks!

Shane’s book has been an invaluable resource. Thank god for it!

I’m building an app that has several tables bound to array controllers. Everything is working great. At the moment, in order to export it’s contents I’m using a repeat loop to write the rows to a file using a shell script (echo … >> pathtofile.txt)

I’ve been trying to use writeToFile_atomically_ by putting the array controller’s arrangedObjects into an array and feeding it to writeToFile_atomically_. The intention is to speed up the save outs and simplify the code. I also intend to read the plist files to import and simplify that process. I haven’t had much luck. Here’s what I have:


property NSMutableArray : class "NSMutableArray"
property contentArray : {}
...
set my contentArray to NSMutableArray's alloc()'s init()
set theList to myArrayController's arrangedObjects() -- this should return an array, correct?
contentArray's addObjectsFromArray_(theList)
            
set thisPath to POSIX path of (((path to preferences folder) & "save_file.plist") as string)
contentArray's writeToFile_atomically_(thisPath, true)


I previously tried simply:

myArrayController's arrangedObjects()'s writeToFile_atomically_(thisPath, true)

when I log the writeToFile_atomically_ line, it returns a 0 (zero).

What am I doing wrong?

Thanks for any help in advance!

Hi,

I recommend to use the “real” property list serialization API


set plistArray to myArrayController's arrangedObjects()
set xmlPlistFormat to current application's NSPropertyListXMLFormat_v1_0
set plistData to current application's NSPropertyListSerialization's dataWithPropertyList_format_options_error_(plistArray, xmlPlistFormat, 0, missing value)
set thisPath to POSIX path of (path to preferences folder) & "save_file.plist"
plistData's writeToFile_atomically_(thisPath, true)

Thanks for the reply!

I plugged that code in and I’m actually getting an error in my log now:

The column data in the array controller are of various things, dates (as string), strings, numbers, one holds a ref to an image. Could that be tripping it up?

thanks.

Also, if that column has no image, it is storing “missing value”.

Images cannot be stored in property list files, a workaround is to store the TIFF representation of the image as an NSData object

Ah, that’s a shame.

Thanks for your help.

Would there be a way to skip columns that are of a type that can’t be written?

Where do the images come from? Is it possible to save the URLs or paths instead of the data?

Yes! I just did it and it works! Thanks for all your help!

Follow up questions:

I need to then insert the data into a table, but I’d like to get it into a list first to do some manipulations. What is the best way of going about that?

Or if using a dictionary is the best way to handle this, how can I go through the dict entries in a repeat loop?

Heres an example of the plist:

There’s a reverse method of NSPropertyListSerialization to create the array of dictionaries from the plist file.
Then you could use a repeat loop to do your manipulations and add the objects to the array controller

I see. Is there any thread or tutorial on how you could manage this? I’ve never worked with NSDictionaries in ASOC, unfortunately ive searched Google and there seems to be slim pickings. Thanks for all your help.

In case you want to deal with Cocoa objects contrary to AppleScript records, you have to create mutable objects.
The getter is

objectForKey_()

the setter

setObject_forKey_()

Shane’s book covers the use of NSString, NSArray and NSDictionary in ASOC.

Alternatively use a custom NSObject class which is more flexible than a pure dictionary.
Define a property for each key, so you can write for example

myObject's theCost()

So this is what i have:

set thePath to current application's NSString's stringWithString_("~/Library/Preferences/PhotoSTATs Saved State/print_list.plist")
set fullPath to thePath's stringByExpandingTildeInPath()
set theDict to current application's class "NSDictionary"'s dictionaryWithContentsOfFile_(fullPath)

i’m assuming that the spaces in the path will be escaped in stringByExpandingTildeInPath.

What I get is a Dictionary. I’m stumped as to what to do with it or how to access the data.

using

tell theDict to set myDataItem to objectForKey_("theUser") as text

wouldn’t seem to work since how does it know what item to access? I’m assuming this doesnt work since its not a list.

tell theDict to set myDataItem to (item 1)'s objectForKey_("theUser") as text

Sorry for being obtuse. Not sure what I’m missing here.

your plist reveals that the root object is an array containing the dictionaries.
So get the array and use a repeat loop, something like this


set thisPath to POSIX path of (path to preferences folder) & "save_file.plist"
set plistData to current application's NSData's dataWithContentsOfFile_(thisPath)
set plistArray to current application's NSPropertyListSerialization's propertyListWithData_options_format_error_(plistData, current application's NSPropertyListMutableContainersAndLeaves, missing value, missing value)
repeat with aDictionary in plistArray
            -- do something with the dictionary
            
end
 

BINGO!

Had to do some coercion of the path string but it’s working now! A million thanks!

set thisPath to POSIX path of (((path to preferences folder) & "PhotoSTATs Saved State:print_list.plist") as string)