У меня странная вещь, которая меня отключает. Чувствуется, что есть простой «В Swift 2 мы всегда (или никогда) делаем это», что мне не хватает, но я не вижу его.Swift, Singletons, переменные, представляющие функции
У меня есть класс мозга, предназначен для использования в качестве одноэлементного:
class Brain: NSObject {
static var sharedInstance : Brain?
var languageLoadedAndReadyFunction = languageLoadedAndReadyImplementation
init() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "languageLoadedAndReady",
name: Notifications.LanguageLoadedAndReady,
object: nil)
}
func languageLoadedAndReadyImplementation() {
print("Got language Ready notification")
}
func languageLoadedAndReady() {
self.languageLoadedAndReadyFunction(self)()
}
class func get() -> Brain! {
return sharedInstance
}
//...
class func reset() {
sharedInstance = Brain()
}
deinit() {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
В моем модульном тесте для мозга:
func testBrainRegisterForNotificationWhenWakingUp() {
let expectation = expectationWithDescription("Function should be called when the notification is received")
var brain = Brain.get()
brain.languageLoadedAndReadyFunction = {brain ->() ->() in
{
expectation.fulfill()
Brain.reset() // <-- this sets sharedInstance to a new Brain
}
}
brain.startUp() // <-- this causes the languageLoadedAndReady event to arrive at the brain
waitForExpectationsWithTimeout(5) {
error in
if let error = error {
print("Error: \(error.localizedDescription)")
}
}
}
Пути мне нужно определить функцию, как «мозг ->() ->() «чувствует себя громоздким, но, похоже, это работает. Это позволило мне увидеть, когда поступило уведомление, поэтому я могу проверить, по результатам теста, что мы ведем себя правильно. Метод deinit() вызывается после сброса мозга, указывая на то, что старый мозг удаляется из памяти.
Сегодня я пишу новые тесты для TranslatorTests.swift:
func testTranslatorCanTranslate() {
let expectation = expectationWithDescription("Function should be called when the notification is received2")
var brain = Brain.get()
brain.languageLoadedAndReadyFunction = {brain ->() ->() in
{
expectation.fulfill()
Brain.reset()
print("first TranslatorTests")
}
}
brain.startUp() // <-- 'brain' is different here than in BrainTests.swift, causes
// the closure in BrainTests.swift to be called.
waitForExpectationsWithTimeout(5) {
error in
if let error = error {
print("Error: \(error.localizedDescription)")
}
}
translator.setActiveLanguage("en")
let resultString = translator.translate("about_title")
XCTAssertEqual(resultString, "About")
}
func testTranslatorCanTranslateSecondWord() {
let expectation = expectationWithDescription("Function should be called when the notification is received3")
let brain = Brain.get()
brain.languageLoadedAndReadyFunction = {brain ->() ->() in
{
expectation.fulfill()
Brain.reset()
print("second TranslatorTests")
}
}
brain.startUp() // <-- 'brain' is different here than in BrainTests.swift, causes
// the closure in BrainTests.swift to be called.
waitForExpectationsWithTimeout(5) {
error in
if let error = error {
print("Error: \(error.localizedDescription)")
}
}
translator.setActiveLanguage("en")
let resultString = translator.translate("actmon_ready")
XCTAssertEqual(resultString, "Ready to upload")
}
Когда я запускаю тесты, я получаю самую странную ошибку: замыкание в BrainTests.swift вызывается, когда TranslatorTests. выполняется swift. Это приводит к тому, что метод expectation.fulfill() будет вызван во второй раз, что приведет к сбою.
Кстати, внутри замыкания нет «я», но если я поднимаюсь на один уровень в стеке вызовов, «я» относится к предыдущему экземпляру мозга. Это приводит меня к убеждению, что синтаксис мозга ->() ->() является проблемой.
Это ошеломило меня. У «мозга» есть другой адрес перед каждым закрытием, что указывает на то, что это другой экземпляр. Фактически, старый мозг был деинирован этим пунктом, так как его можно было назвать?
Я бы подумал, что назначение переменной для экземпляра означает, что мы даем закрытию новую функцию для выполнения для этого экземпляра.
Может кто-нибудь объяснить это мне? Пожалуйста, используйте небольшие слова, я чувствую себя немного менее умным, чем при написании этого кода.