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

Christopher Rogers christorogers at gmail.com
Tue Jan 12 00:36:43 CST 2016


I've definitely wanted a feature like this. I hesitate to mention this
because it might be a bug, but you can actually you can do this now. Just
add

@objc
@available(*, unavailable)

and it won't be callable from Swift, while still getting bridged. (I'm not
sure you need @objc but it serves as light documentation anyway.) The buggy
part is the fact that it doesn't get bridged with the NS_UNAVAILABLE
attribute. (It doesn't make much sense to have unavailable code in
non-public APIs though so it may be correct behavior.) I use it a lot when
porting code over to Swift to make sure people don't use the same old
methods and classes they're used to using while providing a way to point
them to the newer API by adding a message to the availability attribute.
On Tue, Jan 12, 2016 at 8:40 AM Andrew Bennett via swift-evolution <
swift-evolution at swift.org> wrote:

> +1 I've had similar issues, I've had to provide weaker Objective-C
> interface because my strong swift interfaces were incompatible with
> Objective-C.
>
> 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
>>
>
> _______________________________________________
> 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/289207f3/attachment.html>


More information about the swift-evolution mailing list