Come importare un file Swift da un altro file Swift?


154

Voglio semplicemente includere la mia classe Swift da un altro file, come il suo 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'"    
}

Entrambi i file rapidi si trovano nella stessa directory.



2
Secondo i documenti di Apple non è necessaria un'importazione quando entrambi i file hanno lo stesso target. Purtroppo i test hanno un obiettivo diverso. Una possibile soluzione potrebbe essere quella di fare una dichiarazione di importazione usando yourModule / PrimeNumberModel.
Alex Reynolds,

@Joseph.hainline Sto affrontando lo stesso problema. Come verrà risolto? Sono bloccato ora.
Sviluppatore

Risposte:


131

Ho avuto lo stesso problema, anche nei miei XCTestCasefile, ma non nei normali file di progetto.

Per sbarazzarsi di:

Utilizzo dell'identificatore non risolto "PrimeNumberModel"

Avevo bisogno importdel modulo base nel file di test. Nel mio caso, il mio obiettivo si chiama "myproject" e ho aggiunto import myprojecte la classe è stata riconosciuta.


2
Ciò richiede più voti. Le risposte che consigliano di aggiungere il file .swift alla destinazione del test non sono esattamente sbagliate, ma non è il modo in cui dovrebbe essere fatto
sotto il

10
Ma cosa c'entra il nome del mio progetto "Wildlife League", che contiene spazio?
Allenlinli,

59
A partire da Beta 4, dovrai anche assicurarti che le impostazioni di controllo degli accessi siano corrette. Dovrai impostare esplicitamente sia la classe che stai testando sia le funzioni che stai testando all'interno di quella classe public. Altrimenti la XCTestCasesottoclasse non sarà in grado di "vedere" ciò che stai cercando di testare. Ho perso qualche ora in quest'ultima notte :)
Erik P. Hansen,

2
Se non sbaglio, il modulo del prodotto Nome (in impostazioni di generazione di destinazione) non è sempre uguale al nome del bersaglio ed è il nome del modulo che dovrebbe essere utilizzato nella importdichiarazione
csch

3
Se una destinazione Swift ha uno spazio nel suo nome, puoi importarlo sostituendo gli spazi con caratteri di sottolineatura nell'istruzione import. "My Swift Class" diventa "My_Swift_Class".
Cin316,

70

AGGIORNAMENTO Swift 2.x, 3.x, 4.xe 5.x

Ora non è necessario aggiungere publici metodi ai test da testare. Nelle versioni più recenti di Swift è necessario solo aggiungere la @testableparola chiave.

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

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

E i tuoi metodi interni possono mantenere Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Si noti che i simboli private(e fileprivate) non sono disponibili anche con l'utilizzo @testable.


Swift 1.x

Qui ci sono due concetti rilevanti di Swift (come Xcode 6 beta 6).

  1. Non è necessario importare classi Swift, ma è necessario importare moduli esterni (destinazioni)
  2. Il livello di controllo di accesso predefinito in Swift èInternal access

Considerando che i test sono su un altro target, PrimeNumberModelTests.swiftè necessario importil target che contiene la classe che si desidera testare, se il target viene chiamato MyProjectsarà necessario aggiungere import MyProjecta PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

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

Ma questo non è abbastanza per testare la tua classe PrimeNumberModel, dal momento che il livello di controllo di accesso predefinito è Internal Access, la tua classe non sarà visibile al bundle di test, quindi devi farlo Public Accesse tutti i metodi che vuoi testare:

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}

c'è un modo per modificare il controllo di accesso predefinito? Ho avuto un caso divertente che funzionava senza modificatore pubblico, quindi ho spostato i casi di test, improvvisamente ha smesso di funzionare.
Metaphox,

Penso che non sia possibile, almeno per l'attuale versione di Swift.
Diogo T,

Grazie. E ho scoperto che il mio problema era che il file rapido non è stato creato sulla destinazione del test con i casi di test.
Metaphox,

1
Sì, era esattamente lì che mi sentivo male: non avrei dovuto compilare il file rapido della classe nella destinazione del test case. bel post sul blog! Grazie.
Metaphox,

1
Se hai un progetto creato con Xcode 5 o versione successiva e stai optando per l'approccio "accesso pubblico, importazione modulo di destinazione", ricontrolla il nome del modulo per la tua destinazione di test in quanto potrebbe essere uguale alla destinazione principale. Se ricevi un No such module <moduleName>errore di compilazione nel tuo caso di test, potresti voler verificare la PRODUCT_MODULE_NAMEdestinazione del test. Ottima risposta Diogo.
Chris,

48

Nella documentazione afferma che non ci sono dichiarazioni di importazione in Swift.

inserisci qui la descrizione dell'immagine

Usa semplicemente:

let primNumber = PrimeNumberModel()

2
Questo ha funzionato ma ho dovuto chiudere e riaprire Xcode 6.0 affinché la classe potesse finalmente essere visualizzata. Prova anche a pulire e costruire il progetto.
user3344977

Questo sembra essere nuovo (o un problema) negli ultimi XCode 6.3 beta, quindi la dichiarazione di importazione è ora necessaria. Inoltre c'è una dichiarazione di importazione in Swift, per importare i moduli.
Augunrik,

Secondo la documentazione fornita, questa tabella con "Nessuna dichiarazione di importazione" è correlata al caso "Importa dalla stessa destinazione". Nel caso di XCTest utilizzi target (test) diversi, quindi osserva la sezione "Importazione di frame esterni" dell'articolo, c'è un'altra tabella: Qualsiasi framework linguistico -> Importa in Swift -> è necessario importare "FrameworkName"
Igor Vasilev

Se vedi un problema nell'editor, è spesso che esiste un obiettivo di prova che non include la classe. Quindi probabilmente costruisci bene il tuo eseguibile, ma se qualcuno dei target ha un problema, mostra comunque l'errore. Se avessi selezionato uno di quegli altri target, non ti permetterebbe di compilare.
Joel Teply,

34

Controlla l'appartenenza al target di PrimeNumberModel.swift nel target di test.


1
si prega di aggiungere questo come commento.
4dgaurav,

8
Questa persona non può, ha bisogno di altri 9 rappresentanti per farlo (al momento della stesura).
AlbertEngelB,

1
Che diamine è un bersaglio?
Utente

Grazie ha funzionato per me. Fai clic sul file della classe. Controlla la prima scheda della colonna dell'ispettore sulla destra. La seconda sezione è "Target Membership". Assicurarsi che sia selezionato il target / prodotto che si sta tentando di includere nella classe.
Hairgami_Master

1
Non è strettamente una risposta alla domanda "come posso importare ...", ma ha risposto alla domanda che avevo che mi ha portato qui (ho dimenticato di aggiungere un nuovo file alla destinazione). Quindi, per me e per altri che arriveranno qui seguendo il primo risultato di Google per "rapida classe di identificatori irrisolti", questa è una risposta (e non un commento).
noamtm,

17

In Objective-C, se si desidera utilizzare una classe in un altro file, è necessario importarla:

#import "SomeClass.h"

Tuttavia, in Swift, non devi importare affatto. Usalo semplicemente come se fosse già stato importato.

Esempio

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

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

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

Come puoi vedere, non è stata necessaria l'importazione. Spero che questo ti aiuti.


Grazie! Continuo ad aggirare tutte queste novità da Swift.
Felipe,

5

Secondo Apple non è necessaria un'importazione per file rapidi nello stesso target. Finalmente ho funzionato aggiungendo il mio file rapido sia al mio target normale sia al target di test. Quindi ho usato l'intestazione bridge per test per assicurarmi che i miei file ObjC a cui facevo riferimento nella mia normale intestazione bridge fossero disponibili. Ho corso come un fascino adesso.

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

}

Quindi assicurati che PrimeNumberModel abbia un target del tuo target di test. Oppure funzionerà la soluzione High6 di importazione dell'intero modulo


Funziona solo per le classi logiche / modello o posso usarlo anche per il delegato dell'applicazione?
Nicolas Miari,

5

Sono stato in grado di risolvere questo problema pulendo la mia build.

Menu principale -> Prodotto -> Pulizia o scorciatoia da tastiera: Shift+ Cmd+K


4

A partire da Swift 2.0, la migliore pratica è:

Aggiungi la riga @testable import MyAppall'inizio del file dei test, dove "MyApp" è il nome del modulo del prodotto del target dell'app (visualizzabile nelle impostazioni di build del target dell'app). Questo è tutto.

(Tieni presente che il nome del modulo del prodotto sarà lo stesso del nome del target della tua app a meno che il nome del target della tua app non contenga spazi, che verrà sostituito con caratteri di sottolineatura. Ad esempio, se il target della mia app fosse chiamato "Gioco divertente" scriverei @testable import Fun_Gamenel parte superiore dei miei test.)


1

È necessario aggiungere una routine affinché il compilatore faccia riferimento come punto di ingresso, quindi aggiungere un file main.swift, che in questo caso crea semplicemente un'istanza del file di test:

main.swift

PrimeNumberModelTests()

Quindi compilare dalla riga di comando (sto usando El Capitan e Swift 2.2):

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

In questo caso, riceverai un avviso: il risultato dell'inizializzatore non è utilizzato , ma il programma viene compilato ed è eseguibile:

./PrimeNumberMain

CAVEAT: Ho rimosso il tipo di importazione XCTest e XCTestCase per semplicità.


1

Controlla le tue PrimeNumberModelTestsimpostazioni target.

Se non riesci a vedere il PrimeNumberModel.swiftfile in Build Phases/Compile Sources, aggiungilo.


Questo non è il modo giusto per farlo, controlla la risposta High6.
Diogo T,

0

Quindi, è necessario

  1. Importa i moduli esterni che desideri utilizzare
  2. E assicurati di avere i corretti modificatori di accesso sulla classe e sui metodi che desideri utilizzare.

Nel mio caso avevo un file rapido che volevo testare l'unità, e anche il file test unit era una classe rapida. Mi sono assicurato che i modificatori di accesso fossero corretti, ma la dichiarazione

import stMobile

(diciamo che stMobile è il nostro nome target)

continuava a non funzionare (continuavo a ricevere l'errore "Nessun modulo del genere"), controllavo il mio obiettivo e il suo nome era effettivamente stMobile. Quindi, sono andato a Build Settings, in packaging, e ho trovato il nome del modulo del prodotto, e per qualche ragione questo è stato chiamato St_Mobile, quindi ho cambiato la mia dichiarazione di importazione

import St_Mobile

(che è il nome del modulo del prodotto ) e tutto ha funzionato.

Quindi, per riassumere:

  1. Controllare il nome del modulo del prodotto e utilizzare la seguente dichiarazione di importazione nella classe di test dell'unità

    import myProductModuleName
  2. Assicurati che i modificatori di accesso siano corretti (livello di classe e metodi).


0

Invece di richiedere importazioni esplicite, il compilatore Swift cerca implicitamente i .swiftmodulefile delle librerie Swift di dipendenza.

Xcode può creare moduli rapidi per te o consultare il blog di railsware per istruzioni sulla riga di comando swiftc.


0

Come sottolineato da @ high6 e @ erik-p-hansen nella risposta data da @ high6, questo può essere superato importando il target per il modulo in cui si trova la classe PrimeNumberModel, che probabilmente è lo stesso nome del progetto in un semplice progetto .

Guardando questo, mi sono imbattuto nell'articolo Scrivi il tuo primo test unit in Swift su swiftcast.tv di Clayton McIlrath. Discute i modificatori di accesso, mostra un esempio dello stesso problema riscontrato (ma per un ViewController anziché un file modello) e mostra come sia importare la destinazione sia risolvere il problema del modificatore di accesso includendo il file di destinazione nella destinazione, il che significa non è necessario rendere pubblica la classe che si sta tentando di provare a meno che non si desideri effettivamente farlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.