[swift-corelibs-dev] NSCoding methods

Luke Howard lukeh at padl.com
Wed Dec 23 18:34:46 CST 2015

My plan was just to map any flat unmangled names to SwiftFoundation classes without the boilerplate explicit mappings, but happy to change approaches.

That's what the code in the branch I posted yesterday does, but I need to fix it to encode the mangled name for non-one level class types - was planning to implement NSClassFromString/NSStringFromClass at the same time so at least the logic is in one place, and those can be refined over time.

Sent from my iPhone

> On 24 Dec 2015, at 11:07, Philippe Hausler <phausler at apple.com> wrote:
> So one thing we can do in the interim until there is a sanctioned way for us to convert strings to classes and classes to strings is we can register the classes globally for transformation so that the Foundation or SwiftFoundation module name won’t be an issue.
> By doing this early on in the initialization for NSKeyedArchiver, once of course.
>     NSKeyedArchiver.setClassName("NSArray", forClass: NSArray.self)
>     NSKeyedArchiver.setClassName("NSByteCountFormatter", forClass: NSByteCountFormatter.self)
>     NSKeyedArchiver.setClassName("NSData", forClass: NSData.self)
>     NSKeyedArchiver.setClassName("NSDate", forClass: NSDate.self)
>     NSKeyedArchiver.setClassName("NSDateFormatter", forClass: NSDateFormatter.self)
>     NSKeyedArchiver.setClassName("NSDateIntervalFormatter", forClass: NSDateIntervalFormatter.self)
>     NSKeyedArchiver.setClassName("NSDecimalNumber", forClass: NSDecimalNumber.self)
>     NSKeyedArchiver.setClassName("NSDictionary", forClass: NSDictionary.self)
>     NSKeyedArchiver.setClassName("NSEnergyFormatter", forClass: NSEnergyFormatter.self)
>     NSKeyedArchiver.setClassName("NSFormatter", forClass: NSFormatter.self)
>     NSKeyedArchiver.setClassName("NSLengthFormatter", forClass: NSLengthFormatter.self)
>     NSKeyedArchiver.setClassName("NSMassFormatter", forClass: NSMassFormatter.self)
>     NSKeyedArchiver.setClassName("NSMessagePort", forClass: NSMessagePort.self)
>     NSKeyedArchiver.setClassName("NSMutableArray", forClass: NSMutableArray.self)
>     NSKeyedArchiver.setClassName("NSMutableData", forClass: NSMutableData.self)
>     NSKeyedArchiver.setClassName("NSMutableDictionary", forClass: NSMutableDictionary.self)
>     NSKeyedArchiver.setClassName("NSMutableSet", forClass: NSMutableSet.self)
>     NSKeyedArchiver.setClassName("NSMutableString", forClass: NSMutableString.self)
>     NSKeyedArchiver.setClassName("NSNotification", forClass: NSNotification.self)
>     NSKeyedArchiver.setClassName("NSNumber", forClass: NSNumber.self)
>     NSKeyedArchiver.setClassName("NSNumberFormatter", forClass: NSNumberFormatter.self)
>     NSKeyedArchiver.setClassName("NSPersonNameComponentsFormatter", forClass: NSPersonNameComponentsFormatter.self)
>     NSKeyedArchiver.setClassName("NSPort", forClass: NSPort.self)
>     NSKeyedArchiver.setClassName("NSRegularExpression", forClass: NSRegularExpression.self)
>     NSKeyedArchiver.setClassName("NSSet", forClass: NSSet.self)
>     NSKeyedArchiver.setClassName("NSSocketPort", forClass: NSSocketPort.self)
>     NSKeyedArchiver.setClassName("NSString", forClass: NSString.self)
>     NSKeyedArchiver.setClassName("NSTextCheckingResult", forClass: NSTextCheckingResult.self)
>     NSKeyedArchiver.setClassName("NSTimeZone", forClass: NSTimeZone.self)
>     NSKeyedArchiver.setClassName("NSUUID", forClass: NSUUID.self)
>     NSKeyedArchiver.setClassName("NSValue", forClass: NSValue.self)
> I have a few more things that I was looking at for supporting this that might be useful depending on how far along you are.
> This should give us at least a head start on the NSCoding compliant Foundation classes and user classes can come next once we have support.
>>> On Dec 23, 2015, at 3:33 PM, Luke Howard <lukeh at padl.com> wrote:
>>> On 24 Dec 2015, at 10:12 AM, Philippe Hausler <phausler at apple.com> wrote:
>>> NSCoding will have to use something to transform from strings to classes, and that satisfy the two cases (or more) that we have already shown, currently there is no thing that does that in either form; either mangled or non mangled. Basically we need something to implement NSClassFromString with. Which we have clearly shown that dlsym does not fully meet the needs since there are cases that will emit as “module.classname” and others that emit as the mangled name. The simple case is probably going to be the a very common usage pattern for consumers (and of previously built applications). The inner class should definitely be handled in addition to this case.
>> * If the mangled name is present in the archive, you can re-mangle it to get the metadata accessor
>> * If it’s a one-level unmangled name representing a class, it can be mangled
>> * If it’s a zero-level unmangled name, then it seems reasonable for a first implementation to assume it’s a SwiftFoundation class (or that the caller has set an explicit mapping)
>> Noted that dlsym() will only work with public symbols.
>>> Are there any methods that can fetch the name (either the symbolic or the readable) given a AnyClass in the runtime to get work started here? I think it is definitely sensible as a start to restrict this just to descendants of the class NSObject. I would presume that since the Metadata is potentially volatile contents we should use something along the lines of swift_getTypeName etc?
>> I have been using _typeName() but it always demangles – for interop with existing archives we need to match the behaviour of libobjc's class_getName() (equivalent to NSStringFromClass), which appears to demangle one-level classes.
>> — Luke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-corelibs-dev/attachments/20151224/a9677909/attachment.html>

More information about the swift-corelibs-dev mailing list