What Is Import Func, Struct, Class, and @_Exported in Swift

What is import func, struct, class, and @_exported in Swift?

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 Foundation imported by default?

Yes UIKit imports Foundation so if you have #import <UIKit/UIKit.h> or import UIKit there is no need to import Foundation

Take a look at here in UIKit's source swift code Here

Edit

Here is useful information about how modules work in swift,

You can also selectively import certain declarations from a module:

import func Chess.createGreedyPlayer
import class Foundation.NSRegularExpression

Comparison with Other Languages

Importing a module is much like importing a library in Ruby, Python, or Perl,
importing a class in Java, or including a header file in a C-family
language. However, unlike C, module files are not textually included
and must be valid programs on their own, and may not be in a textual
format at all. Unlike Java, declarations in a module are not visible
at all until imported. And unlike the dynamic languages mentioned,
importing a module cannot automatically cause any code to be run.

Importing a module in swift uses one of three syntaxes below:

import [module]
import [module].[submodule]
import [import kind] [module].[symbol name]

when we do not specify the import kind while importing Data, we’re actually still just importing the entirety of Foundation.

there are multiple permissible import kinds available:

typealias | struct | class | enum | protocol | let | var | func

Like any other body of code, a module may depend on other modules in
its implementation. The module implementer may also choose to
re-export these modules, meaning that anyone who imports the first
module will also have access to the declarations in the re-exported
modules.

@exported import AmericanCheckers

As an example, the "Cocoa" framework on OS X exists only to re-export
three other frameworks: AppKit, Foundation, and CoreData.

Just as certain declarations can be selectively imported from a
module, so too can they be selectively re-exported, using the same
syntax:

@exported import class AmericanCheckers.Board

Exporting Package.swift for Swift Package Manager from existing Xcode project

There are no a menu command or utility to convert application to a static library, dynamic framework or swift package since they are different types of projects with different settings etc.

If you want to export a part of your project as a swift package you should make next steps manually:

1. Create Package.swift file in the root of your project

import PackageDescription

let package = Package(
name: “MyLib”,
products: [
.library(name: "MyLib", targets: ["MyLib"])
],
targets: [
.target(name: "MyLib"),
],
...
)

2. Make folder with subfolder ./Sources/MyLib under the projects’s root.

By default swift package structure requires to put all your sources files under Sources/LibraryName folder but you can change it below.

NOTE: you can simplify first two steps by using swift package init and it creates Package.swift, Sources and Test folders etc.

3. Include source files

a) Move the needed files to share from their current locations to MyLib folder.

For instance:

./Classes/MyEntity.swift -> ./Sources/MyLib/MyEntity.swift

Also you have to update locations of the moved files in your Xcode project to leave it compilable.

b) Use path, sources and exclude to point needed source files to your package from their current locations:

.target(name: "MyLib", path: "Classes"),

NOTE: Don't forget to make your classes public to access to them after import your package:

public class MyEntity {
...
}

After all you will have two working projects - old XCode's one and new Swift package.

4. REPL

Now you can use command line interpreter with your swift package:

swift run --repl
import MyLib
let entity = MyEntity()
...

Referring to a type in another module with the same name as a type in the current module when the other module has a type with its own name in Swift

the issue is ModuleA enum in ModuleA module does not have Test.

When you remove public in ModuleA enum then ModuleB cannot recognize there is a ModuleA enum because its access modifier is internal by default so ModuleB recognizes Test struct in ModuleA instead of trying to find Test in ModuleA enum


Bonus: There is a answer in SO about access modifiers I think you'll find useful.


EDIT:

If you need to use ModuleA.Test even there is an enum named ModuleA then you can use import (class|struct|func|protocol|enum) <needed_component> so in your case you should import like this:

import struct ModuleA.Test

If you want to use the struct with another name to avoid naming conflicts then you can set a typealias ->

import struct ModuleA.Test

typealias TestA = ModuleA.Test

Is it possible to alias an import?

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

How do I import a Swift file from another Swift file?

I had the same problem, also in my XCTestCase files, but not in the regular project files.

To get rid of the:

Use of unresolved identifier 'PrimeNumberModel'

I needed to import the base module in the test file. In my case, my target is called 'myproject' and I added import myproject and the class was recognised.

Is Foundation imported by default?

Yes UIKit imports Foundation so if you have #import <UIKit/UIKit.h> or import UIKit there is no need to import Foundation

Take a look at here in UIKit's source swift code Here

Edit

Here is useful information about how modules work in swift,

You can also selectively import certain declarations from a module:

import func Chess.createGreedyPlayer
import class Foundation.NSRegularExpression

Comparison with Other Languages

Importing a module is much like importing a library in Ruby, Python, or Perl,
importing a class in Java, or including a header file in a C-family
language. However, unlike C, module files are not textually included
and must be valid programs on their own, and may not be in a textual
format at all. Unlike Java, declarations in a module are not visible
at all until imported. And unlike the dynamic languages mentioned,
importing a module cannot automatically cause any code to be run.

Importing a module in swift uses one of three syntaxes below:

import [module]
import [module].[submodule]
import [import kind] [module].[symbol name]

when we do not specify the import kind while importing Data, we’re actually still just importing the entirety of Foundation.

there are multiple permissible import kinds available:

typealias | struct | class | enum | protocol | let | var | func

Like any other body of code, a module may depend on other modules in
its implementation. The module implementer may also choose to
re-export these modules, meaning that anyone who imports the first
module will also have access to the declarations in the re-exported
modules.

@exported import AmericanCheckers

As an example, the "Cocoa" framework on OS X exists only to re-export
three other frameworks: AppKit, Foundation, and CoreData.

Just as certain declarations can be selectively imported from a
module, so too can they be selectively re-exported, using the same
syntax:

@exported import class AmericanCheckers.Board

Create and import swift framework

I've done with the following steps.

  1. Create a framework project, for example named "FooKit". (Cocoa Touch Framework to be selected)
  2. Create a ".swift" file and add a public symbol, for example public func foo(), to it.
  3. Create an use-side (app) project. (I've chosen Single View Application)
  4. Open the root directory of "FooKit" by Finder, drag "FooKit.xcodeproj" there and drop it into the app project via Project Navigator.
  5. Add "FooKit" to Target Dependencies in the app's Build Phases setting.
  6. Add "FooKit.framework" to Embedded Binaries in the app's General setting.

Now you can build like this code in the use-side app.

import FooKit

func bar() {
foo()
}


Related Topics



Leave a reply



Submit