Swift Snippets 3: Preference Files, Property Lists, JSON

Preference files

Write and read key-value pairs for a preference file
<key>myBooleanSetting</key>
<false/>
For each, Save code is used when writing the preference file, and Set code is run in viewDidLoad()

Save string from text box
UserDefaults.standard.setValue(textPredicate1.stringValue, forKey: "textPredicate1")
Set
if let str = UserDefaults.standard.string(forKey: "textPredicate1") {
textPredicate1.stringValue = str
} else {
textPredicate1.stringValue = "Big"
}

with the default value Big

Save popup selection
UserDefaults.standard.set(popupTimeUnits.indexOfSelectedItem, forKey: "popupTimeUnits")
Set
let theInt = UserDefaults.standard.integer(forKey: "popupTimeUnits")
popupTimeUnits.selectItem(at: theInt)
theTimeSelStr = (popupTimeUnits.selectedItem?.title)!

the last line setting a tracking variable.

Save checkbox state
if (checkInfoout.state == NSOnState) {
UserDefaults.standard.setValue(true, forKey: "checkInfoout")
} else {
UserDefaults.standard.setValue(false, forKey: "checkInfoout")
}

Set
filterTMbutton.state = NSOnState
let b1prefs = UserDefaults.standard.bool(forKey: "checkInfoout")
if b1prefs == true { checkInfoout.state = NSOnState } else { checkInfoout.state = NSOffState }

the first line setting a default.

Save radio button group state
if (filterTMbutton.state == NSOnState) {
UserDefaults.standard.setValue(true, forKey: "filterTMbutton")
UserDefaults.standard.setValue(false, forKey: "filterPatternbutton")
UserDefaults.standard.setValue(false, forKey: "filterOtherbutton")
} else {
UserDefaults.standard.setValue(false, forKey: "filterTMbutton")
if (filterPatternbutton.state == NSOnState) {
UserDefaults.standard.setValue(true, forKey: "filterPatternbutton")
UserDefaults.standard.setValue(false, forKey: "filterOtherbutton")
} else {
UserDefaults.standard.setValue(false, forKey: "filterPatternbutton")
UserDefaults.standard.setValue(true, forKey: "filterOtherbutton")
}
}

for each in a group of three
Set
filterTMbutton.state = NSOnState
let b1prefs = UserDefaults.standard.bool(forKey: "filterTMbutton")
if b1prefs == true { filterTMbutton.state = NSOnState } else { filterTMbutton.state = NSOffState }

the first line setting a default.

Property lists

Using property list files to store data.

A dictionary to contain properties
var SetsDict = [ : ] as [String : Any]

Update controls from values held in dictionary
func dictUpdate() {
if ((SetsDict["Repeat"] as! Int) == 1) {
repeatCheck.state = NSOnState
} else {
repeatCheck.state = NSOffState
}
qosPopup.selectItem(at: (SetsDict["QoS"] as! Int))
commandText.stringValue = SetsDict["Command"] as! String
repeatNum.stringValue = "\(SetsDict["Period"] as! Int)"
}

For a new, empty dictionary, set some starting defaults (or load from Preferences)
if (SetsDict.isEmpty) {
SetsDict["Command"] = ""
SetsDict["Repeat"] = 1
}
dictUpdate()

Ensure each view control syncs dictionary value, e.g.
@IBAction func repeatTextAct(_ sender: Any) {
SetsDict["Period"] = repeatNum.integerValue
}

NSDocument needs its own empty dictionary
var theDict = [:] as [String : Any]
then to create view controller dictionary
override func makeWindowControllers() {
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let windowController = storyboard.instantiateController(withIdentifier: "Document Window Controller") as! NSWindowController
self.addWindowController(windowController)
let theVC = self.windowControllers[0].contentViewController as? ViewController
if !(theDict.isEmpty) {
theVC?.SetsDict = theDict
theVC?.dictUpdate()
}
}

In NSDocument, to write dictionary out to a URL
override func write(to url: URL, ofType typeName: String) throws {
if let theVC = self.windowControllers[0].contentViewController as? ViewController {
let theNSDict = theVC.SetsDict as NSDictionary
} else {
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}
}

NSDocument function to read in dictionary from a URL
override func read(from url: URL, ofType typeName: String) throws {
if (typeName != "") {
theDict = NSDictionary.init(contentsOf: url) as! [String : Any]
} else {
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}
}

Given a path to a property list file containing a nested dictionary of dictionaries, parse the innermost dictionary contents
let theDict = NSDictionary.init(contentsOfFile: path)
if ((theDict?.count)! > 0) {
let theDict2 = theDict?["OuterKey"] as! NSDictionary
if (theDict2.count > 0) {
for (_, value) in theDict2 {
let theDict3 = value as! NSDictionary
let theCount3 = theDict3.count
if (theCount3 > 0) {
let theString = theDict3["innerKey"] as! String
}
}
}
}

JSON

Handling JSON data.

Convert JSON data read as data to structured array of dictionaries
let json = try? JSONSerialization.jsonObject(with: data, options: [])

Once data is serialised, iterate through array of dictionaries, analysing entries in each
let jsonArray = json as? NSArray
for jsonObj in jsonArray! {
let jsonDict = jsonObj as? NSDictionary
let jsonKey1 = jsonDict?.object(forKey: "keystring1") as! String
if jsonKey1.contains("search string") {
}
}

Swift Snippets 0: Introduction and Contents