2014-07-07 18 views
1

我一直在使用swift在sprite工具包中创建一个游戏,并且遇到了问题。我有两个视图控制器,每个都有一个场景,一个模式转换到另一个场景。这一切都完美的第一次,但是当我回到第一个视图控制器,然后再次去第二次,我使用了双倍的内存。这给我的印象是没有任何东西正在被释放,但是每次我转换到场景时都会重新分配对象。我在乐器中运行应用程序,得到了相同的结果。在下面的图像中,我从一个场景移动到下一个场景,然后又回到第一个场景,但它似乎重新分配了第一个场景,但尚未清除任何内存。由于dealloc方法现在未被使用,我不明白我能如何解决这个问题。我会将代码发布到下面的第一个视图控制器,以便您可以查看它。非常感谢。在模态转换后释放SKScene

Instument's recordings

import UIKit 
import SpriteKit 

class SelectionViewController: UIViewController { 

var selectionScene:SelectionScene? 
var currentRocketName = "" 

@IBOutlet var playButton: UIButton 

override func viewDidLoad() { 
    super.viewDidLoad() 

    if let selectionScene = SelectionScene.unarchiveFromFile("SelectionScene") as? SelectionScene { 

     // Configure the view. 
     let skView = self.view as SKView 
     skView.showsFPS = true 
     skView.showsNodeCount = true 
     skView.multipleTouchEnabled = false 

     /* Sprite Kit applies additional optimizations to improve rendering performance */ 
     skView.ignoresSiblingOrder = true 

     /* Set the scale mode to scale to fit the window */ 
     selectionScene.scaleMode = .ResizeFill 
     selectionScene.viewController = self 

     skView.presentScene(selectionScene) 

     NSNotificationCenter.defaultCenter().addObserver(selectionScene, selector: "spinnerChanged", name: "spinnerValueChanged", object: nil) 
     NSNotificationCenter.defaultCenter().addObserver(selectionScene, selector: "productBought", name: "ProductBought", object: nil); 
     NSNotificationCenter.defaultCenter().addObserver(selectionScene, selector: "manageErrorInPurchase", name: "ErrorOccured", object: nil) 

    } 
} 

override func shouldAutorotate() -> Bool { 
    return true 
} 

override func viewDidAppear(animated: Bool) { 
} 

@IBAction func playButtonPressed(sender: UIButton) { 
    self.performSegueWithIdentifier("moveToGame", sender: nil) 
} 

override func prefersStatusBarHidden() -> Bool { 
    return true 
} 

override func supportedInterfaceOrientations() -> Int { 
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone { 
     return Int(UIInterfaceOrientationMask.AllButUpsideDown.toRaw()) 
    } else { 
     return Int(UIInterfaceOrientationMask.All.toRaw()) 
    } 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Release any cached data, images, etc that aren't in use. 
} 

override func viewDidUnload() { 
    NSNotificationCenter.defaultCenter().removeObserver(selectionScene) 
} 

override func viewDidDisappear(animated: Bool) { 
    NSNotificationCenter.defaultCenter().removeObserver(selectionScene) 
} 

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { 
    if segue.identifier == "moveToGame" { 
     let destController = segue.destinationViewController as GameViewController 
     destController.rocketTexture = SKTexture(imageNamed: self.currentRocketName) 
    } 
} 

} 

两个selectionScenecurrentRocketName是,尽快为他们被加载到视图传递到ViewController

回答

4

我不熟悉,斯威夫特还,所以我给你的例子在Objective-C中。

skView创建一个IBOutlet。当你要提出另一个视图控制器,删除skView从它的上海华和无它:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    // Need to deallocate GameScene (if game is not paused) 
    [self.skView removeFromSuperview]; 
    self.skView = nil; 
    .... 
} 

不要忘记添加skView回的ViewController的看法,当越来越加载视图控制器:

if (!self.skView.window) { 
    [self.view addSubview:self.skView]; 
} 

要轻松或检查SKScene被释放没有,这方法添加到它:

- (void)dealloc { 
    NSLog(@"GAME SCENE DEALLOCATED"); 
} 
+0

非常透彻的答案,并不能与iOS8上,并迅速被使用dealloc方法外,一切看起来像它会工作完美。 –

+0

我还没有遇到Swift :) :) –

+1

@JackC你可能想用'deinit'而不是'dealloc'用Swift:https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual /Swift_Programming_Language/Deinitialization.html#//apple_ref/doc/uid/TP40014097-CH19 –

0

我也有类似我ssue。

原来,我通过将SKScene实例作为另一个类中的委托创建了一个强大的参考。声明SKScene型或UIView的类型,我的问题弱的每个属性后得到解决:

weak var skScene:SKScene!