Wie importiere ich eine Swift-Datei aus einer anderen Swift-Datei?

154

Ich möchte einfach meine Swift-Klasse aus einer anderen Datei einschließen, wie z. B. den Test

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'"    
}

Beide Swift-Dateien befinden sich im selben Verzeichnis.

joseph.hainline
quelle
2
Laut Apple Docs benötigen Sie keinen Import, wenn beide Dateien dasselbe Ziel haben. Leider haben Tests ein anderes Ziel. Eine mögliche Lösung könnte darin bestehen, eine Importanweisung mit yourModule / PrimeNumberModel durchzuführen.
Alex Reynolds
@ joseph.hainline Ich stehe vor dem gleichen Problem. Wie wird es gelöst? Ich stecke jetzt fest.
Entwickler

Antworten:

131

Ich hatte das gleiche Problem, auch in meinen XCTestCaseDateien, aber nicht in den regulären Projektdateien.

Um das loszuwerden:

Verwendung der ungelösten Kennung 'PrimeNumberModel'

Ich brauchte importdas Basismodul in der Testdatei. In meinem Fall heißt mein Ziel " mein Projekt" und ich habe hinzugefügt import myprojectund die Klasse wurde erkannt.

H6.
quelle
2
Dies erfordert mehr Upvotes. Die Antworten, die empfehlen, nur die .swift-Datei zum Testziel hinzuzufügen, sind nicht genau falsch, aber es ist nicht so, wie es gemacht werden sollte
unter dem
10
Aber was soll ich mit meinem Projektnamen "Wildlife League" machen, in dem Platz ist?
Allenlinli
59
Ab Beta 4 müssen Sie außerdem sicherstellen, dass Ihre Einstellungen für die Zugriffskontrolle korrekt sind. Sie müssen sowohl die Klasse, die Sie testen, als auch die Funktionen, die Sie in dieser Klasse testen, explizit als festlegen public. Andernfalls kann die XCTestCaseUnterklasse nicht "sehen", was Sie testen möchten. Ich habe ein paar Stunden an diesem letzten Abend verschwendet :)
Erik P. Hansen
2
Wenn ich mich nicht irre, stimmt der Name des Produktmoduls (in den Einstellungen für die Zielerstellung) nicht immer mit dem Namen des Ziels überein, und es ist der Name des Moduls, der in der importAnweisung verwendet werden sollte
csch
3
Wenn ein Swift-Ziel ein Leerzeichen in seinem Namen hat, können Sie es importieren, indem Sie die Leerzeichen in der Importanweisung durch Unterstriche ersetzen. "My Swift Class" wird zu "My_Swift_Class".
Cin316
70

UPDATE Swift 2.x, 3.x, 4.x und 5.x.

Jetzt müssen Sie die publiczu den zu testenden Methoden nicht mehr hinzufügen . In neueren Versionen von Swift muss nur das @testableSchlüsselwort hinzugefügt werden .

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

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

Und Ihre internen Methoden können halten Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Beachten Sie, dass private(und fileprivate) Symbole auch bei Verwendung nicht verfügbar sind @testable.


Swift 1.x.

Hier gibt es zwei relevante Konzepte von Swift (As Xcode 6 Beta 6).

  1. Sie müssen keine Swift-Klassen importieren, aber Sie müssen externe Module (Ziele) importieren.
  2. Die Standard - Zugriffssteuerungsebene in Swift istInternal access

Bedenkt man, dass Prüfungen an einem anderen Ziel sind auf PrimeNumberModelTests.swiftSie müssen importdas Ziel, das die Klasse enthält , die Sie testen möchten, ob Ihr Ziel genannt wird MyProjecthinzufügen müssen , import MyProjectum die PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

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

Dies reicht jedoch nicht aus, um Ihre Klasse zu testen PrimeNumberModel, da die Standardzugriffssteuerungsstufe lautet Internal Access, dass Ihre Klasse für das Testpaket nicht sichtbar ist. Daher müssen Sie sie Public Accessund alle Methoden erstellen, die Sie testen möchten:

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}
Diogo T.
quelle
Gibt es eine Möglichkeit, die Standardzugriffskontrolle zu ändern? Ich hatte einen lustigen Fall, in dem es früher ohne öffentlichen Modifikator lief, dann habe ich die Testfälle verschoben, es funktionierte plötzlich nicht mehr.
Metaphox
Ich denke, das ist nicht möglich, zumindest für die aktuelle Version von Swift.
Diogo T
Vielen Dank. Und ich fand heraus, dass mein Problem darin bestand, dass die schnelle Datei mit den Testfällen nicht zum Testziel erstellt wurde.
Metaphox
1
Ja, genau dort habe ich mich falsch gefühlt - ich sollte die Class-Swift-Datei nicht in das Testfallziel einbauen. schöner Blogbeitrag! Vielen Dank.
Metaphox
1
Wenn Sie ein Projekt mit Xcode 5 oder höher erstellt haben und sich für den Ansatz "Öffentlicher Zugriff, Zielmodul importieren" entscheiden, überprüfen Sie den Modulnamen für Ihr Testziel, da dieser möglicherweise mit dem Hauptziel identisch ist. Wenn No such module <moduleName>in Ihrem Testfall ein Kompilierungsfehler angezeigt wird, möchten Sie möglicherweise PRODUCT_MODULE_NAMEdas Testziel überprüfen . Tolle Antwort Diogo.
Chris
48

In der Dokumentation heißt es, dass Swift keine Importanweisungen enthält.

Geben Sie hier die Bildbeschreibung ein

Verwenden Sie einfach:

let primNumber = PrimeNumberModel()
Nitin Gohel
quelle
2
Dies funktionierte, aber ich musste Xcode 6.0 schließen und erneut öffnen, damit die Klasse endlich angezeigt wurde. Versuchen Sie auch, das Projekt zu reinigen und zu erstellen.
user3344977
Dies scheint neu (oder ein Problem) in den neuesten XCode 6.3-Betaversionen zu sein, daher ist die Importanweisung jetzt erforderlich. Außerdem gibt es in Swift eine Importanweisung zum Importieren von Modulen.
Augunrik
Gemäß der bereitgestellten Dokumentation bezieht sich diese Tabelle mit "Keine Importanweisung" auf den Fall "Import vom selben Ziel". Wenn Sie für XCTests ein anderes (Test-) Ziel verwenden, beachten Sie den Abschnitt "Importieren externer Frameworks" des Artikels. Es gibt eine weitere Tabelle: Jedes Sprachframework -> In Swift importieren -> "FrameworkName" importieren
Igor Vasilev
Wenn im Editor ein Problem auftritt, gibt es häufig ein Testziel, in dem die Klasse nicht enthalten ist. Sie erstellen also wahrscheinlich Ihre ausführbare Datei, aber wenn eines der Ziele ein Problem aufweist, wird der Fehler weiterhin angezeigt. Wenn Sie eines dieser anderen Ziele ausgewählt hätten, könnten Sie es nicht kompilieren.
Joel Teply
34

Überprüfen Sie die Zielmitgliedschaft von PrimeNumberModel.swift in Ihrem Testziel.

kimkkikki
quelle
1
Bitte fügen Sie dies als Kommentar hinzu.
4dgaurav
8
Diese Person kann nicht, sie braucht 9 weitere Wiederholungen, um dies zu tun (zum Zeitpunkt des Schreibens).
AlbertEngelB
1
Was zum Teufel ist ein Ziel?
Benutzer
Danke, das hat bei mir funktioniert. Klicken Sie auf die Klassendatei. Überprüfen Sie die erste Registerkarte der Inspektorspalte rechts. Der zweite Abschnitt ist "Zielmitgliedschaft". Stellen Sie sicher, dass das Ziel / Produkt ausgewählt ist, das Sie in die Klasse aufnehmen möchten.
Hairgami_Master
1
Es ist nicht unbedingt eine Antwort auf die Frage "Wie importiere ich ...", aber es hat die Frage beantwortet, die mich hierher gebracht hat (ich habe vergessen, dem Ziel eine neue Datei hinzuzufügen). Also für mich, und andere , die hier ankommen , werden durch nach dem ersten Google - Ergebnis für „swift ungelöste Kennung Klasse“, dies ist eine Antwort (und kein Kommentar).
Noamtm
17

Wenn Sie in Objective-C eine Klasse in einer anderen Datei verwenden möchten, müssen Sie sie importieren:

#import "SomeClass.h"

In Swift müssen Sie jedoch überhaupt nicht importieren. Verwenden Sie es einfach so, als wäre es bereits importiert worden.

Beispiel

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

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

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

Wie Sie sehen, war kein Import erforderlich. Hoffe das hilft.

Fomentia
quelle
Vielen Dank! Ich komme immer noch um all diese neuen Sachen in Swift herum.
Felipe
5

Laut Apple benötigen Sie keinen Import für schnelle Dateien im selben Ziel. Ich habe es endlich geschafft, indem ich meine schnelle Datei sowohl zu meinem regulären Ziel als auch zu meinem Testziel hinzugefügt habe. Dann habe ich den Bridging-Header zum Testen verwendet, um sicherzustellen, dass meine ObjC-Dateien, auf die ich in meinem regulären Bridging-Header verwiesen habe, verfügbar sind. Lief jetzt wie ein Zauber.

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.
    }
}

}

Stellen Sie also sicher, dass PrimeNumberModel ein Ziel Ihres Testziels hat. Oder die High6-Lösung zum Importieren Ihres gesamten Moduls funktioniert

Alex Reynolds
quelle
Funktioniert dies nur für Logik- / Modellklassen oder kann ich es auch für den Anwendungsdelegierten verwenden?
Nicolas Miari
5

Ich konnte dieses Problem lösen, indem ich meinen Build säuberte.

Hauptmenü -> Produkt -> Reinigen oder Tastenkombination: Shift+ Cmd+K

Peter Fisher
quelle
4

Ab Swift 2.0 ist die beste Vorgehensweise:

Fügen Sie die Zeile @testable import MyAppoben in Ihre Testdatei ein, wobei "MyApp" der Name des Produktmoduls Ihres App-Ziels ist (in den Build-Einstellungen Ihres App-Ziels sichtbar ). Das ist es.

(Beachten Sie, dass das Produkt Modulnamen die gleiche wie Ihre App Ziel Name sein wird , es sei denn , Ihre Anwendung Ziel der Name Leerzeichen enthält, die mit Unterstrichen ersetzt werden. Zum Beispiel, wenn meine app Ziel genannt wurde „Fun Game“ Ich schreibe würde @testable import Fun_Gamebei der oben auf meinen Tests.)

George WS
quelle
1

Sie müssen eine Routine hinzufügen, auf die der Compiler als Einstiegspunkt verweisen kann. Fügen Sie daher eine main.swift-Datei hinzu, die in diesem Fall einfach eine Instanz Ihrer Testdatei erstellt:

main.swift

PrimeNumberModelTests()

Dann kompilieren Sie in der Befehlszeile (ich verwende El Capitan und Swift 2.2):

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

In diesem Fall erhalten Sie eine Warnung: Das Ergebnis des Initialisierers wird nicht verwendet , aber das Programm wird kompiliert und ist ausführbar:

./PrimeNumberMain

CAVEAT: Der Einfachheit halber habe ich den Importtyp XCTest und XCTestCase entfernt.

Tannenzapfen
quelle
1

Überprüfen Sie Ihre PrimeNumberModelTestsZieleinstellungen.

Wenn Sie die PrimeNumberModel.swiftDatei in Build nicht sehen können Phases/Compile Sources, fügen Sie sie hinzu.

Bumseok
quelle
Dies ist nicht der richtige Weg. Überprüfen Sie die High6-Antwort.
Diogo T
0

Also musst du

  1. Importieren Sie externe Module, die Sie verwenden möchten
  2. Stellen Sie sicher, dass Sie über die richtigen Zugriffsmodifikatoren für die Klasse und die Methoden verfügen, die Sie verwenden möchten.

In meinem Fall hatte ich eine schnelle Datei, die ich einem Unit-Test unterziehen wollte, und die Unit-Test-Datei war auch eine schnelle Klasse. Ich habe sichergestellt, dass die Zugriffsmodifikatoren korrekt waren, aber die Anweisung

import stMobile

(Nehmen wir an, stMobile ist unser Zielname)

funktionierte immer noch nicht (ich bekam immer noch den Fehler "Kein solches Modul"), ich überprüfte mein Ziel und sein Name war in der Tat stMobile. Also ging ich zu Build-Einstellungen unter Verpackung und fand den Namen des Produktmoduls. Aus irgendeinem Grund hieß dieser Name St_Mobile, also änderte ich meine Importanweisung

import St_Mobile

(das ist der Name des Produktmoduls ), und alles hat funktioniert.

Um es zusammenzufassen:

  1. Überprüfen Sie den Namen Ihres Produktmoduls und verwenden Sie die folgende Importanweisung in Ihrer Unit-Test-Klasse

    import myProductModuleName
  2. Stellen Sie sicher, dass Ihre Zugriffsmodifikatoren korrekt sind (Klassenebene und Ihre Methoden).

Cloud9999Strife
quelle
0

Anstatt explizite Importe zu erfordern, sucht der Swift-Compiler implizit nach .swiftmoduleDateien mit Swift-Abhängigkeitsbibliotheken.

Xcode kann schnelle Module für Sie erstellen oder Anweisungen zur Befehlszeile finden Sie im Railsware-Blogswiftc .

mcandre
quelle
0

Wie @ high6 und @ erik-p-hansen in der Antwort von @ high6 betonten, kann dies überwunden werden, indem das Ziel für das Modul importiert wird, in dem sich die PrimeNumberModel-Klasse befindet. Dies ist wahrscheinlich der gleiche Name wie Ihr Projekt in einem einfachen Projekt .

Während ich mir das ansah , stieß ich auf den Artikel Schreiben Sie Ihren ersten Unit Test in Swift auf swiftcast.tv von Clayton McIlrath. Es werden Zugriffsmodifikatoren erläutert, ein Beispiel für dasselbe Problem angezeigt (jedoch für einen ViewController anstelle einer Modelldatei) und es wird gezeigt, wie Sie das Ziel importieren und das Problem mit den Zugriffsmodifikatoren lösen, indem Sie die Zieldatei in das Ziel aufnehmen Sie müssen die Klasse, die Sie testen möchten, nicht öffentlich machen, es sei denn, Sie möchten dies tatsächlich tun.

mr_sd
quelle