如何从一个Swift文件中导入另一个Swift文件?

163

我想从另一个文件中引用我的Swift类,就像测试那样。

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel { }

PrimeNumberModelTests.swift

import XCTest
import PrimeNumberModel  // gives me "No such module 'PrimeNumberModel'"

class PrimeNumberModelTests: XCTestCase {
    let testObject = PrimeNumberModel()  // "Use of unresolved identifier 'PrimeNumberModel'"    
}

两个 Swift 文件在同一个目录中。


2
根据苹果文档,当两个文件具有相同的目标时,您不需要导入。不幸的是,测试具有不同的目标。一种可能的解决方案是使用“yourModule/PrimeNumberModel”进行导入语句。 - Alex Reynolds
@joseph.hainline 我也遇到了同样的问题。这个问题怎么解决呢?我现在卡住了。 - Developer
13个回答

134

我也遇到了同样的问题,出现在我的XCTestCase文件中,但并未出现在普通的项目文件中。

为了消除:

Use of unresolved identifier 'PrimeNumberModel'

我需要在测试文件中import基础模块。在我的情况下,我的目标称为'myproject',我添加了import myproject,这个类被识别出来了。


2
这需要更多的赞。建议只需将.swift文件添加到测试目标的答案并不完全错误,但这不是正确的做法。 - below
10
我的项目名叫“野生动物联盟”,但它中间有空格,应该怎么处理? - allenlinli
59
从Beta 4开始,你还需要确保你的访问控制设置正确。你需要显式地将你要测试的类和该类中要测试的函数都设置为“public”。否则,XCTestCase子类将无法“看到”你试图测试的内容。我昨晚浪费了几个小时在这个问题上 :) - Erik P. Hansen
2
如果我没记错的话,在目标构建设置中,产品模块名称并不总是与目标名称相同,应该在import语句中使用模块名称。 - csch
3
如果 Swift 目标的名称中包含空格,您可以在导入语句中用下划线替换空格来导入它。"My Swift Class" 变成 "My_Swift_Class"。 - Cin316
显示剩余14条评论

73

更新Swift 2.x、3.x、4.x和5.x版本

现在,您不需要向方法添加public以测试它们。 在较新版本的Swift中,只需添加@testable关键字即可。

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

class PrimeNumberModelTests: XCTestCase {
    let testObject = PrimeNumberModel()
}

而你的内部方法可以保持Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

请注意,即使使用 @testableprivate(和 fileprivate)符号也不可用。


Swift 1.x

在 Swift 中有两个相关概念(截至 Xcode 6 beta 6):

  1. 您不需要导入 Swift 类,但需要导入外部模块(目标)
  2. Swift 中默认的访问控制级别是Internal access

考虑到测试位于 PrimeNumberModelTests.swift 的另一个目标上,如果您的目标称为 MyProject,则需要在 PrimeNumberModelTests 中添加 import MyProject导入包含要测试的类的目标:

PrimeNumberModelTests.swift

import XCTest
import MyProject

class PrimeNumberModelTests: XCTestCase {
    let testObject = PrimeNumberModel()
}

但这还不足以测试你的类PrimeNumberModel,因为默认的访问控制级别是Internal Access,你的类对于测试包将不可见,所以你需要将其改为Public Access,并且所有想要测试的方法也需要如此。

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}

谢谢。我发现我的问题是,Swift文件没有与测试用例一起构建到测试目标中。 - Metaphox
@Metaphox,你不应该在测试目标上构建类,请查看我写的有关此问题更详细的文章:http://blog.diogot.com/blog/2014/08/23/swift_access_control_and_testing/ - Diogo T
1
是的,那正是我感觉错了的地方——我不应该将类的Swift文件构建到测试用例目标中。很棒的博客文章!谢谢。 - Metaphox
1
如果您使用Xcode 5或更高版本创建了一个项目,并选择“公共访问,导入目标模块”方法,请仔细检查测试目标的模块名称,因为它可能与主目标相同。如果在测试用例中收到“没有这样的模块<moduleName>”编译错误,则可能需要检查测试目标的PRODUCT_MODULE_NAME。很好的答案Diogo。 - Chris
以防万一其他人也遇到类似的问题,您需要检查设置在项目>目标层次结构中的位置。单击目标设置编辑器左上方的“级别”选项(在选项卡控件下方),确保您的应用程序目标定义了“PRODUCT_MODULE_NAME”,但测试目标没有。您可能意外地在项目级别而不是目标级别上定义了PRODUCT_MODULE_NAME,导致您的两个目标具有相同的模块名称。 - Brian Gerstle
显示剩余2条评论

51
文档中指出,Swift中没有导入语句。

enter image description here

只需使用:

let primNumber = PrimeNumberModel()

2
这个方法可行,但我必须关闭并重新打开Xcode 6.0,才能最终看到这个类。也可以尝试清理并构建项目。 - user3344977
这似乎是最新的XCode 6.3 beta版中的新问题,因此现在需要导入语句。此外,在Swift中有一个导入模块的导入语句。 - Augunrik
根据提供的文档,这个没有“导入语句”的表格与“从同一目标导入”情况有关。在XCTests的情况下,您使用不同(测试)目标,因此请观察文章中的“导入外部框架”部分,那里有另一个表格:任何语言框架->导入到Swift->需要导入“FrameworkName”。 - Igor Vasilev
如果您在编辑器中看到问题,通常是因为有一个测试目标没有包含该类。因此,您可能会成功构建可运行文件,但如果任何一个目标存在问题,它仍然会显示错误。如果您选择了其中的另一个目标,则无法编译。 - Joel Teply

35

请检查您的测试目标中PrimeNumberModel.swift文件的目标成员资格。


1
please add this as comment. - 4dgaurav
9
这个人不能这样做,他还需要9点声望才能行动(在写作时)。 - AlbertEngelB
1
什么是目标? - User
谢谢,这个方法对我有用。点击那个类文件,在右边的检查器栏中检查第一个选项卡。第二个部分是“目标成员资格”。确保所要包括该类的目标/产品已被选择。 - Hairgami_Master
1
这并不是对问题“如何导入…”的严格回答,但它确实回答了我在这里所遇到的问题(我忘记将新文件添加到目标中)。所以对于我和其他通过搜索“Swift未解析标识符类”而来到这里的人来说,这才是一个回答(而不仅仅是评论)。 - noamtm
显示剩余2条评论

19

在 Objective-C 中,如果你想在另一个文件中使用一个类,你需要导入它:

#import "SomeClass.h"

然而,在Swift中,您根本不需要导入。只需像已经导入一样使用它。

示例

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

// This is a different file, named OtherClass.swift

class OtherClass : NSObject {
    let object = SomeClass()
}

如您所见,不需要导入任何内容。希望这能有所帮助。


谢谢!我还在适应Swift中的所有新东西。 - Felipe

6

我通过清理我的构建来解决了这个问题。

顶部菜单 -> 产品 -> 清理 或者使用快捷键:Shift+Cmd+K


6
根据苹果公司的说法,你不需要为同一目标中的Swift文件导入任何内容。我最后通过将我的Swift文件添加到常规目标和测试目标中来使其工作。然后我使用了测试的桥接头文件来确保我在常规桥接头文件中引用的ObjC文件可用。现在运行得非常好。
import XCTest
//Optionally you can import the whole Objc Module by doing #import ModuleName

class HHASettings_Tests: XCTestCase {

override func setUp() {
    let x : SettingsTableViewController = SettingsTableViewController()

    super.setUp()
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDown() {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    super.tearDown()
}

func testExample() {
    // This is an example of a functional test case.
    XCTAssert(true, "Pass")
}

func testPerformanceExample() {
    // This is an example of a performance test case.
    self.measureBlock() {
        // Put the code you want to measure the time of here.
    }
}

}

请确保PrimeNumberModel的目标是您的测试目标。或者,导入整个模块的High6解决方案也将起作用。

这只适用于Logic/Model类,还是我也可以在应用程序代理中使用它呢? - Nicolas Miari

5
从Swift 2.0开始,最佳实践是:
在你的测试文件顶部添加一行代码 @testable import MyApp,其中"MyApp"是你的应用程序目标的产品模块名称(可在应用程序目标的构建设置中查看)。就这样。 (请注意,产品模块名称将与您的应用程序目标的名称相同,除非您的应用程序目标的名称包含空格,否则将被替换为下划线。例如,如果我的应用程序目标称为“Fun Game”,那么我会在我的测试文件顶部编写@testable import Fun_Game。)

3

请检查PrimeNumberModelTests的目标设置。

如果在构建Phases/Compile Sources中无法看到PrimeNumberModel.swift文件,请添加它。


这不是正确的做法,请查看High6的响应。 - Diogo T

2
您需要添加一个例程作为编译器的入口点,因此请添加一个main.swift文件,在这种情况下,它只需创建您测试文件的实例: main.swift
PrimeNumberModelTests()

然后在命令行上编译(我使用的是El Capitan和Swift 2.2):

xcrun -sdk macosx swiftc -emit-executable -o PrimeNumberMain PrimeNumberModel.swift PrimeNumberModelTests.swift main.swift

在这种情况下,你会得到一个警告:initializer的结果未被使用,但程序可以编译并执行:
./PrimeNumberMain

注意:为了简化,我删除了import XCTest和XCTestCase类型。


(这是关于IT技术的提示信息)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接