Here's another example on OS X:
import Foundation
class Outer {
class Inner : NSObject, NSCoding {
let uuid: Foundation.NSUUID
required init?(coder aDecoder: NSCoder) {
uuid = aDecoder.decodeObjectForKey("my.uuid") as! Foundation.NSUUID
}
override init() {
uuid = Foundation.NSUUID()
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(uuid, forKey: "my.uuid")
}
}
}
NSKeyedArchiver.archiveRootObject(Outer.Inner(), toFile:
"/Users/jrose/Desktop/test-archive")
Which results in this archive:
{
"$version" => 100000
"$objects" => [
0 => "$null"
1 => {
"my.uuid" => <CFKeyedArchiverUID 0x7f8992c0e9d0 [0x7fff7c5acd80]>{value =
2}
"$class" => <CFKeyedArchiverUID 0x7f8992c0ec90 [0x7fff7c5acd80]>{value =
4}
}
2 => {
"NS.uuidbytes" => <67f0b08b c8274f8c b0c78d90 bd4627dc>
"$class" => <CFKeyedArchiverUID 0x7f8992c0eda0 [0x7fff7c5acd80]>{value =
3}
}
3 => {
"$classname" => "NSUUID"
"$classes" => [
0 => "NSUUID"
1 => "NSObject"
]
}
4 => {
"$classname" => "_TtCC4main5Outer5Inner"
"$classes" => [
0 => "_TtCC4main5Outer5Inner"
1 => "NSObject"
]
}
]
"$archiver" => "NSKeyedArchiver"
"$top" => {
"root" => <CFKeyedArchiverUID 0x7f8992c0f0c0 [0x7fff7c5acd80]>{value = 1}
}
}
NSStringFromClass makes pretty names when they fall into the "simple" category,
but that's not an arbitrarily extensible transformation, and NSCoding shouldn't
have to know anything about it.
Jordan
> On Dec 23, 2015, at 14:48, Philippe Hausler <[email protected]> wrote:
>
> The archiving format encodes the names of the classes in the archive itself.
> Here are a few code examples and a quasi readable output from them:
>
> let uuid = NSUUID()
> let data = NSKeyedArchiver.archivedDataWithRootObject(uuid)
> let archive = try! NSPropertyListSerialization.propertyListWithData(data,
> options: [], format: nil)
> print(archive)
>
> prints the following:
>
> {
> "$archiver" = NSKeyedArchiver;
> "$objects" = (
> "$null",
> {
> "$class" = "<CFKeyedArchiverUID 0x1030025e0
> [0x7fff7ab33bb0]>{value = 2}";
> "NS.uuidbytes" = <797639fe dad74b14 902afab3 c490448b>;
> },
> {
> "$classes" = (
> NSUUID,
> NSObject
> );
> "$classname" = NSUUID;
> }
> );
> "$top" = {
> root = "<CFKeyedArchiverUID 0x103002a80 [0x7fff7ab33bb0]>{value = 1}";
> };
> "$version" = 100000;
> }
>
> Note the $classes and $classname objects; which are what tell the internal
> implementation of NSKeyedUnarchiver what to construct; moreover you can
> create your own classes..
>
> // I don’t really think this is a good naming for an application’s class but
> hey it might happen...
> class NSUUID : NSObject, NSCoding {
> let uuid: Foundation.NSUUID
> required init?(coder aDecoder: NSCoder) {
> uuid = aDecoder.decodeObjectForKey("my.uuid") as! Foundation.NSUUID
> }
> override init() {
> uuid = Foundation.NSUUID()
> }
> func encodeWithCoder(aCoder: NSCoder) {
> aCoder.encodeObject(uuid, forKey: "my.uuid")
> }
> }
>
> let uuid = NSUUID()
> let data = NSKeyedArchiver.archivedDataWithRootObject(uuid)
> let archive = try! NSPropertyListSerialization.propertyListWithData(data,
> options: [], format: nil)
> print(archive)
>
> prints the following:
>
> {
> "$archiver" = NSKeyedArchiver;
> "$objects" = (
> "$null",
> {
> "$class" = "<CFKeyedArchiverUID 0x100709630
> [0x7fff7ab33bb0]>{value = 4}";
> "my.uuid" = "<CFKeyedArchiverUID 0x100708e60
> [0x7fff7ab33bb0]>{value = 2}";
> },
> {
> "$class" = "<CFKeyedArchiverUID 0x100709740
> [0x7fff7ab33bb0]>{value = 3}";
> "NS.uuidbytes" = <546e5b5e 15c244a1 aa96eb90 30c3f7f6>;
> },
> {
> "$classes" = (
> NSUUID,
> NSObject
> );
> "$classname" = NSUUID;
> },
> {
> "$classes" = (
> "Archiver.NSUUID",
> NSObject
> );
> "$classname" = "Archiver.NSUUID";
> }
> );
> "$top" = {
> root = "<CFKeyedArchiverUID 0x100709b70 [0x7fff7ab33bb0]>{value = 1}";
> };
> "$version" = 100000;
> }
>
> Granted this is a questionable name for a class but it illustrates which
> class names are encoded where and how they should be interpreted in the
> pre-existing archive format; which we will have to figure out some sensible
> way of inflating and deflating to/from disk/network etc.
>
>> On Dec 23, 2015, at 2:37 PM, Jordan Rose <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> No, we cannot encode things "non-mangled but with the namespace". For any
>> type other than top-level non-generic class types, using a non-mangled name
>> is not unique. The only correct answer for arbitrary classes is to use
>> mangled names, or something that maps one-to-one with mangled names.
>>
>> Now, Foundation classes are not arbitrary classes, but then I don't see why
>> we'd need to use mangled names for those. We can just use the plain old
>> Objective-C names that the OS X classes use today.
>>
>> Jordan
>>
>>> On Dec 22, 2015, at 10:16, Philippe Hausler via swift-corelibs-dev
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> To clarify the goals: I think it is reasonable for us to have a goal to be
>>> able to encode/decode archives from foreign targets; e.g. linux encodes an
>>> archive and mac os x decodes or iOS encodes and linux decodes. This will
>>> allow for server architecture to transmit binary archives across the wire.
>>> This will mean that we will want to have the encoded class names from the
>>> application scope to be encoded as the non mangled name but with the
>>> namespace. However this presents a problem; Foundation will have a
>>> namespace which will need to be inferred both for encoding and decoding.
>>> Thankfully there may be a reasonable way to approach this;
>>>
>>> public class func classNameForClass(cls: AnyClass) -> String?
>>> public class func setClassName(codedName: String?, forClass cls: AnyClass)
>>>
>>> These methods can be used to allow for translation of classes by
>>> registering the appropriate classes for a “shortened” name that drops the
>>> Foundation/SwiftFoundation namespace prefix during encoding.
>>>
>>>> On Dec 22, 2015, at 2:45 AM, Luke Howard via swift-corelibs-dev
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>
>>>>
>>>>> On 22 Dec 2015, at 5:50 AM, Jordan Rose <[email protected]
>>>>> <mailto:[email protected]>> wrote:
>>>>>
>>>>> IMHO on Linux NSKeyedArchiver should always use mangled names. If we want
>>>>> cross-platform archives, we should set up standard substitutions, but
>>>>> given that Swift classes exposed to Objective-C are archived with their
>>>>> full names it doesn't make sense to use "half the name" in the archive.
>>>>
>>>> You mean namespaced but unmangled yes? If so I agree.
>>>>
>>>> BTW I found a couple of small CF nits:
>>>>
>>>> * in CFDictionaryGetKeysAndValues(), keybuf and valuebuf are transposed in
>>>> the call to CF_SWIFT_FUNCDISPATCHV(NSDictionary.getObjects())
>>>>
>>>> * _CFSwiftDictionaryGetKeysAndValues() does not handle keybuf or valbuf
>>>> being NULL (either of which are valid when calling
>>>> CFDictionaryGetKeysAndValues())
>>>>
>>>
>>> This is a bit un-related to NSCoding and the transposition is probably a
>>> mistake if it is inverted (the CF method should be reversed from the NS
>>> method to mimic the objc counterpart)
>>>
>>>> — Luke
>>>> _______________________________________________
>>>> swift-corelibs-dev mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
>>>> <https://lists.swift.org/mailman/listinfo/swift-corelibs-dev>
>>>
>>> _______________________________________________
>>> swift-corelibs-dev mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev
>>> <https://lists.swift.org/mailman/listinfo/swift-corelibs-dev>
>
_______________________________________________
swift-corelibs-dev mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev