In my document based application I saved and reloaded the data in OS 10.6 via the method “NSPropertyListSerialization”. It worked well.
It does not in OS 10.7 (Lion). So I changed the method to “NSKeyedArchiver” and “NSKeyedUnarchiver” (as Shane teached me). It works well too.
But now I have the problem to read in the Data saved in OS 10.6 to OS 10.7.
ErrMess.:
Appname(912,0xace542c0) malloc: reference count underflow for 0x1aeb910, break on auto_refcount_underflow_error to debug.
2011-08-01 18:46:59.956 Appname[912:f0b] *** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive version (-1)
Does anyone know a way to convert the data in a readable form?
here are my script parts. Some of the words are in german language, but I think you can detect the structure.
on dataOfType_error_(typeName, outError)
set theFormat to 100 -- kCFPropertyListXMLFormat_v1_0
set theOptions to 0 -- default
set theError to missing value
set outError to missing value
-- First collecting the properties:
set dieSchuelerDaten1 to kDataSource -- 1. data source
-- die Spaltentitel --- headerCells in table view
set theTableColumns to kTableView's tableColumns as list
set theTitleList to {}
repeat with aColumn in theTableColumns
set theTitle to (aColumn's headerCell's stringValue)
set theTitleList to (theTitleList & theTitle)
end repeat
set dieSpaltenTitel to theTitleList
---------------------------
-- some others:
set dieKopfzeile to kopfzeile
set dieAnzahlSpalten to kTableView's numberOfColumns()
set dieNamenEinfuegung to namenEingefuegt
set dieStufenart to stufenart
set dieVerteilungsBestimmung to verteilungBestimmt
set dieArtDerVerteilung to verteilungFeld's stringValue()
set dieMaxPunkte to maxPunkteFeld's intValue()
set dieSicherungGrenze5 to grenze5Feld's intValue()
set dieSicherungGrenze6 to grenze6Feld's intValue()
-- pushbuttons:
set dieSicherungBonusMalus to pbBewertungAls's indexOfSelectedItem as integer
set dieSicherungRelAbsG5 to pbRelAbs5's indexOfSelectedItem as integer
set dieSicherungRelAbsG6 to pbRelAbs6's indexOfSelectedItem as integer
set dieSicherungVerteilungNach to pbVerteilungNach's indexOfSelectedItem as integer
set dieSicherungSchwerpunkt to pbSchwerpunkt's indexOfSelectedItem as integer
set dieSicherungVerteilung to pbberechneVerteilung's indexOfSelectedItem as integer
set dieSicherungFormat to pbFormat's indexOfSelectedItem as integer
-- 2. table view, depending of users choice:
if (stufenart as string) is "oberstufe" then
set dieSchuelerDaten2 to noDataSource
else if (stufenart as string) is "u_m_stufe" then
set dieSchuelerDaten2 to nuDataSource
else if (stufenart as string) is "" then
set dieSchuelerDaten2 to {}
end if
-- and now putting all together:
set myData to {ergebnisse1:dieSchuelerDaten1, spalten:anzahlSpalten, spaltenTitel:dieSpaltenTitel, kopfzeile:dieKopfzeile, NamenEinfuegung:dieNamenEinfuegung, maximalePunkte:dieMaxPunkte, VerteilungsBestimmung:dieVerteilungsBestimmung, SicherungGrenze5:dieSicherungGrenze5, SicherungGrenze6:dieSicherungGrenze6, SicherungRelAbsG5:dieSicherungRelAbsG5, SicherungRelAbsG6:dieSicherungRelAbsG6, SicherungBonusMalus:dieSicherungBonusMalus, SicherungVerteilungNach:dieSicherungVerteilungNach, SicherungSchwerpunkt:dieSicherungSchwerpunkt, SicherungVerteilung:dieSicherungVerteilung, SicherungFormat:dieSicherungFormat, ergebnisse2:dieSchuelerDaten2, dieStufenart:stufenart, dieArtDerPunkte:ArtDerPunkte, SicherungArtDerVerteilung:dieArtDerVerteilung}
-- build the property list:
set theData to current application's class "NSPropertyListSerialization"'s dataWithPropertyList_format_options_error_(myData, theFormat, theOptions, theError)
if outError is not missing value then
set contents of outError to my NSError's errorWithDomain_code_userInfo_(my NSOSStatusErrorDomain, my unimpErr, missing value)
end if
return theData
end dataOfType_error_
-- 2. part.
on readFromData_ofType_error_(theData, typeName, outError)
set theFormat to missing value --? otherwise error message!
set theOptions to 0 -- default
set theError to missing value --outError
set outError to missing value
set propertyList to current application's class "NSPropertyListSerialization"'s propertyListWithData_options_format_error_(theData, theOptions, theFormat, theError)
-- read back:
set anzahlSpalten to propertyList's spalten
set spaltenTitel to propertyList's spaltenTitel -- in
set kopfzeile to propertyList's kopfzeile -- in
set ArtDerVerteilung to propertyList's SicherungArtDerVerteilung
set stufenart to propertyList's dieStufenart
set verteilungBestimmt to propertyList's VerteilungsBestimmung
set namenEingefuegt to propertyList's NamenEinfuegung
set maxPunkte to propertyList's maximalePunkte
set wertGrenze5 to propertyList's SicherungGrenze5
set wertGrenze6 to propertyList's SicherungGrenze6
set myBonusMalus to (propertyList's SicherungBonusMalus)
set ArtDerPunkte to propertyList's dieArtDerPunkte
set relabsG5 to (propertyList's SicherungRelAbsG5) as string
set relabsG6 to (propertyList's SicherungRelAbsG6) as string
set dieverteilungnach to (propertyList's SicherungVerteilungNach) as string
set derschwerpunkt to (propertyList's SicherungSchwerpunkt) as string
set berechneDieVerteilung to (propertyList's SicherungVerteilung) as string
set dasformat to (propertyList's SicherungFormat) as string
set mykDataSource to propertyList's ergebnisse1 -- data source 1
set myTheDataSource to propertyList's ergebnisse2 -- data source 2
set dataloaded to true
-- if true then rebuilding in 'windowDidBecomeMain_(aNotification)'
if outError is not missing value then
set contents of outError to my NSError's errorWithDomain_code_userInfo_(my NSOSStatusErrorDomain, my unimpErr, missing value)
end if
return true
end readFromData_ofType_error_
errmess.:
2011-08-02 11:30:35.832 Schulnoten 2.2[489:f0b] *** -[MyDocument readFromData:ofType:error:]: unable to set argument 5 - the type o^@ is not supported. (error -10000)
set propertyList to current application's class "NSPropertyListSerialization"'s propertyListWithData_options_format_error_(theData, 0, theFormat, missing value)
Setting a variable to missing value and then using the variable probably won’t work.
Als, the two “if outError …” blocks might as well be deleted; they don’t work. The last argument passed in to the handlers is a pointer to a pointer (NSError **), and AppleScriptObjC can’t do anything with them.
I wonder if there’s a problem with myData. What happens if you just set myData to something simple like {a:“a”}? Do you still get the error? Can you put in log statements to confirm where the error is happening?
on dataOfType_error_(typeName, outError)
set theFormat to 100 -- kCFPropertyListXMLFormat_v1_0
set myData to {a:"a"}
set theData to current application's class "NSPropertyListSerialization"'s dataWithPropertyList_format_options_error_(myData, theFormat, 0, missing value)
return theData
end dataOfType_error_
on readFromData_ofType_error_(theData, typeName, outError)
set propertyList to current application's class "NSPropertyListSerialization"'s propertyListWithData_options_format_error_(theData, 0, missing value, missing value)
--log propertyList
return true
end readFromData_ofType_error_
I can’t save it.
errmess:
2011-08-02 15:08:24.073 Schulnoten 2.2[1885:f0b] *** -[MyDocument dataOfType:error:]: unable to set argument 5 - the type o^@ is not supported. (error -10000)
At this stage all I can do is confirm the problem. As a work around, you could try using something like this instead:
set myData to current application's NSDictionary's dictionaryWithDictionary_(myData)
myData's writeToFile_atomically_("/Users/shane/Desktop/Test.plist", true)
set myData to current application's NSData's dataWithContentsOfFile_("/Users/shane/Desktop/Test.plist")
It’s dreadful double-handling, though. It might be better to implement it in writeToURL:ofType:error:, instead of using dataOfType:error:.
So the best solution will probably to add an Objective-C class to your project. Call it something like PLSHelper. The PLSHelper.h file should be like this:
I am sorry Shane,
all what I get is a list in hexadecimals.
But I found out that the file is to open with property list editor.
So I made a work around with an additional menu in the menu bar that calls an open window to get the path.
set theDict to current application's NSDictionary's dictionaryWithContentsOfFile_(filePath)
I was busy, but I turned in a circle.
All what I got was a list in hexas. And how do I set it into the dataOfType_error_ handler?
I tried that:
on readFromData_ofType_error_(theData, typeName, outError)
try
set theDecoder to current application's NSKeyedUnarchiver's alloc()'s initForReadingWithData_(theData)
....
stuff for decoding a newer file
...
return true
on error errmess
--if the user will open an older file then
set myHelpersData to current application's PLSHelper's dataWithPropertyListSpecial_(theData)
log myHelpersData
-- and now?
-- return false
end try
end readFromData_ofType_error_
on dataOfType_error_(typeName, outError)
set myData to {a:"a"} -- whatever
set theData to current application's PLSHelper's dataWithPropertyListSpecial_(myData)
return theData
end dataOfType_error_
So I solved it by adding a new menu that calls the following handler (in short):
on openOldFile()
try
-- open panel and file path:
set myOpenPanel to NSOpenPanel's openPanel
myOpenPanel's setCanChooseFiles_(true)
myOpenPanel's setCanChooseDirectories_(true)
myOpenPanel's setAllowsMultipleSelection_(false)
myOpenPanel's runModal
set thePath to myOpenPanel's URLs
set thePathComponents to thePath's pathComponents
set myPathComponents to item 1 of thePathComponents
set theCount to myPathComponents's |count|()
set thePath to "/"
repeat with i from 2 to (theCount - 1)
set thePath to thePath & (item i of myPathComponents as string) & "/"
end repeat
set filePath to POSIX path of (pfad & item theCount of myPathComponents)
-- read in a dictionary:
set theDict to current application's NSDictionary's dictionaryWithContentsOfFile_(filePath)
-- set the title of the new window to file name (last part of the path):
mainWindow's setTitle_(item theCount of myPathComponents as string) -- mainWindow id bound as a property to the main window
-- to get the keys of theDict: set allKeys to theDict's allKeys()
-- for example (FE) the key for the table's data source is 'tableDatas'
set myDataSource to theDict's objectForKey_("tableDatas")
myTableView's reloadData()
-- setting fields:
maxPointsField's setIntValue_(theDict's objectForKey_("maxPoints"))
-- setting popupButtons (FE):
pbMyChoice's selectItemAtIndex_(theDict's objectForKey_("myChoice") as integer)
on error errmess
display alert errmess
return false
end try
end openOldFile
After reading in, the table view and others of the window can now saved normally.
just FYI, file name and parent directory can be easier specified with Cocoa methods
set myOpenPanel to NSOpenPanel's openPanel
myOpenPanel's setCanChooseFiles_(true)
myOpenPanel's setCanChooseDirectories_(true)
myOpenPanel's setAllowsMultipleSelection_(false)
myOpenPanel's runModal -- returns a list of file URL's
set myURL to item 1 of myOpenPanel's URLs -- file URL with format file://localhost/Users/.
set thePath to myURL's |path| -- coercion to string path with format /Users/.
set fileName to thePath's lastPathComponent
set parentDirectory to thePath's stringByDeletingLastPathComponent
A slight mod of your suggested code works nicely for getting propertyListWithData working in an ASOC project.
There seems to be a genuine bug in the Lion/Applescript implementation of NSPropertyListSerialization functions.