¿Cómo importo un archivo Swift de otro archivo Swift?

154

Simplemente quiero incluir mi clase Swift de otro archivo, como su prueba

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

Ambos archivos rápidos están en el mismo directorio.

joseph.hainline
fuente
2
De acuerdo con los documentos de Apple, no necesita una importación cuando ambos archivos tienen el mismo objetivo. Lamentablemente, las pruebas tienen un objetivo diferente. Una posible solución podría ser hacer una declaración de importación usando yourModule / PrimeNumberModel.
Alex Reynolds
@ joseph.hainline Estoy enfrentando el mismo problema. ¿Cómo se resolverá? Estoy atrapado ahora.
Desarrollador

Respuestas:

131

Tuve el mismo problema, también en mis XCTestCasearchivos, pero no en los archivos normales del proyecto.

Para deshacerse de:

Uso del identificador no resuelto 'PrimeNumberModel'

Necesitaba importel módulo base en el archivo de prueba. En mi caso, mi objetivo se llama 'myproject' y agregué import myprojecty la clase fue reconocida.

H6.
fuente
2
Esto necesita más votos a favor. Las respuestas que aconsejan simplemente agregar el archivo .swift al objetivo de la prueba no son exactamente incorrectas, pero no es la forma en que debería hacerse
por debajo del
10
Pero, ¿qué hacer con el nombre de mi proyecto "Wildlife League", que tiene espacio?
allenlinli
59
A partir de Beta 4, también deberá asegurarse de que la configuración de control de acceso sea correcta. Tendrá que establecer explícitamente tanto la clase que está probando como las funciones que está probando dentro de esa clase public. De lo contrario, la XCTestCasesubclase no podrá "ver" lo que está intentando probar. Perdí unas horas en esta última noche :)
Erik P. Hansen
2
Si no me equivoco, el Nombre del módulo del producto (en la configuración de compilación del objetivo) no siempre es el mismo que el nombre del objetivo y es el nombre del módulo que debe usarse en la importdeclaración
csch
3
Si un objetivo Swift tiene un espacio en su nombre, puede importarlo reemplazando los espacios con guiones bajos en la declaración de importación. "My Swift Class" se convierte en "My_Swift_Class".
Cin316
70

ACTUALIZACIÓN Swift 2.x, 3.x, 4.xy 5.x

Ahora no necesita agregar el publica los métodos para probar entonces. En las versiones más recientes de Swift solo es necesario agregar la @testablepalabra clave.

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

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

Y sus métodos internos pueden mantener Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Tenga en cuenta que private(y fileprivate) los símbolos no están disponibles incluso con el uso @testable.


Swift 1.x

Aquí hay dos conceptos relevantes de Swift (como Xcode 6 beta 6).

  1. No necesita importar clases Swift, pero necesita importar módulos externos (objetivos)
  2. El nivel de control de acceso predeterminado en Swift esInternal access

Teniendo en cuenta que las pruebas están en otro objetivo en el PrimeNumberModelTests.swiftque necesita importel objetivo que contiene la clase que desea probar, si se llama a su objetivoMyProject deberá agregar import MyProjecta PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

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

Pero esto no es suficiente para probar su clase PrimeNumberModel, ya que el nivel de control de acceso predeterminado es que Internal Accesssu clase no será visible para el paquete de prueba, por lo que debe hacerlo Public Accessy todos los métodos que desea probar:

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}
Diogo T
fuente
¿Hay alguna forma de cambiar el control de acceso predeterminado? Tuve un caso divertido que solía ejecutarse sin un modificador público muy bien, luego moví los casos de prueba, de repente dejó de funcionar.
Metaphox
Creo que eso no es posible, al menos para la versión actual de swift.
Diogo T
Gracias. Y descubrí que mi problema era que el archivo swift no está construido para el objetivo de prueba con los casos de prueba.
Metaphox
1
Sí, eso fue exactamente donde me sentí mal: no debería construir el archivo de clase rápida en el objetivo del caso de prueba. buena publicación de blog! Gracias.
Metaphox
1
Si tiene un proyecto creado con Xcode 5 o posterior y está optando por el enfoque de "acceso público, importar módulo objetivo", verifique dos veces el nombre del módulo para su objetivo de prueba, ya que podría ser el mismo que el objetivo principal. Si recibe un No such module <moduleName>error de compilación en su caso de prueba, es posible que desee verificar el PRODUCT_MODULE_NAMEobjetivo de la prueba. Gran respuesta Diogo.
Chris
48

En la documentación dice que no hay declaraciones de importación en Swift.

ingrese la descripción de la imagen aquí

Simplemente use:

let primNumber = PrimeNumberModel()
Nitin Gohel
fuente
2
Esto funcionó pero tuve que cerrar y volver a abrir Xcode 6.0 para que la clase finalmente apareciera. Intente limpiar y construir el proyecto también.
user3344977
Esto parece ser nuevo (o un problema) en los últimos XCode 6.3 beta, por lo que la declaración de importación es necesaria ahora. También hay una declaración de importación en Swift, para importar módulos.
Augunrik
De acuerdo con la documentación proporcionada, esta tabla con "Declaración de no importación" está relacionada con el caso "Importar desde el mismo destino". En el caso de XCTests, utiliza un objetivo diferente (prueba), así que observe la sección "Importar marcos externos" del artículo, hay otra tabla: Cualquier marco de idioma -> Importar a Swift -> importar "FrameworkName" es necesario
Igor Vasilev
Si ve un problema en el editor, a menudo hay un objetivo de prueba que no incluye la clase. Por lo tanto, es probable que construya su multa ejecutable, pero si alguno de los objetivos tiene un problema, aún muestra el error. Si hubiera seleccionado uno de esos otros objetivos, no le permitiría compilar.
Joel Teply
34

Verifique la membresía objetivo de PrimeNumberModel.swift en su objetivo de prueba.

kimkkikki
fuente
1
por favor agregue esto como comentario.
4dgaurav
8
Esta persona no puede, necesita 9 representantes más para hacerlo (al momento de escribir).
AlbertEngelB
1
¿Qué diablos es un objetivo?
Usuario
Gracias, esto funcionó para mí. Haga clic en el archivo de la clase. Verifique la primera pestaña de la columna del inspector a la derecha. La segunda sección es "Membresía objetivo". Asegúrese de que esté seleccionado el objetivo / producto que está tratando de incluir la clase.
Hairgami_Master
1
No es estrictamente una respuesta a la pregunta "cómo importo ...", pero sí respondió la pregunta que tuve que me trajo aquí (olvidé agregar un nuevo archivo al objetivo). Entonces, para mí y para otros que llegarán aquí siguiendo el primer resultado de Google para "clase de identificador rápido no resuelto", esta es una respuesta (y no un comentario).
noamtm
17

En Objective-C, si deseaba usar una clase en otro archivo, tenía que importarla:

#import "SomeClass.h"

Sin embargo, en Swift, no tiene que importar nada. Simplemente utilícelo como si ya estuviera importado.

Ejemplo

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

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

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

Como puede ver, no se necesitaba importar. Espero que esto ayude.

Fomentia
fuente
¡Gracias! Todavía estoy manejando todas estas cosas nuevas de Swift.
Felipe
5

Según Apple, no necesita importar archivos rápidos en el mismo destino. Finalmente conseguí que funcione agregando mi archivo swift tanto a mi objetivo regular como a mi objetivo de prueba. Luego utilicé el encabezado de puente para la prueba para asegurarme de que mis archivos ObjC a los que hice referencia en mi encabezado de puente regular estaban disponibles. Corrió como un encanto ahora.

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

}

ASÍ que asegúrese de que PrimeNumberModel tenga un objetivo de su Objetivo de prueba. O la solución High6 de importar todo tu módulo funcionará

Alex Reynolds
fuente
¿Funciona esto solo para las clases de lógica / modelo, o puedo usarlo también para el Delegado de aplicaciones?
Nicolas Miari
5

Pude resolver este problema limpiando mi compilación.

Menú superior -> Producto -> Limpiar o método abreviado de teclado: Shift+ Cmd+K

Peter Fisher
fuente
4

A partir de Swift 2.0, la mejor práctica es:

Agregue la línea @testable import MyAppen la parte superior de su archivo de pruebas, donde "MyApp" es el nombre del módulo del producto del objetivo de su aplicación (visible en la configuración de compilación del objetivo de su aplicación ). Eso es.

(Tenga en cuenta que el nombre del módulo del producto será el mismo que el nombre del objetivo de su aplicación a menos que el nombre del objetivo de la aplicación contenga espacios, que se reemplazarán con guiones bajos. Por ejemplo, si el objetivo de mi aplicación se llamara "Juego divertido", escribiría @testable import Fun_Gameen el arriba de mis pruebas.)

George WS
fuente
1

Debe agregar una rutina para que el compilador haga referencia como un punto de entrada, así que agregue un archivo main.swift, que en este caso simplemente crea una instancia de su archivo de prueba:

main.swift

PrimeNumberModelTests()

Luego compile en la línea de comando (estoy usando El Capitan y Swift 2.2):

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

En este caso, recibirá una advertencia: el resultado del inicializador no se utiliza , pero el programa se compila y es ejecutable:

./PrimeNumberMain

CAVEAT: Eliminé el tipo XCTest y XCTestCase de importación por simplicidad.

Piña
fuente
1

Verifique su PrimeNumberModelTestsconfiguración de destino.

Si no puede ver el PrimeNumberModel.swiftarchivo en Build Phases/Compile Sources, agréguelo.

Bumseok
fuente
Esta no es la forma correcta de hacerlo, verifique la respuesta High6.
Diogo T
0

Entonces, necesitas

  1. Importe los módulos externos que desea usar
  2. Y asegúrese de tener los modificadores de acceso correctos en la clase y los métodos que desea usar.

En mi caso, tenía un archivo rápido que quería probar unitario, y el archivo de prueba unitario también era una clase rápida. Me aseguré de que los modificadores de acceso fueran correctos, pero la declaración

import stMobile

(digamos que stMobile es nuestro nombre objetivo)

todavía no funcionaba (todavía recibía el error 'No hay tal módulo'), verifiqué mi objetivo y su nombre era stMobile. Entonces, fui a Build Settings, en el paquete, y encontré el Nombre del módulo del producto, y por alguna razón se llamaba St_Mobile, así que cambié mi declaración de importación

import St_Mobile

(que es el nombre del módulo del producto ), y todo funcionó.

Así que para resumir:

  1. Verifique el nombre del módulo del producto y use la declaración de importación a continuación en su clase de prueba unitaria

    import myProductModuleName
  2. Asegúrese de que sus modificadores de acceso sean correctos (nivel de clase y sus métodos).

Cloud9999Strife
fuente
0

En lugar de requerir importaciones explícitas, el compilador Swift busca implícitamente .swiftmodulearchivos de bibliotecas Swift de dependencia.

Xcode puede construir módulos rápidos para usted, o consulte el blog de railsware para obtener instrucciones sobre la línea de comandos swiftc.

mcandre
fuente
0

Como @ high6 y @ erik-p-hansen señalaron en la respuesta dada por @ high6, esto se puede superar importando el objetivo para el módulo donde está la clase PrimeNumberModel, que probablemente sea el mismo nombre que su proyecto en un proyecto simple .

Mientras miraba esto, me encontré con el artículo Escriba su primera prueba de unidad en Swift en swiftcast.tv por Clayton McIlrath. Analiza los modificadores de acceso, muestra un ejemplo del mismo problema que tiene (pero para un ViewController en lugar de un archivo de modelo) y muestra cómo importar el objetivo y resolver el problema del modificador de acceso al incluir el archivo de destino en el objetivo, lo que significa no tiene que hacer pública la clase que está tratando de evaluar a menos que realmente quiera hacerlo.

mr_sd
fuente