Proposal PR submitted as https://github.com/apple/swift-evolution/pull/85

-Kevin Ballard

On Tue, Dec 15, 2015, at 11:18 AM, Kevin Ballard wrote:
> When writing ObjC code, there's a macro NS_REFINED_FOR_SWIFT (or 
> __attribute__((swift_private))) that mangles the name when imported into 
> Swift. The intention here is to hide an API from normal Swift usage (but 
> still make it callable) so that a better Swift API can be written around it.
> 
> But there's no facility for doing this in reverse. You can expose Swift APIs 
> to ObjC, but the API has to be ObjC-compatible. Which means that if you have 
> a non-ObjC-compatible API, you have to write a separate API to expose it to 
> ObjC, and this separate API now shows up in the Swift API too.
> 
> I think the simplest way to fix this is to allow for a modifier public(objc) 
> (following the syntax of private(set)). The only thing this modifier does is 
> ensure the declaration gets added to the generated header as if it were 
> public (or—for apps—internal). If the declaration is not marked as @objc then 
> it would emit an error (it could imply @objc but it feels weird to me to have 
> an access control modifier do that). If the declaration is already public 
> (but not internal, so the same source can be used in apps and libraries) it 
> will emit a warning.
> 
> Armed with this new modifier, I can start to write code like
> 
> class MyClass: NSObject {
>     func foo<T>(x: T) { ... }
> }
> 
> extension MyClass {
>     @objc(foo) public(objc) private func __foo(x: AnyObject) { ... }
> }
> 
> When used on a property that already has private(set), the public(objc) 
> modifier will only apply to the getter (e.g. the private(set) takes 
> precedence for the setter).
> 
> Alternatives:
> 
> * Add a new attribute @export_objc that has the same behavior.
> 
> * Change the @objc attribute to take an optional second argument, which may 
> be the token "exported", as in @objc(foo,exported). When using the "exported" 
> token, the selector portion is required. We could possibly support an empty 
> selector to indicate the default, as in @objc(,exported), but that looks odd.
> 
> My preference is for public(objc) as proposed as it matches more closely with 
> the intended behavior, which is "this API is private in Swift and public in 
> ObjC".
> 
> -Kevin Ballard
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to