How do I import a swift function declared in a compiled .swiftmodule into another swift file?
The .swiftmodule
describes the Swift module's interface but it does not contain the module's implementation. A library or set of object files is still required to link your application against. Here's a modified version of the makefile that creates both libhello.dylib and hello.swiftmodule and builds the application against them:
PWD=$(shell pwd)
APP_NAME=main
MODULE_NAME=hello
LIB_NAME=lib$(MODULE_NAME).dylib
LIB_PATH=$(PWD)/$(LIB_NAME)
SWIFT_MODULE_PATH=$(PWD)/$(MODULE_NAME).swiftmodule
main : clean
xcrun swift \
-emit-library \
-o $(LIB_PATH) \
-Xlinker -install_name \
-Xlinker @rpath/$(LIB_NAME) \
-emit-module \
-emit-module-path $(SWIFT_MODULE_PATH) \
-module-name $(MODULE_NAME) \
-module-link-name $(MODULE_NAME) \
-v \
$(MODULE_NAME).swift
xcrun swift $(APP_NAME).swift \
-o $(APP_NAME) \
-I $(PWD) \
-L $(PWD) \
-Xlinker -rpath \
-Xlinker @executable_path/ \
-v
clean :
rm -rf $(APP_NAME) $(LIB_NAME) $(MODULE_NAME).swiftmodule $(MODULE_NAME).swiftdoc
In the absence of documentation I can't say that this is entirely correct, but it works.
Note that if you simply want to use multiple source files within your application module this is much more straightforward and requires no import
declaration or module qualification in main.swift:
swift -o main hello.swift main.swift
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.
Swift function forward-declaration or prototype
You cannot declare a function in Swift without defining it, the compiler
needs "foo.swift" in order to compile "main.swift".
Here is an example how one can compile Swift files separately and then link the object files:
swift -frontend -c -module-name myprog -primary-file main.swift foo.swift
swift -frontend -c -module-name myprog -primary-file foo.swift main.swift
swiftc -o myprog main.o foo.o
This is a very simple example, for real applications you probably need to import
additional frameworks and set more options. It can be instructive to check waht
Xcode does when building a project, the full compiler and linker output
can be found in the Report navigator.
See also SWIFT MAKEFILES – TAKE 2
for a general GNU Make based solution.
Another option is to compile against a
.swiftmodule and a shared library, compare e.g. How do I import a swift function declared in a compiled .swiftmodule into another swift file?.
Then func foo
must be marked as public
:
foo.swift:
public func foo() {
print("foo")
}
swiftc -emit-module -emit-library -module-name Foo -module-link-name Foo foo.swift
creates Foo.swiftmodule and libFoo.dylib (this can also be done in
separate steps). Now main.swift can import the Foo module
main.swift:
import Foo
foo()
swiftc -emit-object -I . main.swift
and the object file can be linked against the shared library:
swiftc -o myprog -L . main.o
What does a module mean in swift?
A module is a single unit of code distribution—a framework or application that is built and shipped as a single unit and that can be imported by another module with Swift’s import keyword.
Each build target (such as an app bundle or framework) in Xcode is treated as a separate module in Swift. If you group together aspects of your app’s code as a stand-alone framework—perhaps to encapsulate and reuse that code across multiple applications—then everything you define within that framework will be part of a separate module when it’s imported and used within an app, or when it’s used within another framework.
As the docs indicate, the module is an application or a framework (library). If you create a project with classes A
and B
, they are part of the same module. Any other class in the same project can inherit from those classes. If you however import that project to another project, classes from that another project won't be able to subclass A
nor B
. For that you would have to add open
indicator before their declarations.
Basically, if you work on a single app then you are working in one single module and unless declared as private
or fileprivate
, the classes can subclass each other.
EDIT
Let us have following class in module (project) Module1:
class A {
}
Since this class is not open
, it can be subclassed only within the same module. That means that following class:
class B: A {
}
Can be written only in the same project, in Module1.
If you add Module1 as a dependency to project Module2, and try to do this:
import Module1
class C: A {
}
It will not compile. That's because class A
is not open
(in other words it has access public
or less) and it does not belong to the same module as C
. A
belongs to Module1, C
belongs to Module2.
Note
import
keyword imports a dependency module to your current module. If you write import UIKit
in your project, you are telling the compiler that you want to use module UIKit
in your module. import
does not define current module. Current module is the current project.
Adding import UIKit
at the beginning of the file does not change nor define to which module the file belongs. It just tells the compiler that in that file you want to use code from UIKit
module.
How to reuse Swift code in other projects?
- Create a new project (iOS Cocoa Touch Framework) for your reusable code
- Move your classes to that Framework project
- Mark your methods and classes, that should be visible to others as
public
- Create Workspace.
You can create a workspace on step 1. When you create new Framework project, Xcode will ask you if you want to create new workspace and add that project to workspace. This is the best approach - Add both your project and Framework to the workspace
- Select you project target -> General tab. Add Framework and Libraries (add your library here)
- When you want to use code from your Library in swift file, import it using
import 'LibTargetName'
Getting error No such module using Xcode, but the framework is there
I'm not sure why this happens, but one way to solve your issue is to go into your build settings and defining the Framework Search Paths to a folder which contains the frameworks in question. If the frameworks are placed in your project directory, simply set the framework search path to $(SRCROOT)
and set it to recursive.
Related Topics
Why Can't I Use a Tuple Constant as a Case in a Switch Statement
Converting a C-Style for Loop That Uses Division for the Step to Swift 3
Implicit Return in a Closure Causing an Error
Is This a Good Way to Display Asynchronous Data
How to Write a Function That Will Unwrap a Generic Property in Swift Assuming It Is an Optional Type
Parameters After Opening Bracket
How to Convert Between Related Types Through a Common Initializer
What Are 'Get' and 'Set' in Swift
Swift Error: Missing Return in a Function Expected to Return 'String'
Autolayout Contraints for a View from Xib
Skphysicsbody Avoid Collision Swift/Spritekit
Does a Mutating Struct Function in Swift Create a New Copy of Self
Fibonacci Calculator Stack Overflows at 93Nd Number in Swift
How to Upload Zip Data with Alamofire
Global Function Sequence(State:Next:) and Type Inference