[swift-evolution] Proposal: Add public(objc) modifier

Andrew Bennett cacoyi at gmail.com
Mon Jan 11 17:39:50 CST 2016

+1 I've had similar issues, I've had to provide weaker Objective-C
interface because my strong swift interfaces were incompatible with

I've considered whether @objc(foo) implies public(objc) (in most cases),
and if you'd need private(objc) if it did, but I think your proposal is
more consistent/clear.

On Tue, Jan 12, 2016 at 9:51 AM, Kevin Ballard via swift-evolution <
swift-evolution at swift.org> wrote:

> I could really use some feedback on this proposal. This is something that
> annoys me every time I write a pure-Swift API with an Obj-C wrapper (which,
> coincidentally, I'm doing again right at this moment). I'd really like to
> have some graceful way of handling this in Swift so the Obj-C compatibility
> API is not exposed to Swift clients, but this proposal can't move forward
> without community support.
> -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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160112/088562ae/attachment.html>

More information about the swift-evolution mailing list