Working With Property Lists In Swift — Part 1

A sample Plist file and a custom type

To start, suppose that we have the following property list file in the app’s bundle called DefaultShape.plist. Its purpose is to contain the default data regarding hypothetical shape types:

  • backgroundColor and borderColor are Strings representing colors as Hex values.
  • isInteractive is a Boolean value, indicating whether a shape will be interacting on user actions or not.
  • patternImage is a Data value and its purpose is to store the actual data of an image that can be used as a background pattern on the shape.
struct CustomShape {
var width: CGFloat = 0
var height: CGFloat = 0
var backgroundColor: String = "000000"
var borderColor: String = "000000"
var borderWidth: CGFloat = 0
var cornerRadius: CGFloat = 0
var isInteractive: Bool = false
var patternImage: Data = Data()
}

Decoding a property list with Codable type

Codable is not a real protocol itself in Swift. Instead, it’s the combination of two other protocols, Encodable and Decodable. With those two, it’s easy to encode and decode a native custom Swift type to and from a specific data format respectively, such as JSON and property list.

struct CustomShape: Codable {
...
}
init(withPlistAt url: URL) {
do {

} catch {
print(error.localizedDescription)
}
}
let plistData = try Data(contentsOf: url)
self = try PropertyListDecoder().decode(CustomShape.self, from: plistData)
init(withPlistAt url: URL) {
do {
let plistData = try Data(contentsOf: url)
self = try PropertyListDecoder().decode(CustomShape.self, from: plistData)
} catch {
print(error.localizedDescription)
}
}
guard let defaultShapeURL = Bundle.main.url(forResource: "DefaultShape", withExtension: "plist") else { return }

var shape = CustomShape(withPlistAt: defaultShapeURL)

Encoding to property list

Let’s see now how we can perform the opposite and save an instance of the CustomShape type as a plist file. Suppose that we set new values to some properties which we want to store persistently:

shape.width = 500
shape.height = 250
shape.backgroundColor = "ff0000"
shape.borderWidth = 5
shape.cornerRadius = 15
func save(as name: String) {

}
func save(as name: String) {
let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
.appendingPathComponent(name)
.appendingPathExtension("plist")

}
let encodedData = try PropertyListEncoder().encode(self)
try encodedData.write(to: saveURL)
func save(as name: String) {
let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
.appendingPathComponent(name)
.appendingPathExtension("plist")

do {
let encodedData = try PropertyListEncoder().encode(self)
try encodedData.write(to: saveURL)
} catch {
print(error.localizedDescription)
}
}
shape.save(as: "myShape")

Summary

In this post I showed you how to decode data from property list files into a custom type, and encode and save back to plist as well. All that using the Codable type, PropertyListEncoder and PropertyListDecoder APIs. However, things are not always ideal, and you may want to avoid including all properties in an encoding or decoding process. Or, you may have properties of data types that cannot be encoded or decoded at all. All that are being discussed in the second post about property lists in Swift. Don’t miss it!

An iOS & macOS app maker writing code in Swift. Author of countless programming tutorials. Content creator. https://serialcoder.dev

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store