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]> 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