hugues
1
Hello
I’m trying to access data that are in a .plist file which has the content :
<array>
<dict>
<key>AKey</key>
Value1
<key>AnotherKey</key>
Value2
<key>YetAnother</key>
Value3
…
</dict>
…
</array>
Where value can be different things :
<string>aString</string>
<integer>anInteger</integer>
<false/> or <true/>
<array> <dict>….</dict></array>
I’m sofar working on the playground
import PlaygroundSupport
let path = playgroundSharedDataDirectory.appendingPathComponent("input.pfile")
nsArray = try NSArray(contentsOf: path, error: ())
brings the Data in a array. So far so good
var item0 = nsArray![0]
gives me the content of 1rst item of the array. Looks like a dictionary
//(key "AKey", value Value1)
//…
But I can’t find how to handle item0. It is said to be of type __NSDictionaryM
let t = type(of: item0)
// __C.__NSDictionaryM.Type
But can’t be accessed by
var test = item0["AKey"]
//error: Value of type 'Any' has no subscripts
Tried Type casting to no avail. So I’m stucked
cukr
2
with plist file
<?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">
<array>
<dict>
<key>AKey</key>
<string>Value1</string>
<key>AnotherKey</key>
<string>Value2</string>
</dict>
</array>
</plist>
this code works for me
import Foundation
import PlaygroundSupport
let path = playgroundSharedDataDirectory.appendingPathComponent("input.plist")
let nsArray = try NSArray(contentsOf: path, error: ())
var item0 = nsArray[0]
var test = (item0 as! NSDictionary)["AKey"]
print(test)
The only thing I added except fixing the code you posted is type casting to NSDictionary
P.S. don't use as! in a real project, it's better to gracefully handle the errors
1 Like
hugues
3
Thanks !!!
My mistake was trying to coerce type into a Dictionary, and not to a NSDictionary, getting cryptic error message.
I still have a lot to learn before handling gracefully errors...
bzamayo
(Benjamin Mayo)
4
FYI, it is probably more elegant to parse the property list using PropertyListDecoder. Look up the documentation for Codable for more information on how to do it.
1 Like
hugues
5
I figured so also, but since my .pfile has irregularities (no same keys, arrays in value,...) I needed to fix first my type casting errors, before assimilating PropertyListDecoder.
Thanks for confirming the hint.
bzamayo
(Benjamin Mayo)
6
You can still use Codable in these cases, but you'll need to do some more custom handling compared to just writing types. If you can share a full sample plist, we can step through the necessary code. The end result will probably be cleaner than messing around with NS-typecasting stuff.
hugues
7
Actually, I am trying to clean up my Mail.app rules that are now a 5500 lines file with all the mail adresses I want to direct to specific mail boxes, that have been accumulated for a decade or two. So the plist file is the syncedRules.plist that can be found in Library/Mail/V7/SyncedRules.plist.
It's an array of rules, each rule being a dict of keys, with one being for criteria used, itself being a array of conditions, each condition a dictionary where you can find domain names. The (sofar) vague idea is to identify which domain names conditions are redundants (can be performed automatically), and maybe also obsolete (with a manual glance).
The objective is to accelerate the everyday filtering, but also to make my first real swift program :)