Bagaimana cara mengimpor file Swift dari file Swift lain?

154

Saya hanya ingin memasukkan kelas Swift saya dari file lain, seperti pengujiannya

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

Kedua file cepat berada di direktori yang sama.

joseph.hainline
sumber
2
Menurut apple docs, Anda tidak perlu mengimpor ketika kedua file memiliki target yang sama. Sayangnya tes memiliki target berbeda. Salah satu solusi yang mungkin adalah dengan melakukan pernyataan impor menggunakan yourModule / PrimeNumberModel.
Alex Reynolds
@ joseph.hainline Saya menghadapi masalah yang sama. Bagaimana itu akan diselesaikan? Saya terjebak sekarang.
Pengembang

Jawaban:

131

Saya memiliki masalah yang sama, juga dalam XCTestCasefile saya , tetapi tidak dalam file proyek biasa.

Untuk menghilangkan:

Penggunaan pengidentifikasi yang belum terselesaikan 'PrimeNumberModel'

Saya perlu importmodul dasar dalam file tes. Dalam kasus saya, target saya disebut 'myproject' dan saya menambahkan import myprojectdan kelasnya dikenali.

H6.
sumber
2
Ini membutuhkan lebih banyak upvotes. Jawaban yang menyarankan untuk hanya menambahkan file .swift ke target tes tidak sepenuhnya salah, tapi itu bukan cara yang seharusnya dilakukan
bawah
10
Tapi apa yang harus dilakukan dengan nama proyek saya "Wildlife League", yang memiliki ruang di dalamnya?
allenlinli
59
Dimulai dengan Beta 4, Anda juga harus memastikan pengaturan kontrol akses Anda sudah benar. Anda harus menetapkan secara eksplisit kelas yang Anda uji dan fungsi yang Anda uji di dalam kelas tersebut public. Kalau tidak, XCTestCasesubclass tidak akan dapat "melihat" apa yang Anda coba untuk menguji. Saya menghabiskan beberapa jam pada malam terakhir ini :)
Erik P. Hansen
2
Jika saya tidak salah, Nama Modul Produk (dalam pengaturan target build) tidak selalu sama dengan nama target dan itu adalah nama modul yang harus digunakan dalam importpernyataan
csch
3
Jika target Swift memiliki spasi dalam namanya, Anda dapat mengimpornya dengan mengganti spasi dengan garis bawah pada pernyataan impor. "My Swift Class" menjadi "My_Swift_Class".
Cin316
70

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

Sekarang Anda tidak perlu menambahkan publicmetode untuk menguji itu. Pada versi Swift yang lebih baru, hanya perlu menambahkan @testablekata kunci.

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

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

Dan metode internal Anda dapat dipertahankan Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Perhatikan bahwa private(dan fileprivate) simbol tidak tersedia bahkan dengan menggunakan @testable.


Swift 1.x

Ada dua konsep yang relevan dari Swift di sini (As Xcode 6 beta 6).

  1. Anda tidak perlu mengimpor kelas Swift, tetapi Anda perlu mengimpor modul eksternal (target)
  2. Level Kontrol Akses Default di Swift adalahInternal access

Mempertimbangkan bahwa tes berada pada target lain pada PrimeNumberModelTests.swiftAnda perlu importtarget yang berisi kelas yang ingin Anda uji, jika target Anda dipanggil MyProjectperlu menambahkan import MyProjectke PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

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

Tetapi ini tidak cukup untuk menguji kelas Anda PrimeNumberModel, karena tingkat Kontrol Akses default adalah Internal Access, kelas Anda tidak akan terlihat oleh bundel tes, jadi Anda perlu membuatnya Public Accessdan semua metode yang ingin Anda uji:

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}
Diogo T
sumber
adakah cara untuk mengubah Kontrol Akses default? Saya memiliki case lucu yang digunakan untuk menjalankan tanpa pengubah publik baik-baik saja, kemudian saya memindahkan test case sekitar, tiba-tiba berhenti bekerja lagi.
Metaphox
Saya pikir itu tidak mungkin, setidaknya untuk versi cepat saat ini.
Diogo T
Terima kasih. Dan saya menemukan bahwa masalah saya adalah bahwa file cepat tidak membangun ke target pengujian dengan kasus uji.
Metaphox
1
ya, di situlah saya merasa salah - saya seharusnya tidak membangun file swift kelas menjadi target test case. posting blog yang bagus! Terima kasih.
Metaphox
1
Jika Anda memiliki proyek yang dibuat dengan Xcode 5 atau lebih baru dan Anda memilih untuk pendekatan "akses publik, impor modul target", periksa ulang nama modul untuk target pengujian Anda karena mungkin sama dengan target utama. Jika Anda menerima No such module <moduleName>kesalahan kompilasi dalam kasus pengujian Anda, Anda mungkin ingin memeriksa PRODUCT_MODULE_NAMEtarget pengujian. Jawaban yang bagus Diogo.
Chris
48

Dalam Dokumentasi dikatakan tidak ada pernyataan impor di Swift.

masukkan deskripsi gambar di sini

Cukup gunakan:

let primNumber = PrimeNumberModel()
Nitin Gohel
sumber
2
Ini berhasil tetapi saya harus menutup dan membuka kembali Xcode 6.0 untuk kelas yang akhirnya muncul. Coba bersihkan dan bangun proyek juga.
user3344977
Ini sepertinya baru (atau masalah) dalam XCode 6.3 beta terbaru, jadi pernyataan impor diperlukan sekarang. Juga ada pernyataan impor di Swift, untuk mengimpor modul.
Augunrik
Menurut dokumentasi yang disediakan, tabel ini dengan "Tidak ada pernyataan impor" terkait dengan kasus "Impor dari target yang sama". Dalam hal XCTests Anda menggunakan target (tes) yang berbeda, jadi perhatikan bagian "Mengimpor Kerangka Eksternal" dari artikel, ada tabel lain: Kerangka bahasa apa pun -> Impor ke Swift -> impor "FrameworkName" diperlukan
Igor Vasilev
Jika Anda melihat masalah di editor, seringkali ada target pengujian yang tidak menyertakan kelas. Jadi Anda mungkin membangun denda runnable Anda, tetapi jika salah satu dari target mengalami masalah, itu masih menunjukkan kesalahan. Jika Anda memilih salah satu dari target itu, Anda tidak dapat dikompilasi.
Joel Teply
34

Periksa target-keanggotaan PrimeNumberModel.swift di target pengujian Anda.

kimkkikki
sumber
1
tolong tambahkan ini sebagai komentar.
4dgaurav
8
Orang ini tidak bisa, dia perlu 9 rep lagi untuk melakukannya (pada saat penulisan).
AlbertEngelB
1
Apa yang dimaksud dengan target?
Pengguna
Terima kasih, ini berhasil untuk saya. Klik pada file kelas. Periksa tab pertama kolom inspektur di sebelah kanan. Bagian kedua adalah "Keanggotaan Target". Pastikan target / produk yang Anda coba masukkan kelas dipilih.
Hairgami_Master
1
Ini bukan jawaban untuk pertanyaan "bagaimana cara mengimpor ...", tetapi itu menjawab pertanyaan yang saya bawa yang membawa saya ke sini (saya lupa menambahkan file baru ke target). Jadi bagi saya, dan orang lain yang akan tiba di sini dengan mengikuti hasil google pertama untuk "kelas pengenal cepat yang belum terselesaikan", ini adalah jawaban (dan bukan komentar).
noamtm
17

Di Objective-C, jika Anda ingin menggunakan kelas di file lain, Anda harus mengimpornya:

#import "SomeClass.h"

Namun, di Swift, Anda tidak perlu mengimpor sama sekali. Cukup gunakan seolah-olah sudah diimpor.

Contoh

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

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

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

Seperti yang Anda lihat, tidak diperlukan impor. Semoga ini membantu.

Fomentia
sumber
Terima kasih! Masih menyiasati semua hal baru ini di Swift.
Felipe
5

Menurut Apple Anda tidak perlu mengimpor untuk file cepat di Target yang Sama. Saya akhirnya berhasil dengan menambahkan file cepat ke target reguler dan target pengujian saya. Kemudian saya menggunakan bridging header untuk pengujian untuk memastikan file ObjC saya yang saya rujuk di header bridging biasa saya tersedia. Berlari seperti pesona sekarang.

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

}

JADI pastikan PrimeNumberModel memiliki target Target pengujian Anda. Atau solusi High6 untuk mengimpor seluruh modul Anda akan berfungsi

Alex Reynolds
sumber
Apakah ini hanya berfungsi untuk kelas logika / model, atau bisakah saya menggunakannya juga untuk Delegasi Aplikasi?
Nicolas Miari
5

Saya dapat mengatasi masalah ini dengan membersihkan bangunan saya.

Menu atas -> Produk -> Bersihkan Atau pintasan keyboard: Shift+ Cmd+K

Peter Fisher
sumber
4

Pada Swift 2.0, praktik terbaik adalah:

Tambahkan baris @testable import MyAppke bagian atas file tes Anda, di mana "MyApp" adalah Nama Modul Produk dari target aplikasi Anda (dapat dilihat di pengaturan build target aplikasi Anda ). Itu dia.

(Perhatikan bahwa nama modul produk akan sama dengan nama target aplikasi Anda kecuali nama target aplikasi Anda berisi spasi, yang akan diganti dengan garis bawah. Misalnya, jika target aplikasi saya disebut "Permainan Menyenangkan" saya akan menulis @testable import Fun_Gamedi atas tes saya.)

George WS
sumber
1

Anda perlu menambahkan rutin untuk kompiler untuk referensi sebagai titik masuk, jadi tambahkan file main.swift, yang dalam hal ini hanya membuat turunan dari file pengujian Anda:

cepat

PrimeNumberModelTests()

Kemudian kompilasi pada baris perintah (saya menggunakan El Capitan dan Swift 2.2):

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

Dalam hal ini, Anda akan mendapatkan peringatan: hasil initializer tidak digunakan , tetapi program mengkompilasi dan dieksekusi:

./PrimeNumberMain

CAVEAT: Saya menghapus jenis impor XCTest dan XCTestCase untuk kesederhanaan.

Biji pinus
sumber
1

Periksa PrimeNumberModelTestsPengaturan Target Anda .

Jika Anda tidak dapat melihat PrimeNumberModel.swiftfile di Build Phases/Compile Sources, tambahkan.

Bumseok
sumber
Ini bukan cara yang tepat untuk melakukannya, periksa respons High6.
Diogo T
0

Jadi, Anda harus melakukannya

  1. Impor modul eksternal yang ingin Anda gunakan
  2. Dan pastikan Anda memiliki pengubah akses yang tepat di kelas dan metode yang ingin Anda gunakan.

Dalam kasus saya, saya memiliki file cepat yang ingin saya uji unit, dan file uji unit juga kelas cepat. Saya memastikan pengubah akses sudah benar, tetapi pernyataan itu

import stMobile

(katakanlah stMobile adalah nama target kami)

masih tidak bekerja (saya masih mendapatkan kesalahan 'Tidak ada modul'), saya memeriksa target saya, dan namanya memang stMobile. Jadi, saya pergi ke Pengaturan Bangun, di bawah pengemasan, dan menemukan Nama Modul Produk, dan untuk beberapa alasan ini disebut St_Mobile, jadi saya mengubah pernyataan impor saya

import St_Mobile

(yang merupakan Nama Modul Produk ), dan semuanya berfungsi.

Jadi, untuk meringkas:

  1. Periksa Nama Modul Produk Anda dan gunakan pernyataan impor di bawah ini di kelas uji unit Anda

    import myProductModuleName
  2. Pastikan pengubah akses Anda benar (tingkat kelas dan metode Anda).

Cloud9999Strife
sumber
0

Alih-alih membutuhkan impor eksplisit, kompiler Swift secara implisit mencari .swiftmodulefile perpustakaan Swift dependensi.

Xcode dapat membangun modul cepat untuk Anda, atau merujuk ke blog railsware untuk instruksi baris perintah swiftc.

mcandre
sumber
0

Seperti @ high6 dan @ erik-p-hansen tunjukkan dalam jawaban yang diberikan oleh @ high6, ini dapat diatasi dengan mengimpor target untuk modul di mana kelas PrimeNumberModel berada, yang mungkin nama yang sama dengan proyek Anda dalam proyek sederhana .

Sambil melihat ini, saya menemukan artikel Menulis Tes Unit pertama Anda di Swift di swiftcast.tv oleh Clayton McIlrath. Ini membahas pengubah akses, menunjukkan contoh dari masalah yang sama yang Anda alami (tetapi untuk ViewController daripada file model) dan menunjukkan cara mengimpor target dan memecahkan masalah pengubah akses dengan memasukkan file tujuan dalam target, yang berarti Anda tidak harus membuat kelas yang Anda coba uji publik kecuali Anda benar-benar ingin melakukannya.

mr_sd
sumber