Howto writing a file in plist mode of an array of text dictionary

Hello


I have previously created a plist file using Objective C


<?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>ipaddress</key>
        <string>192.168.10.101</string>
        <key>ipport</key>
        <string>12345</string>
        <key>upsname</key>
        <string>S 2000 (Port 1)</string>
        <key>upsport</key>
        <string>1</string>
    </dict>
    <dict>
        <key>ipaddress</key>
        <string>192.168.10.102</string>
        <key>ipport</key>
        <string>12345</string>
        <key>upsname</key>
        <string>S 3000 (Port 2)</string>
        <key>upsport</key>
        <string>2</string>
    </dict>
    <dict>
        <key>ipaddress</key>
        <string>192.168.10.103</string>
        <key>ipport</key>
        <string>12345</string>
        <key>upsname</key>
        <string>S 2000 (Port 3)</string>
        <key>upsport</key>
        <string>3</string>
    </dict>
</array>
</plist>



--------------

I now use Swift and I have created an array of dictionaries that matches following print:

[{
    ipaddress = "192.168.10.101";
    ipport = 12345;
    upsname = "S 2000 (Port 1)";
    upsport = 1;
}, {
    ipaddress = "192.168.10.102";
    ipport = 12345;
    upsname = "S 3000 (Port 2)";
    upsport = 2;
}, {
    ipaddress = "192.168.10.103";
    ipport = 12345;
    upsname = "S 2000 (3)";
    upsport = 3;
}]

Which function may I use to transform this array in a plist file as above ?

Thanks for your help

Replies

(yourArray as NSArray).write(toFile: someFileName, atomically:true)

or

(yourArray as NSArray).write(to:someURL, atomically:true)

should work.

While guywithmazda’s suggestion is the most direct way to solve this problem, I strongly encourage you to rethink how you’re modelling this data. Using an array of dictionaries is not how you’d normally do this in Swift. Rather, you’d normally use a type to represent each UPS and then use a

PropertyListEncoder
to convert from that type to its serialised form (and
PropertyListDecoder
to go the other way).

Pasted in below is some code that illustrates this. Here

UPSRecord
is a struct that represents the each UPS in memory.

The advantage of this approach is type safety. Rather than manipulating arrays of dictionaries at runtime, which is very error prone, you can manipulate arrays of

UPSRecord
, which allows the type system to prevent you from making ‘obvious’ mistakes.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
import Foundation

struct UPSRecord : Codable {
    var ipAddress: String
    var ipPort: Int
    var upsName: String
    var upsPort: Int

    enum CodingKeys : CodingKey, String {
        case ipAddress = "ipaddress"
        case ipPort = "ipport"
        case upsName = "upsname"
        case upsPort = "upsport"
    }
}

let upsList = [
    UPSRecord(ipAddress: "192.168.10.101", ipPort: 12345, upsName: "S 2000 (Port 1)", upsPort: 1),
    UPSRecord(ipAddress: "192.168.10.102", ipPort: 12345, upsName: "S 2000 (Port 2)", upsPort: 2),
    UPSRecord(ipAddress: "192.168.10.103", ipPort: 12345, upsName: "S 2000 (Port 3)", upsPort: 3),
]

func write(upsList: [UPSRecord], to url: URL) throws {
    let encoder = PropertyListEncoder()
    encoder.outputFormat = .xml
    let plistData = try encoder.encode([upsList])
    try plistData.write(to: url)
}