What is import func, struct, class, and #_exported in Swift? - swift

In Apple's github for the Swift Package manager they use
import func POSIX.isatty
import func libc.strerror_r
import var libc.EINVAL
import var libc.ERANGE
import struct PackageModel.Manifest
source
There is also a file where the only code in it is #_exported source
#_exported import func libc.fileno
Is this a Swift 3 feature? I can not find anywhere that you can import a type in the Swift documentation and nothing on #_exported.

You can import only a specific part of a module, not a whole module:
Providing more detail limits which symbols are imported—you can specify a specific submodule or a specific declaration within a module or submodule. When this detailed form is used, only the imported symbol (and not the module that declares it) is made available in the current scope.
From Import Declaration
For example import func POSIX.isatty will import function isatty from module POSIX instead of importing the whole module POSIX (which is BIG).
The #_exported attribute starts with an underscore. That means it's a private Swift attribute. Not a feature, an implementation detail.
In short, this attribute lets you export a symbol from another module as if it were from your module.

Related

#_exported import but in Objective-C

Swift has an interesting keyword, which can be declared in the ModuleA:
#_exported import Foundation
Then, when in some other module (e.g. ModuleB) I import the ModuleA:
import ModuleA
let currentDate = Date() // using a Foundation struct
... I'm able to use also the types from the Foundation even though I'm not importing it with an import statement. It's being automatically imported as it has been declared as #_exported in the ModuleA.
Now I'd like to have a similar behavior in Objective-C.
Given:
3 Targets: TargetA (Swift), ProtocolTarget(Swift with #objc keyword annotated types) and TargetB (ObjC)
I'd like to make the ProtocolTarget implicitly imported, so that when the TargetB imports TargetA, all of the methods from the ProtocolTarget should become also available inside the TargetA.
How can I achieve this?

Importing only specific extensions from a module

Say I have some extension in module A:
public extension String {
func foo() { ... }
}
In module B, I would like to sometimes import individual extensions (or files), just like I can import struct, import enum, ...
Neither of
import struct A.String
import func A.String.foo
works, and there does not seem to be a keyword geared towards extensions.
Is this possible? How?
First of all read this: apple doc modules
but its not possible, you can only use the Access Levels

Import one class from a Swift module

Is it possible to import just one class from a Swift module? I used
import struct Foundation.Date
but now, NSString and other Foundation classes/structs are available too, at the top level!
All I really want is the Date class, to avoid polluting the namespace.
This answer is originally made for objective-c but the behaviour is the same: Why does a simple program import <Foundation/Foundation.h> instead of individual header files?
You don't have to worry about that, I think your compiler do this job perfectly ! :)

Is it possible to alias an import?

In c# when pulling in a library that has a lot of name collisions with existing code, there's a way to alias the import so you don't need to fully clarify the namespace for each use. eg:
using MyCompany.MyLibrary.Model as MMM
then you could do
MMM.MyObject
instead of
MyCompany.MyLibrary.Model.MyObject
With the recent update to swift 3.0, I've found some of my model objects are now colliding with the Foundation types, and I've been forced to prefix things that used to have an NS prefix in the class name with Foundation.classname. It would be great if I could type alias the import of my model library much like the c# example given above. Is this possible in swift 3.0? If not is there another strategy to avoid name collisions that would result in having to write the framework name in front of each type? I'm considering going back to prefixing my class names like we did in obj-c, but I'm trying to explore my options before I do that.
Update 2021 for Swift 5;
No, but you can import all and alias (in separate file), read below for more details.
Generally
You can import a particular entity as well as the entire module:
import struct­ SomeModule.SomeStruct
import class­ SomeModule.SomeClass
import func SomeModule.someFunc
See the full list of "importable" entity types in the import-kind rule of Swift grammar.
Then you can create a typealias:
typealias SMSomeStruct = SomeModule.SomeStruct
And, as of Swift 3, there is no import declaration combined with aliasing.
Considering the Collisions with Foundation Entities
Say, you have a class SomeModule.NumberFormatter.
It is enough to create two typealiases in a separate Swift file (in an importing project) to prevent collisions:
import Foundation
import SomeModule
typealias NumberFormatter = Foundation.NumberFormatter
typealias SMNumberFormatter = SomeModule.NumberFormatter
It's not even with Swift 5 possible to directly alias an import-statement!?
But fortunately, I could workaround it with something like:
import typealias MyModule.MyInnerClass
I mean, if we are the module's developer, simply move the alias into the module, like:
public typealias MyInnerClass = MyClass.MyInnerClass
public class MyClass {
public class MyInnerClass {
// Some cool logic here...
}
}

Submodules in Swift

Say I have an app, MyApp which is built in an Xcode workspace. Inside this workspace I have the primary app target and two nested Xcode projects for my frameworks, Foo and Bar.
Inside my app I import Foo and Bar and dependency inject an object in Foo into an object in Bar. Say, however, I don't need all of Foo, just a couple of classes. How could I create a submodule within foo and import that. E.g. import Foo.Models.Animals.Dog
While you can do something like
import struct MyModule.MyStruct
import func Darwin.glob
I'm not sure if you can get much deeper than that. Here's a relevant quote from the (free) Swift book
“Providing more detail limits which symbols are imported—you can specify a specific submodule or a specific declaration within a module or submodule. When this detailed form is used, only the imported symbol (and not the module that declares it) is made available in the current scope.”
It goes on to explain that you can import any of typealias, struct, class, enum, protocol, var, or func
It looks as though Swift has some type of support for submodules (they're mentioned offhand a few places), but I'm not sure we have the ability to actually compile those just yet.