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

Kevin Ballard kevin at sb.org
Tue Jan 12 14:01:54 CST 2016


Interesting, I didn't realize that worked. It does sound like a bug
though; I would have expected the @available attribute to generate an
NS_AVAILABLE() or NS_UNAVAILABLE() annotation on the Obj-C call.

-Kevin Ballard

On Mon, Jan 11, 2016, at 10:36 PM, Christopher Rogers wrote:
> 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/b0e4954e/attachment.html>


More information about the swift-evolution mailing list