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?
Related
Would there be drawbacks in performance when I arrange my codes as,
import Foundation
class Foo { }
import SomethingElse
extension Foo: SomethingElse { }
compared to putting all the imported modules at the beginning of the file?
import Foundation
import SomethingElse
class Foo { }
extension Foo: SomethingElse { }
It shouldn't matter, see here
Most Swift files in your app are order-independent, meaning you can
use a type before it is defined, and can even import modules at the
bottom of the file (although that is not recommended Swift style.)
Basically packages are imported at the top of usable classes to write code in a more optimized way, while importing those packages in middle doesn't raise any issue but sure effects the compiler way to compile files.
import Foundation
class Foo {
// if raises any exception here below code wait for compilation until handle it.
}
import SomethingElse // import when make sense with //MARK:
extension Foo: SomethingElse {
}
This could be a modern way of programming ahead because optimized code changes always makes program better.
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.
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 ! :)
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...
}
}
Consider:
A Swift framework called FrameworkA that defines the type Thing.
A Swift framework called FrameworkB that also defines the type Thing and the type FrameworkA.
An app that imports both frameworks in the same Swift file.
How do I reference FrameworkA.Thing in said file? The following line fails with Thing is not a member of FrameworkA.
let t : FrameworkA.Thing? = nil
This appears to be a Swift bug. As a workaround, you can create a new Swift file in the app that imports only FrameworkA and defines a typealias for Thing:
import FrameworkA
typealias ThingA = Thing
Then in the file that needs to import both frameworks, you use ThingA instead of FrameworkA.Thing.