Why is Array.init(contentsOfURL:) not available?


(Ole Begemann) #1

(Apologies if this is not the right list to ask this question. I couldn't decide between swift-corelibs-dev and swift-dev.)

I noticed that the NSArray and NSDictionary initializers to create a collection from a property list file are not exposed in the stdlib Array and Dictionary types. The same is true for the corresponding methods to write a collection to a property list:

– init?(contentsOfFile:)
– init?(contentsOfURL:)
– write(toFile:atomically:)
– write(to:atomically:)

You can still call these from Swift by using NSArray or NSDictionary directly.

My question is why this decision was made, purely out of interest and because I couldn't find any information about this. I can imagine a few reasons:

1) Property lists are quite specific to Apple platforms and we don't want to "pollute" the standard library with platform-specific solutions.

2) Plists are just one of several potentially useful file formats and users might assume that an initializer to deserialize a collection from a file also supported other file formats, such as JSON or YAML, especially with a generic name like init(contentsOfFile:).

3) The resulting collections are heterogeneously typed ([Any] or [String:Any]) and as such not very pleasant to work with in Swift, so Array and Dictionary are really considered to be the wrong types to offer this functionality. It would be preferable to have a separate data type for working with plists, something like:

enum PropertyList {
    case text(String)
    case bool(Bool)
    case int(Int)
    case double(Double)
    case date(Date)
    indirect case array([PropertyList])
    indirect case dict([String: PropertyList])
}

Thanks!
Ole


(Tony Parker) #2

Hi Ole,

(Apologies if this is not the right list to ask this question. I couldn't decide between swift-corelibs-dev and swift-dev.)

I noticed that the NSArray and NSDictionary initializers to create a collection from a property list file are not exposed in the stdlib Array and Dictionary types. The same is true for the corresponding methods to write a collection to a property list:

– init?(contentsOfFile:)
– init?(contentsOfURL:)
– write(toFile:atomically:)
– write(to:atomically:)

You can still call these from Swift by using NSArray or NSDictionary directly.

My question is why this decision was made, purely out of interest and because I couldn't find any information about this. I can imagine a few reasons:

1) Property lists are quite specific to Apple platforms and we don't want to "pollute" the standard library with platform-specific solutions.

2) Plists are just one of several potentially useful file formats and users might assume that an initializer to deserialize a collection from a file also supported other file formats, such as JSON or YAML, especially with a generic name like init(contentsOfFile:).

3) The resulting collections are heterogeneously typed ([Any] or [String:Any]) and as such not very pleasant to work with in Swift, so Array and Dictionary are really considered to be the wrong types to offer this functionality. It would be preferable to have a separate data type for working with plists, something like:

enum PropertyList {
   case text(String)
   case bool(Bool)
   case int(Int)
   case double(Double)
   case date(Date)
   indirect case array([PropertyList])
   indirect case dict([String: PropertyList])
}

Thanks!
Ole

The main reason is actually that we just prefer people use NSPropertyListSerialization API to read or write property lists. One big reason: that API has the possibility of giving you an error, whereas the collection methods do not.

The collection API is a trivial convenience method over property list serialization anyway. Here is the implementation:

    data = [[NSData allocWithZone:NULL] initWithContentsOfFile:path];
    if (!data) return nil;
    id plist = [[NSPropertyListSerialization propertyListWithData:data options:immutable ? NSPropertyListImmutable : NSPropertyListMutableContainers format:NULL error:NULL] retain];
    [data release];

Plus an additional check to make sure the result is the right type (array or dictionary).

- Tony

···

On Dec 5, 2016, at 5:11 AM, Ole Begemann via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:


(Ole Begemann) #3

The main reason is actually that we just prefer people use
NSPropertyListSerialization API to read or write property lists. One big
reason: that API has the possibility of giving you an error, whereas the
collection methods do not.

Thanks for the quick reply, Tony, that makes sense. I also hadn't realized the nice correspondence of PropertyListSerialization and JSONSerialization until a friend pointed that out to me. It makes sense to separate the (de-)serialization step from the actual data type.

Ole