Как импортировать файл Swift из другого файла Swift?

Я просто хочу включить свой класс Swift из другого файла, например его тест

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

Оба файла swift находятся в одном каталоге.


person joseph.hainline    schedule 04.06.2014    source источник
comment
проверьте developer.apple.com/library/prerelease/ios/documentation/Swift/   -  person Nitin Gohel    schedule 04.06.2014
comment
Согласно документации Apple, вам не нужен импорт, если оба файла имеют одну и ту же цель. К сожалению, у тестов другая цель. Одним из возможных решений может быть выполнение оператора импорта с использованием yourModule / PrimeNumberModel.   -  person Alex Reynolds    schedule 05.06.2014
comment
@ joseph.hainline У меня такая же проблема. Как это разрешится? Я застрял.   -  person Developer    schedule 25.09.2014


Ответы (13)


У меня была такая же проблема, тоже в моих XCTestCase файлах, но не в обычных файлах проекта.

Чтобы избавиться от:

Использование неразрешенного идентификатора PrimeNumberModel

Мне нужно было import базовый модуль в тестовом файле. В моем случае моя цель называется myproject, я добавил import myproject, и класс был распознан.

person H6.    schedule 04.06.2014
comment
Да, это способ сделать это. Только я думаю, что вы импортируете не ваш проект, а цель, содержащую код, который вы хотите протестировать? - person Michael; 05.06.2014
comment
Спасибо, чувак, это сэкономило мне много времени. Вам нужно import <TARGET>. - person Jeffery Thomas; 07.06.2014
comment
Для этого нужно больше голосов. Ответы, рекомендующие просто добавить файл .swift в тестовую цель, не совсем неверны, но это не так, как это нужно делать. - person below; 22.06.2014
comment
Но что делать с моим проектом под названием «Лига дикой природы», в котором есть место? - person allenlinli; 08.07.2014
comment
Начиная с Beta 4, вам также необходимо убедиться, что ваши настройки контроля доступа верны. Вам необходимо явно указать как класс, который вы тестируете, так и функции, которые вы тестируете в этом классе, как public. В противном случае подкласс XCTestCase не сможет увидеть, что вы пытаетесь протестировать. Прошлой ночью я потратил на это несколько часов :) - person Erik P. Hansen; 01.08.2014
comment
У меня та же проблема, что и у OP, но import не помогло. Моя цель называется PresentAPIClient, но в модуле перечислены только import Foundation и import UIKit, в отличие от примеров проектов, которые, кажется, перечисляют доступные интерфейсы для модуля. Все мои исходные файлы включены в цель в источниках компиляции. - person HighFlyingFantasy; 08.08.2014
comment
@AllenLin: Хороший вопрос. У меня была такая же проблема, и я решил ее, просто переименовав свой проект. Я сделал это, щелкнув самый верхний элемент моих проектов в навигаторе проекта, нажав клавишу ВВОД и удалив все пробелы. XCode автоматически обработает переименование связанных файлов. - person Jeehut; 14.08.2014
comment
Однако мне пришлось вручную изменить запись Test Host в настройках сборки моей тестовой цели. Проверьте это также, если вы получите какие-либо ошибки Mach-O Linker после переименования проекта. - person Jeehut; 14.08.2014
comment
Если я не ошибаюсь, Имя модуля продукта (в настройках целевой сборки) не всегда совпадает с именем цели, и это имя модуля должно использоваться в выражении import. - person csch; 28.08.2014
comment
Я удалил пробел в имени моего проекта, но по-прежнему показывает ошибку Нет такого модуля. Почему? - person Developer; 25.09.2014
comment
Я думаю, что лучше всего будет добавить файл модели swift и любые другие файлы в тестовую цель. Тогда вам не нужно играть в игры с модификаторами доступа и выставлять все, что нужно для тестирования. - person Paul Solt; 19.11.2014
comment
Вдобавок к этому мне пришлось установить целевое членство в инспекторе файлов на правой боковой панели моего быстрого файла. - person Morgan Chen; 27.01.2015
comment
Если цель Swift имеет пробел в своем имени, вы можете импортировать его, заменив пробелы подчеркиванием в операторе импорта. Мой класс Swift становится My_Swift_Class. - person Cin316; 04.05.2015
comment
Что касается Xcode 6.3.1, не обязательно делать каждый класс общедоступным. Мне удалось заставить его работать, как описано выше, с внутренними классами. - person Arthur Gevorkyan; 26.06.2015
comment
@ArthurGevorkyan: Xcode 6.4, Swift 1.x здесь; пытается получить доступ к AppDelegate из подкласса XCTestCase (который imports MyAppTargetName). Пометка класса и методов делегата приложения как public работает нормально; маркировка как internal дает Использование необработанного идентификатора AppDelegate в подклассе XCTestCase. - person Nicolas Miari; 05.08.2015
comment
Я пробовал: оставив AppDelegate и его свойства / методы как internal, но изменив целевое членство AppDelegate.swift, чтобы включить и тестовую цель. Это строится, но во время выполнения тест терпит неудачу, потому что let delegate = UIApplication.sharedApplication().delegate as? AppDelegate терпит неудачу (либо его nil, либо объект другого типа - не проверено). Если вместо этого я сделаю все public и удалю целевое членство, это сработает. - person Nicolas Miari; 05.08.2015
comment
[продолжение] оказывается, что это не тот тип, не nil! Это бросок, который терпит неудачу. - person Nicolas Miari; 05.08.2015
comment
@NicolasMiari, это значит, что с твоей настройкой все в порядке? Если да, то поздравляю :) - person Arthur Gevorkyan; 06.08.2015
comment
@ ErikP.Hansen, ты болван - person Neil Japhtha; 05.09.2016

ОБНОВЛЕНИЕ Swift 2.x, 3.x, 4.x и 5.x

Теперь вам не нужно добавлять public к методам для тестирования. В более новых версиях Swift необходимо только добавить @testable ключевое слово.

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

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

И ваши внутренние методы могут сохранять Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Обратите внимание, что символы privatefileprivate) недоступны даже при использовании @testable.


Swift 1.x

Здесь есть две важные концепции Swift (как Xcode 6 beta 6).

  1. Вам не нужно импортировать классы Swift, но вам нужно импортировать внешние модули (цели)
  2. Значение по умолчанию Уровень контроля доступа в Swift равен Internal access

Учитывая, что тесты относятся к другой цели на PrimeNumberModelTests.swift, вам нужно import цель, содержащую класс, который вы хотите протестировать, если ваша цель называется MyProject, нужно будет добавить import MyProject к PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

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

Но этого недостаточно для тестирования вашего класса PrimeNumberModel, поскольку уровень контроля доступа по умолчанию Internal Access, ваш класс не будет виден для тестового пакета, поэтому вам нужно сделать его Public Access и все методы, которые вы хотите протестировать:

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}
person Diogo T    schedule 25.08.2014
comment
есть ли способ изменить контроль доступа по умолчанию? У меня был забавный случай, когда он нормально работал без общедоступного модификатора, затем я переместил тестовые примеры, он внезапно перестал работать. - person Metaphox; 23.09.2014
comment
Я думаю, что это невозможно, по крайней мере, для текущей версии swift. - person Diogo T; 24.09.2014
comment
благодаря. И я обнаружил, что моя проблема в том, что быстрый файл не создается для тестовой цели с тестовыми примерами. - person Metaphox; 25.09.2014
comment
@Metaphox, вам не следует создавать класс на тестовой цели, более подробно ознакомьтесь с постом, который я написал об этом: blog.diogot.com/blog/2014/08/23/ - person Diogo T; 26.09.2014
comment
да, именно в этом я и чувствовал себя не так - я не должен встраивать файл class swift в целевой тестовый пример. хороший пост в блоге! благодаря. - person Metaphox; 29.09.2014
comment
Если у вас есть проект, созданный с помощью Xcode 5 или более поздней версии, и вы выбираете общедоступный подход, импортируйте целевой модуль, дважды проверьте имя модуля для вашей тестовой цели, так как оно может быть таким же, как основная цель. Если вы получаете No such module <moduleName> ошибку компиляции в вашем тестовом примере, вы можете проверить PRODUCT_MODULE_NAME для тестовой цели. Отличный ответ Диого. - person Chris; 28.04.2015
comment
На всякий случай, если кто-то еще столкнется с этим, вам нужно проверить, где настройки определены в иерархии Project ›Target. Щелкните параметр «Уровни» слева от редактора целевых параметров (под вкладкой) и убедитесь, что для вашего целевого приложения задано PRODUCT_MODULE_NAME, но не целевого объекта тестирования. Возможно, вы случайно определили PRODUCT_MODULE_NAME на уровне проекта вместо целевого уровня, в результате чего обе ваши цели будут иметь одинаковое имя модуля. - person Brian Gerstle; 07.07.2015

В документации говорится, что есть нет операторов импорта в Swift.

введите описание изображения здесь

Просто используйте:

let primNumber = PrimeNumberModel()
person Nitin Gohel    schedule 04.06.2014
comment
Это сработало, но мне пришлось закрыть и снова открыть Xcode 6.0, чтобы класс наконец появился. Попробуйте также очистить и построить проект. - person user3344977; 23.09.2014
comment
Это кажется новым (или проблемой) в последней бета-версии XCode 6.3, поэтому теперь требуется оператор импорта. Также в Swift есть оператор импорта для импорта модулей. - person Augunrik; 27.03.2015
comment
Согласно предоставленной документации, эта таблица без оператора импорта относится к импорту из того же целевого случая. В случае XCTests вы используете другую (тестовую) цель, поэтому обратите внимание на раздел статьи «Импорт внешних фреймворков», там есть еще одна таблица: Любая языковая структура - ›Импорт в Swift -› Требуется импорт FrameworkName - person Igor Vasilev; 12.07.2015
comment
Если вы видите проблему в редакторе, часто бывает, что есть тестовая цель, в которую не включен класс. Таким образом, вы, вероятно, создаете свою работоспособную систему, но если у какой-либо из целей есть проблема, она все равно показывает ошибку. Если бы вы выбрали одну из этих других целей, это не позволило бы вам скомпилировать. - person Joel Teply; 30.10.2015

Проверьте целевое членство PrimeNumberModel.swift в своей тестовой цели.

person kimkkikki    schedule 09.06.2014
comment
пожалуйста, добавьте это как комментарий. - person 4dgaurav; 09.06.2014
comment
Этот человек не может, для этого ему нужно еще 9 повторений (на момент написания). - person AlbertEngelB; 29.08.2014
comment
Что за цель? - person User; 12.10.2014
comment
Спасибо, это сработало для меня. Щелкните файл класса. Проверьте первую вкладку столбца инспектора справа. Второй раздел - Целевое членство. Убедитесь, что выбрана цель / продукт, который вы пытаетесь включить в класс. - person Hairgami_Master; 27.03.2015
comment
Это не совсем ответ на вопрос, как мне импортировать ..., но он действительно ответил на вопрос, который привел меня сюда (я забыл добавить новый файл в цель). Итак, для меня и других, которые придут сюда, следуя первому результату Google для быстрого неразрешенного класса идентификаторов, этот является ответом (а не комментарием). - person noamtm; 01.06.2015
comment
Это не может решить вопрос для многих сценариев, это заставляет тестовое приложение создавать отдельный экземпляр класса, поэтому, если вы, например, тестируете службы или компоненты, которые могут быть подключены только к одному экземпляру за раз, вы приведет к конфликтам или получению неверных данных. - person gbdavid; 25.11.2015
comment
Включение файлов кода вашего приложения в тестовую цель также может вызвать всевозможные странные проблемы, когда ваша тестовая цель компилируется, как этот. Сначала я сделал это, затем понял, что лучше всего импортировать весь модуль. - person George WS; 05.01.2016

В Objective-C, если вы хотели использовать класс в другом файле, вам нужно было его импортировать:

#import "SomeClass.h"

Однако в Swift вам вообще не нужно импортировать. Просто используйте его, как если бы он уже был импортирован.

Пример

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

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

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

Как видите, импорт не потребовался. Надеюсь это поможет.

person Fomentia    schedule 18.07.2014
comment
Спасибо! Все еще обходит все эти новые вещи в Swift. - person Felipe; 25.11.2015

Согласно Apple, вам не нужен импорт быстрых файлов в одну и ту же цель. Наконец-то я заставил его работать, добавив мой быстрый файл как в мою обычную цель, так и в тестовую. Затем я использовал заголовок моста для тестирования, чтобы убедиться, что мои файлы ObjC, на которые я ссылался в своем обычном заголовке моста, были доступны. Бежал теперь как шарм.

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

}

Итак, убедитесь, что PrimeNumberModel имеет цель вашей тестовой цели. Или решение High6 для импорта всего модуля будет работать

person Alex Reynolds    schedule 04.06.2014
comment
Работает ли это только для классов логики / модели, или я могу использовать его и для делегата приложения? - person Nicolas Miari; 05.08.2015

Я смог решить эту проблему, очистив мою сборку.

Верхнее меню -> Продукт -> Очистить Или сочетание клавиш: Shift + Cmd + K

person Peter Fisher    schedule 22.01.2015

Начиная с Swift 2.0, лучшая практика:

Добавьте строку @testable import MyApp в начало файла тестов, где «MyApp» - это имя модуля продукта целевого приложения (его можно просмотреть в настройках сборки вашего целевого приложения). Вот и все.

(Обратите внимание, что имя модуля продукта будет таким же, как имя целевого объекта вашего приложения, если имя целевого приложения вашего приложения не содержит пробелов, которые будут заменены подчеркиванием. Например, если бы мое целевое приложение называлось «Веселая игра», я бы напишите @testable import Fun_Game в верхней части моих тестов.)

person George WS    schedule 05.01.2016

Проверьте свои PrimeNumberModelTests целевые настройки.

Если вы не видите PrimeNumberModel.swift файл в сборке Phases/Compile Sources, добавьте его.

person Bumseok    schedule 03.07.2014
comment
Это неправильный способ, проверьте ответ High6. - person Diogo T; 24.08.2014

Вам нужно добавить процедуру для ссылки компилятора в качестве точки входа, поэтому добавьте файл main.swift, который в этом случае просто создает экземпляр вашего тестового файла:

main.swift

PrimeNumberModelTests()

Затем скомпилируйте в командной строке (я использую El Capitan и Swift 2.2):

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

В этом случае вы получите предупреждение: результат инициализатора не используется, но программа компилируется и является исполняемой:

./PrimeNumberMain

ПРЕДОСТЕРЕЖЕНИЕ: для простоты я удалил импортные типы XCTest и XCTestCase.

person Pinecone    schedule 27.06.2016

Итак, вам нужно

  1. Импортируйте внешние модули, которые хотите использовать
  2. И убедитесь, что у вас есть правильные модификаторы доступа для класса и методов, которые вы хотите использовать.

В моем случае у меня был быстрый файл, который я хотел протестировать, и файл модульного теста также был быстрым классом. Я убедился, что модификаторы доступа верны, но утверждение

import stMobile

(предположим, что stMobile - наше целевое имя)

по-прежнему не работал (я все еще получал ошибку «Нет такого модуля»), я проверил свою цель, и ее имя действительно было stMobile. Итак, я пошел в настройки сборки, в разделе упаковки, и нашел имя модуля продукта, и по какой-то причине это называлось St_Mobile, поэтому я изменил свой оператор импорта

import St_Mobile

(это название модуля продукта), и все сработало.

Итак, подведем итоги:

  1. Проверьте имя модуля продукта и используйте приведенный ниже оператор импорта в своем классе модульного теста.

    import myProductModuleName
    
  2. Убедитесь, что ваши модификаторы доступа верны (уровень класса и ваши методы).

person Cloud9999Strife    schedule 04.10.2014

Вместо того, чтобы требовать явного импорта, компилятор Swift неявно ищет .swiftmodule файлы зависимых библиотек Swift.

Xcode может создавать для вас быстрые модули или обратиться к railsware blog, где приведены инструкции для swiftc.

person mcandre    schedule 02.12.2014

Как указали @ high6 и @ erik-p-hansen в ответе @ high6, это можно преодолеть, импортировав цель для модуля, в котором находится класс PrimeNumberModel, который, вероятно, совпадает с именем вашего проекта в простом проекте. .

Глядя на это, я наткнулся на статью Напишите свой первый модульный тест на Swift о swiftcast .tv Клейтона Макилрата. В нем обсуждаются модификаторы доступа, показан пример той же проблемы, с которой вы столкнулись (но для ViewController, а не для файла модели), и показано, как импортировать целевой объект и решить проблему модификатора доступа, включив целевой файл в целевой файл, то есть вам не нужно делать класс, который вы пытаетесь протестировать, общедоступным, если вы на самом деле этого не хотите.

person mr_sd    schedule 04.01.2015