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 <phaus...@apple.com> 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 <jordan_r...@apple.com 
>> <mailto:jordan_r...@apple.com>> 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 
>>> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>> 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 
>>>> <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>> wrote:
>>>> 
>>>> 
>>>>> On 22 Dec 2015, at 5:50 AM, Jordan Rose <jordan_r...@apple.com 
>>>>> <mailto:jordan_r...@apple.com>> 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
>>>> swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev 
>>>> <https://lists.swift.org/mailman/listinfo/swift-corelibs-dev>
>>> 
>>> _______________________________________________
>>> swift-corelibs-dev mailing list
>>> swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-corelibs-dev 
>>> <https://lists.swift.org/mailman/listinfo/swift-corelibs-dev>
> 

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

Reply via email to