1

I'm working on a framework.

The library is written in Swift and I notice that when a class inherits from NSObject or conforms to NSObjectProtocol, its declaration can be found in *.framework/Headers/*-Swift.h.

This class is available outside of the module in Objective-C code, so it became public.

Why does it happen if the access level is internal?

Cristik
  • 30,989
  • 25
  • 91
  • 127

1 Answers1

0

Internal Swift classes need to be available to the Objective-C code of that framework, however the only way Objective-C code can access the Swift classes is by importing the -Swift.h header file.

Now, how can a Swift class be visible to Objective-C: it either needs to inherit NSObject, or conform to NSObjectProtocol. If any of these two conditions is fulfilled, and the class declaration is not decorated with @nonobjc/private/fileprivate, then it will be exported to Objective-C via the -Swift.h module header.

This is why any Swift classes that are exportable to Objective-C will automatically be present in the discussed header file. It's an (unfortunate) coincidence that for frameworks this results in the class being publicly available (due to the fact that any Objective-C declarations that appear in a header are public).

Now, if you want your class to not end up in the -Swift.h header file, but still want to keep the NSObject(Protocol) inheritance/conformance, a workaround would be to make your class generic, thus prohibiting its exposure to Objective-C. Note that this will also prevent the class from being available to Objective-C code in the same framework.

// the generic argument doesn't matter, it's only used to make the class
// Swift-only
class MyClass<T>: NSObject { }

The caveat would be that every time the class is used, you will need to specify a value for the generic argument. This can be avoided by adding an intermediary base class:

// just a class that inherits NSObject, but is not exported in the -Swift header
class Empty<T>: NSObject { }

class MyClass: Empty<String> { }
Cristik
  • 30,989
  • 25
  • 91
  • 127
  • Unfortunately, @nonobjc can't be used with class declaration. It would be nice to have the explanation in access modifier docs. Thank you for your answer `@Cristik` – user3158880 Jan 29 '19 at 18:09
  • @user3158880 yeah, however if you need a workaround to this "limitation", I updated my answer with a such one. – Cristik Feb 05 '19 at 06:14