2017-02-03 10 views
1

У меня есть игра, в которой главное меню представляет сцену игры, а когда игрок проигрывает, игровая сцена представляет меню. При переходе из меню в сцену игры успешно вызывается deinit. Моя проблема заключается в том, что противоположного не происходит (при переходе с игровой сцены на сцену меню, gameScene deinit не вызывается).Сохранение проблемы цикла при переходе между сценами

Я подозреваю, что существует сильный ссылочный цикл непосредственно между новым экземпляром главного меню, который я создаю, и сценой игры, которая создает экземпляр. Материя фактов, если я изменить код моего gameScene как следующее, я получаю Deinit вызова «s, но мое приложение падает во время выполнения, пытаясь представить сцену:

class GameScene: SKScene { 
    // Some stuff 

    // Now the function which is called when I want to present back the menu scene: 
    func lose() { 
     // Some stuff 

     // Delay is a helper function 
     delay(bySeconds: 2.0, closure: { [unowned self] in 
      for child in self.children { 
       child.removeFromParent() 
      } 

      unowned let menu = MainMenu(size: CGSize(width: 1152, height: 2048)) 
      let reveal = SKTransition.fade(with: SKColor.black, duration: 1.0) 

      self.view?.presentScene(menu, transition: reveal) 
     }) 

    } 
} 

Во время выполнения я получаю следующее ошибка:

Attempted to retain deallocated object

Вот определение задержки:

public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping() -> Void) { 
    let dispatchTime = DispatchTime.now() + seconds 
    dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure) 
} 

public enum DispatchLevel { 
    case main, userInteractive, userInitiated, utility, background 
    var dispatchQueue: DispatchQueue { 
     switch self { 
     case .main:     return DispatchQueue.main 
     case .userInteractive:  return DispatchQueue.global(qos: .userInteractive) 
     case .userInitiated:  return DispatchQueue.global(qos: .userInitiated) 
     case .utility:    return DispatchQueue.global(qos: .utility) 
     case .background:   return DispatchQueue.global(qos: .background) 
     } 
    } 
} 

А вот мой класс MainMenu:

class MainMenu: SKScene { 
    let gameScene = GameScene(size: CGSize(width: 1152, height: 2048)) 
    let reveal = SKTransition.fade(with: SKColor.black, duration: 1.0) 
    // Some stuff 
    // override func didMove(to ... 

    // Now the function which is called when I want to present the game scene: 
    func presentGame() { 
     view?.presentScene(gameScene, transition: reveal) 
    } 
} 

Я пробовал разные вещи, но они не сработали (например: установка нового экземпляра меню в методе init метода gameScene).

Если удалить «бесхозного» определения меню константы в классе GameScene, переход успешно установлено, но Deinit не называется.

Любые предложения?

+0

вы пробовали «слабый я» вместо «несобственного я»? – Emptyless

+0

Да, но это тоже не работает. – gionti

ответ

0

Я, наконец, нашел то, что удерживало мою игровую сцену от деинициализации.

Это не имело никакого отношения к коду, который я предоставил с моим вопросом. Проблема заключалась в сильной «самореактивной» ссылке внутри замыкания, которая отвечала за интерпретацию входа акселерометра.

Если вы заинтересованы в дополнительной информации, смотрите здесь: Retain cycle suspected in closure