[swift-evolution] [Review] SE-0005 Better Translation of Objective-C APIs Into Swift

Andrew Bennett cacoyi at gmail.com
Wed Feb 10 23:32:37 CST 2016

I like your idea, I think you may need a protocol for each class though.
It's possible for NSNumber to be used as an NSValue, for example.

On Monday, 8 February 2016, Marco Masser via swift-evolution <
swift-evolution at swift.org> wrote:

> I know I’m late to the party and the review period has ended, but I’d like
> to add a suggestion towards a possible solution to a point that was
> discussed in this context.
> On 2016-02-05, at 17:54, Michel Fortin via swift-evolution <
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> wrote:
> […]
> Eventually, classes such as NSCountedSet and NSIndexSet will have a proper
> struct wrapper that will claim the non-prefixed name. But there is no
> urgency in making those wrappers ready for Swift 3 because the class
> remains available.
> Anyway, that's what I'd propose. There aren't that many classes in
> Foundation; cases like this can be sorted out manually.
> I wholeheartedly agree with this: I’d take a close look at every class in
> Foundation that should really be a value type in Swift (all collection
> types, NSURL, …) and keep the NS prefix for them. Then, at some later point
> (or with Swift 3 if there’s enough time), add struct wrappers without the
> NS prefix for these classes.
> I want to outline a possible solution to this that allows all developers
> to annotate their classes and have them automatically imported as structs
> in Swift.
> I think that could actually work with just a couple of annotations in the
> Objective-C headers and the correct interpretation of them in the Clang
> Importer. I’d propose something like this:
> @interface NS_SWIFT_STRUCT(CountedSet) NSCountedSet<ObjectType> :
> NSMutableSet<ObjectType> {
> @property BOOL foo; // Just for demonstration purposes.
> - (NSUInteger)countForObject:(ObjectType)object;
> - (void)addObject:(ObjectType)object NS_SWIFT_MUTATING;
> - (void)removeObject:(ObjectType)object NS_SWIFT_MUTATING;
> @end
> In Swift, that would come through as the following (in addition to an
> NSCountedSet class):
> struct CountedSet<ObjectType> {
>     private let _internal: NSCountedSet
>     var foo: Bool
>     func countForObject(object: ObjectType) -> Int
>     mutating func addObject(object: ObjectType)
>     mutating func removeObject(object: ObjectType)
> }
> That is: NS_SWIFT_STRUCT(_name) specifies that a struct with the given
> _name should be created that has a private let member of the annotated
> class. All methods of the class and all its superclasses are
> automatically imported as methods of the struct. Methods annotated as
> NS_SWIFT_MUTATING are imported as mutating methods in the Swift struct.
> For @property declarations, the importer could automatically infer that
> the setter is mutating and the getter nonmutating, although an
> NS_SWIFT_NONMUTATING might be useful to annotate that a property setter
> should be imported as nonmutating, if applicable.
> After a quick glance over all of Foundation’s classes, I think the
> following could be eligible (probably not a complete list):
> NSAttributedString
> NSCharacterSet
> NSCountedSet
> NSData
> NSDate
> NSDecimalNumber
> NSError
> NSHashTable
> NSIndexPath
> NSIndexSet
> NSNotification
> NSNumber/NSValue
> NSOrderedSet
> Whereas for some classes it would be better to use the mutable variants as
> the internal storage for the Swift struct:
> NSMutableAttributedString (as AttributedString)
> NSMutableCharacterSet (as CharacterSet)
> NSMutableData (as Data)
> NSMutableIndexSet (as IndexSet)
> NSMutableOrderedSet (as OrderedSet)
> The Clang Importer could also handle the case where passing a Swift URL to
> an Objective-C method that expects an NSURL could work automatically. Maybe
> an Objective-C methods like this:
> - (void)methodImplementedInObjectiveC:(NSURL *)arg;
> … could be imported into Swift like this:
> func methodImplementedInObjectiveC(arg: NSURL)
> func methodImplementedInObjectiveC(inout arg: URL) // Objective-C code
> operates on arg._internal
> If the struct wraps a class that has a mutable counterpart (this would
> have to be annotated somehow), the import could do a better job for the
> nonmutating variant. This would require a variant of the
> NS_SWIFT_STRUCT(_name) macro that takes another parameter that points to
> the nonmutating variant. Then, the following methods:
> - (void)nonmutatingMethodImplementedInObjectiveC:(NSData *)arg;
> - (void)mutatingMethodImplementedInObjectiveC:(NSMutableData *)arg;
> … could be imported into Swift like this:
> func nonmutatingMethodImplementedInObjectiveC(arg: Data)
> func mutatingMethodImplementedInObjectiveC(inout arg: Data) //
> Objective-C code operates on arg._internal
> Annotations like this would be very useful because it would also allow
> developers to annotate their own classes like this. It’s not uncommon to
> have model objects that could sensibly be structs in Swift, but can’t
> because existing Objective-C code requires them to be classes.
> When Objective-C classes become Swift structs, they obviously lose their
> inheritance chain and therefore polymorphic properties. I haven’t done a
> survey, but my gut feeling tells me that the classes for which all this
> is relevant – i.e. those that should have value semantics – aren’t usually
> subclassed and this point could therefore be moot. I may be wrong about
> that, though.
> There are probably a lot of additional things to specify here, but maybe
> this could be a way forward. It would enable using things like NSCountedSet
> and NSURL in Swift just like it does now, with the possibility to add value
> types for them later without breaking existing code. In time, the classes could
> also be deprecated in favor of the struct, if that is desired.
> Cheers,
> Marco
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160211/89ac8f94/attachment.html>

More information about the swift-evolution mailing list