Como importo um arquivo Swift de outro arquivo Swift?


154

Eu simplesmente quero incluir minha classe Swift de outro arquivo, como seu teste

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

Os dois arquivos rápidos estão no mesmo diretório.



2
De acordo com os documentos da apple, você não precisa de uma importação quando os dois arquivos têm o mesmo destino. Infelizmente, os testes têm um alvo diferente. Uma solução possível pode ser fazer uma declaração de importação usando yourModule / PrimeNumberModel.
Alex Reynolds

@ joseph.hainline Estou enfrentando o mesmo problema. Como será resolvido? Eu estou preso agora.
Desenvolvedor

Respostas:


131

Eu tive o mesmo problema, também nos meus XCTestCasearquivos, mas não nos arquivos regulares do projeto.

Para se livrar do:

Uso do identificador não resolvido 'PrimeNumberModel'

Eu precisava importdo módulo base no arquivo de teste. No meu caso, meu destino é chamado 'myproject' e eu adicionei import myprojecte a classe foi reconhecida.


2
Isso precisa de mais votos. As respostas recomendando apenas adicionar o arquivo .swift ao destino do teste não estão exatamente erradas, mas não é o que deve ser feito
abaixo de

10
Mas o que fazer com o nome do meu projeto "Wildlife League", que tem espaço?
allenlinli

59
A partir do Beta 4, você também precisará verificar se as configurações de controle de acesso estão corretas. Você precisará definir explicitamente a classe que está testando e as funções que está testando nessa classe como public. Caso contrário, a XCTestCasesubclasse não poderá "ver" o que você está tentando testar. Eu desperdiçado algumas horas nesta última noite :)
Erik P. Hansen

2
Se não me engano, o produto Nome do Módulo (em configurações de compilação-alvo) não é sempre o mesmo que o nome do alvo e é o nome do módulo que deve ser utilizado na importdeclaração
csch

3
Se um destino Swift tiver um espaço em seu nome, você poderá importá-lo, substituindo os espaços por sublinhados na instrução de importação. "Minha classe Swift" se torna "My_Swift_Class".
Cin316

70

ATUALIZAÇÃO Swift 2.x, 3.x, 4.xe 5.x

Agora você não precisa adicionar publicos métodos aos testes para então. Nas versões mais recentes do Swift, é necessário apenas adicionar a @testablepalavra - chave.

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

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

E seus métodos internos podem manter Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Observe que os símbolos private(e fileprivate) não estão disponíveis mesmo com o uso @testable.


Swift 1.x

Existem dois conceitos relevantes da Swift aqui (como Xcode 6 beta 6).

  1. Você não precisa importar classes Swift, mas precisa importar módulos externos (destinos)
  2. O nível de controle de acesso padrão no Swift éInternal access

Considerando que os testes estão em outro destino, PrimeNumberModelTests.swiftvocê precisa importdo destino que contém a classe que deseja testar, se o seu destino for chamado, MyProjectserá necessário adicionar import MyProjectao PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

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

Mas isso não é suficiente para testar sua classe PrimeNumberModel, já que o nível padrão de Controle de Acesso é que Internal Accesssua classe não estará visível para o pacote de teste, portanto, você precisa fazer isso Public Accesse todos os métodos que deseja testar:

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}

existe alguma maneira de alterar o controle de acesso padrão? Eu tive um caso engraçado que costumava ser executado sem modificador público, então mudei os casos de teste, e de repente parou de funcionar.
Metaphox

Eu acho que isso não é possível, pelo menos para a versão atual do swift.
Diogo T

obrigado. E descobri que meu problema era que o arquivo rápido não era criado para o destino de teste nos casos de teste.
Metaphox

1
Sim, foi exatamente onde me senti mal - não devo criar o arquivo swift de classe no destino do caso de teste. bom post no blog! obrigado.
Metaphox

1
Se você tiver um projeto criado com o Xcode 5 ou posterior e estiver optando pela abordagem "acesso público, importar módulo de destino", verifique duas vezes o nome do módulo para o seu destino de teste, pois pode ser o mesmo que o destino principal. Se você estiver recebendo um No such module <moduleName>erro de compilação no seu caso de teste, convém verificar o PRODUCT_MODULE_NAMEdestino do teste. Ótima resposta Diogo.
Chris

48

Na documentação , diz que não há instruções de importação no Swift.

insira a descrição da imagem aqui

Basta usar:

let primNumber = PrimeNumberModel()

2
Isso funcionou, mas eu tive que fechar e reabrir o Xcode 6.0 para que a classe finalmente aparecesse. Tente limpar e criar o projeto também.
user3344977

Isso parece ser novo (ou um problema) nas versões beta mais recentes do XCode 6.3, portanto, a declaração de importação é necessária agora. Também há uma declaração de importação no Swift, para importar módulos.
Augunrik

De acordo com a documentação fornecida, esta tabela com "Nenhuma declaração de importação" está relacionada ao caso "Importar do mesmo destino". No caso de XCTests, você usa um destino diferente (teste); portanto, observe a seção "Importando estruturas externas" do artigo, existe outra tabela: Qualquer estrutura de idioma -> Importar para Swift -> importação "FrameworkName" é necessária
Igor Vasilev

Se você vir um problema no editor, geralmente há um destino de teste que não inclui a classe. Portanto, você provavelmente cria sua multa executável, mas se algum dos destinos estiver com um problema, ele ainda mostra o erro. Se você tivesse selecionado um desses outros destinos, ele não deixaria você compilar.
Joel Teply #

34

Verifique a associação ao destino de PrimeNumberModel.swift no seu destino de teste.


1
adicione isso como comentário.
4dgaurav

8
Essa pessoa não pode, precisa de mais 9 representantes para fazê-lo (no momento da redação).
AlbertEngelB

1
O que diabos é um alvo?
Utilizador

Graças isso funcionou para mim. Clique no arquivo da turma. Verifique a primeira guia da coluna do inspetor à direita. A segunda seção é "Membro de destino". Verifique se o destino / produto que você está tentando incluir na classe está selecionado.
Hairgami_Master 27/03

1
Não é estritamente uma resposta à pergunta "como importo ...", mas respondeu à pergunta que me trouxe aqui (esqueci de adicionar um novo arquivo ao destino). Então, para mim e para outras pessoas que chegarão aqui, seguindo o primeiro resultado do Google para "classe de identificador não resolvido rápida", essa é uma resposta (e não um comentário).
noamtm

17

No Objective-C, se você quiser usar uma classe em outro arquivo, precisará importá-lo:

#import "SomeClass.h"

No entanto, no Swift, você não precisa importar. Basta usá-lo como se já estivesse importado.

Exemplo

// 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 você pode ver, nenhuma importação foi necessária. Espero que isto ajude.


Obrigado! Ainda contornando todas essas novidades de Swift.
Felipe

5

De acordo com a Apple, você não precisa de uma importação para arquivos rápidos no mesmo destino. Finalmente consegui trabalhar adicionando meu arquivo rápido ao meu objetivo comum e ao objetivo de teste. Em seguida, usei o cabeçalho da ponte para teste para garantir que meus arquivos ObjC que eu referenciei no meu cabeçalho de ponte normal estavam disponíveis. Corria como um encanto agora.

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

}

Portanto, verifique se o PrimeNumberModel tem um destino para o seu destino de teste. Ou a solução High6 de importar todo o módulo funcionará


Isso funciona apenas para classes de lógica / modelo ou também posso usá-lo para o Application Delegate?
Nicolas Miari

5

Consegui resolver esse problema limpando minha compilação.

Menu superior -> Produto -> Limpar ou atalho de teclado: Shift+ Cmd+K


4

A partir do Swift 2.0, a melhor prática é:

Adicione a linha @testable import MyAppna parte superior do seu arquivo de testes, em que "MyApp" é o Nome do módulo do produto do seu destino de aplicativo (visível nas configurações de compilação do seu destino de aplicativo ). É isso aí.

(Observe que o nome do módulo do produto será o mesmo do destino do seu aplicativo, a menos que o nome do destino do aplicativo contenha espaços, que serão substituídos por sublinhados. Por exemplo, se meu destino do aplicativo se chamar "Jogo divertido", eu escreveria @testable import Fun_Gameno topo dos meus testes.)


1

Você precisa adicionar uma rotina para o compilador fazer referência como um ponto de entrada; portanto, adicione um arquivo main.swift, que nesse caso simplesmente cria uma instância do seu arquivo de teste:

main.swift

PrimeNumberModelTests()

Em seguida, compile na linha de comando (estou usando El Capitan e Swift 2.2):

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

Nesse caso, você receberá um aviso: o resultado do inicializador não é usado , mas o programa compila e é executável:

./PrimeNumberMain

CAVEAT: removi os tipos de importação XCTest e XCTestCase por simplicidade.


1

Verifique suas PrimeNumberModelTestsconfigurações de destino.

Se você não conseguir ver o PrimeNumberModel.swiftarquivo no Build Phases/Compile Sources, adicione-o.


Esta não é a maneira correta de fazer isso, verifique a resposta High6.
Diogo T

0

Então, você precisa

  1. Importar módulos externos que você deseja usar
  2. E verifique se você possui os modificadores de acesso corretos na classe e nos métodos que deseja usar.

No meu caso, eu tinha um arquivo rápido que queria fazer teste de unidade, e o arquivo de teste de unidade também era uma classe rápida. Verifiquei se os modificadores de acesso estavam corretos, mas a declaração

import stMobile

(digamos que stMobile é o nosso nome de destino)

ainda não funcionou (eu ainda estava recebendo o erro 'Não existe esse módulo'), verifiquei meu destino e seu nome era realmente stMobile. Então, eu fui para Build Settings, embaixo da embalagem, e encontrei o Product Module Name e, por algum motivo, isso foi chamado St_Mobile, então mudei minha declaração de importação

import St_Mobile

(que é o nome do módulo do produto ) e tudo funcionou.

Entao, para resumir:

  1. Verifique o nome do módulo do produto e use a declaração de importação abaixo na sua classe de teste de unidade

    import myProductModuleName
  2. Verifique se seus modificadores de acesso estão corretos (nível de classe e seus métodos).


0

Em vez de exigir importações explícitas, o compilador Swift procura implicitamente .swiftmodulearquivos de bibliotecas Swift de dependência.

O Xcode pode criar módulos rápidos para você, ou consulte o blog do railsware para obter instruções sobre a linha de comando swiftc.


0

Como @ high6 e @ erik-p-hansen apontaram na resposta dada por @ high6, isso pode ser superado importando o destino para o módulo onde está a classe PrimeNumberModel, que provavelmente é o mesmo nome do seu projeto em um projeto simples .

Enquanto olhava para isso, deparei-me com o artigo Escreva seu primeiro teste de unidade no Swift no swiftcast.tv de Clayton McIlrath. Ele discute os modificadores de acesso, mostra um exemplo do mesmo problema que você está tendo (mas para um ViewController em vez de um arquivo de modelo) e mostra como importar o destino e resolver o problema do modificador de acesso, incluindo o arquivo de destino no destino, o que significa você não precisa tornar pública a classe que está tentando testar, a menos que realmente queira fazê-lo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.