Ok, I have my two table sample working great, So now I want to save the table data.
I try saving it to user defaults simply but realized I have set my record to contain image objects
set theValue to NSWorkspace's sharedWorkspace()'s iconForFile_(newFilepath)
set theNewTableValues to {{fileicon:theValue, filename:newFilename, pathtofile:newFilepath, filesize:"---"}} & theOldTableValues
This creates weird corrupt plist files. So I remove the images and it all works.
Then I try adding in the images at run time and removing them at quit. That works but the defaults plist is being written to during runtime and the odd plist files are created as I add rows to the table etc…
So forget User defaults. Can I write these records to file somehow, including the image objects? Remember we are dealing with a record here…
I have tried to convert it to NSMutableArray with no luck. This is an OBJ-C area that really confuses me.
I also read that you can have a datasource for a table that uses bindings but can’t get that to work so far. I figured I could then use the table datasource methods to set the images as Craig does in booklist example.
So close again but not sure of what direction to take this. Any guidance appreciated.
It isn’t the image that causes the corrupted plist file. It is the open panel!
my plist file name is normally
com.rdutoit.backuplistc.plist
When the open panel gets called:
set openPanel to current application's class "NSOpenPanel"'s openPanel()
tell openPanel
set allowsMultipleSelection of it to true
set canChooseDirectories of it to true
set allowsOtherFileTypes of it to true
runModal()
set fileUrl to |URL| of it
if fileUrl is missing value then
return
end if
set newFilepath to |path| of fileUrl as text -- Error occurs without 'as text'
end tell
When I press the “add” button it triggers the above open panel call. At that moment and after accepting a choice in the open panel, endless new defaults plist files are generated with a names like
com.rdutoit.backuplistc.plist.7gSYoM7
com.rdutoit.backuplistc.plist.0XVtcPM
etc.
They are corrupted files!
I suspect something odd is happening with the URL word?
Anyone have a clue here.
I am suing this for defaults write:
-- on Awake from nib
tell NSUserDefaults of current application
tell its standardUserDefaults()
set storedDataArray to its arrayForKey_("theArrayRecord")
set my theData to storedDataArray
if my theData is in {"", missing value} then set my theData to {{backupset:"newBackupset",sourcefiles:{}}}
end tell
end tell
-- on quit
tell NSUserDefaults of current application
tell its standardUserDefaults()
its setObject_forKey_( my theData, "theArrayRecord")
end tell
end tell
Not really sure of why you have a problem but I have used this snippet without any problems:
It may help
All the best
Terry
tell class "NSOpenPanel" of current application to set myOpenPanel to its openPanel
myOpenPanel's setAllowsMultipleSelection_(false)
myOpenPanel's setCanChooseFiles_(true)
myOpenPanel's setCanChooseDirectories_(false)
myOpenPanel's runModal
set tFileArray to myOpenPanel's filenames()
set tFilepath to tFileArray's objectAtIndex_(0)
tell MyView to setImageWithPath_(tFilepath)
Hi All,
Back with my two tables experiment. All is well and I am trying to now save the table data. USer defaults weren’t working for reasons I posted earlier so I tried “writeToFile” which seems to be working. Here it reads in the file and then writes out.
on awakeFromNib()
set theNewArray to NSMutableArray's alloc()'s initWithContentsOfFile_(FILE_PATH)
if theNewArray is equal to missing value then
set theNewArray to NSMutableArray's alloc()'s init()
set theData to {{backupset:"newBackupset", sourcefiles:{}}}
theNewArray's addObjectsFromArray_(theData)
set my theData to theNewArray
else
--workaround for empty image column. We set the images one by one!
set my theData to theNewArray
my addImagesAfterArchiving()
end if
set my theData to my theData
end awakeFromNib
on writeToFile()
set theNewAnotherArray to NSMutableArray's alloc()'s init()
theNewAnotherArray's addObjectsFromArray_(my theData)
if not theNewAnotherArray's writeToFile_atomically_(FILE_PATH, true) then
set messageText to "There was an error writing to file"
display dialog messageText buttons {"Ok"} default button 1
end if
end writeToFile
What confuses me is I am using a record but then it gets turned into an array so it will archive. This seems to work. One little bug though is if you add a new set to table one and try to quit without editing the set name, it throws the “WriteToFile” error and doesn’t retain the new entry.
on addSets_(sender)
set my theData to {{backupset:"newBackupset", sourcefiles:{}}} & my theData
set my theData to my theData
end addSets_
Somehow the new entry is seen as something foreign by writeToFile_atomically?
It isn’t the end of the world but makes me nervous. Any thoughts appreciated, or thoughts about a better archiving method.
Try logging the value of theNewAnotherArray when you get the error. My guess is that having sourcefiles as {} is causing the problem, although I can’t see an obvious alternative.
on applicationShouldTerminate_(sender)
--before archiving, we need to clear out all the image objects
my removeImagesBeforeArchiving()
my writeToFile()
return true
end applicationShouldTerminate_
on removeImagesBeforeArchiving()
set theOldArraysValues to Backset's arrangedObjects()
repeat with i from 1 to count of theOldArraysValues
set theSourceItems to Backset's arrangedObjects()'s objectAtIndex_(i - 1)'s valueForKey_("sourcefiles")
repeat with j from 1 to count of theSourceItems
set theSourceItemsObject to theSourceItems's objectAtIndex_(j - 1)
--here we remove the image and set fileicon to ""
theSourceItemsObject's setValue_forKey_("", "fileicon")
end repeat
end repeat
log theOldArraysValues
end removeImagesBeforeArchiving
You can see that, on terminate, the images are removed so the array can be archived (I tried NSCoding etc. with no luck.)
So when a new item is added to table 1 and you quit without editing that items name, it returns the array with images in it even though removeImagesBeforeArchiving() is called. Then the error happens. When you edit the new item in table 1 or do anything there, it returns the image-less array which is archived fine.
I have tried numerous ways of triggering the array into the current form but no luck yet.
on writeToFile()
set theCurrentArrayValues to Backset's arrangedObjects()
set theNewAnotherArray to NSMutableArray's alloc()'s init()
theNewAnotherArray's addObjectsFromArray_(theCurrentArrayValues)
if not theNewAnotherArray's writeToFile_atomically_(FILE_PATH, true) then
set messageText to "There was an error writing to file"
display dialog messageText buttons {"Ok"} default button 1
end if
end writeToFile
That makes sense since I change the images to “” in Backset’s arrangedObjects(). It is theData variable that isn’t getting updated yet.
What I don’t understand is why this doesn’t work as well:
on writeToFile()
set theCurrentArrayValues to Backset's arrangedObjects()
if not theCurrentArrayValues y's writeToFile_atomically_(FILE_PATH, true) then
set messageText to "There was an error writing to file"
display dialog messageText buttons {"Ok"} default button 1
end if
end writeToFile
Isn’t Backset’s arrangedObjects() an array? Why do I have to create new array and then add that to it to pass to writeToFile?
Well, It’s solved now. The archive works and the table bindings are incredibly fast, even with dozens of files and images added and with hardly any code!
Now if I can only add drag and drop to the table - so far no luck. There are six datasource methods! I may have to make aOBJ-C class for that one.
I thought of that. I think I read somewhere that NSAArrayController’s arrangedObjects returns a plain Array… though you can change the values of it with setValue_forKey_ so maybe not. Is there a way in cocoa to log what class something is?
Or perhaps we need to pass the writeToFile an new instance of the Array and not the results of the array controller itself?