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

Kevin Ballard kevin at sb.org
Tue Jan 5 16:56:42 CST 2016

Code completion aside, it just makes me really unhappy to expose a Swift
API that nobody should *ever* call from Swift. I just don't want to have
that API be accessible at all when it only exists to serve as the Obj-C

-Kevin Ballard

On Tue, Jan 5, 2016, at 02:55 PM, Félix Cloutier wrote:
> .NET has an EditorBrowsable[1] attribute that controls whether things
> appear in autocomplete or not. I think that this alternative deserves
> some consideration.
> It clearly won't have identical semantics, but I think that it would
> be a little more graceful and much less involved. This solution only
> needs a new attribute and SourceKit changes.
> Félix
>> Le 5 janv. 2016 à 15:23:55, Kevin Ballard via swift-evolution <swift-
>> evolution at swift.org> a écrit :
>> 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 swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution


  1. https://msdn.microsoft.com/en-us/library/system.componentmodel.editorbrowsableattribute(v=vs.110).aspx
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160105/f9b14395/attachment.html>

More information about the swift-evolution mailing list