For the More Curious: Reading and Writing to the Filesystem

In addition to archiving and Data’s binary read and write methods, there are a few more methods for transferring data to and from the filesystem. One of them, Core Data, is coming up in Chapter 22. A couple others are worth mentioning here.

Using Data works well for binary data. For text data, String has two instance methods: write(to:atomically:encoding:) and init(contentsOf:encoding:). They are used as follows:

// Save someString to the filesystem
do {
    try someString.write(to: someURL,
        atomically: true,
        encoding: .utf8)
} catch {
    print("Error writing to URL: (error)")
}

// Load someString from the filesystem
do {
    let myEssay = try String(contentsOf: someURL, encoding: .utf8)
    print(myEssay)
} catch {
    print("Error reading from URL: (error)")
}

Note that in many languages, anything unexpected results in an exception being thrown. In Swift, exceptions are nearly always used to indicate programmer error. When an exception is thrown, the information about what went wrong is in an NSException object. That information is usually just a hint to the programmer, like, You tried to access the seventh object in this array, but there are only two. The symbols for the call stack (as it appeared when the exception was thrown) are also in the NSException.

When do you use exceptions, and when do you use error handling? If you are writing a method that should only be called with an odd number as an argument, throw an exception if it is called with an even number – the caller is making an error and you want to help that programmer find the error. If you are writing a method that wants to read the contents of a particular directory but does not have the necessary privileges, use Swift’s error handling and throw an error to the caller to indicate why you were unable to fulfill this very reasonable request.

Property list serializable types can also be written to the filesystem. The only types that are property list serializable are String, NSNumber (including primitives like Int, Double, and Bool), Date, Data, Array<Element>, and Dictionary<Key: Hashable,Value>. When an Array<Element> or Dictionary<Key,Value> is written to the filesystem with these methods, an XML property list is created. An XML property list is a collection of tagged values, like:

<?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>firstName</key>
        <string>Christian</string>
        <key>lastName</key>
        <string>Keur</string>
    </dict>
    <dict>
        <key>firstName</key>
        <string>Aaron</string>
        <key>lastName</key>
        <string>Hillegass</string>
    </dict>
</array>
</plist>

XML property lists are a convenient way to store data because they can be read on nearly any system. Many web service applications use property lists as input and output. The code for writing and reading a property list looks like this:

let authors = [
    ["firstName":"Christian", "lastName":"Keur"],
    ["firstName":"Aaron", "lastName":"Hillegass"]
]

// Write array to disk
if PropertyListSerialization.propertyList(authors,
    isValidFor: .xml) {
        do {
            let data = try PropertyListSerialization.data(with: authors,
                format: .xml,
                options: [])
            data.write(to: url, options: [.atomic])
        } catch {
            print("Error writing plist: (error)")
        }
}

// Read array from disk
do {
    let data = try Data(contentsOf: url, options: [])
    let authors = try NSPropertyListSerialization.propertyList(from: data,
        options: [],
        format: nil)
    print("Read in authors: (authors)")
} catch {
    print("Error reading plist: (error)")
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset