这是一个具有iOS 8.0+目标的Swift 2.1项目。
与this question中的用户Cybermew非常相似,我有一个设置,其中A-> B-> C-> D。 A是导航控制器,其余是常规UIViewControllers。当从D展开到B时,C不会被释放。这会导致内存泄漏和其他意外的副作用。
与上面提到的问题相反,我没有任何我知道的可能会将视图保留在内存中的NSTimer。是什么导致这种情况发生?
C代码(修剪):
import UIKit
import SpriteKit
import AVFoundation
import AVFoundation.AVAudioSession
class GameViewController: UIViewController {
var scene: GameScene!
var level: Level!
@IBOutlet weak var gameOverPanel: UIImageView!
@IBOutlet weak var heroPicture: UIImageView!
@IBOutlet weak var villainPicture: UIImageView!
@IBOutlet weak var spellOneButton: UIButton!
@IBOutlet weak var doubleLife: UISwitch!
let attackSound = SKAction.playSoundFileNamed("Attack.wav", waitForCompletion: false)
var tapGestureRecognizer: UITapGestureRecognizer!
var backgroundMusic: AVAudioPlayer = {
let sess = AVAudioSession.sharedInstance()
if sess.otherAudioPlaying {
_ = try? sess.setCategory(AVAudioSessionCategoryAmbient, withOptions: [])
_ = try? sess.setActive(true, withOptions: [])
}
let url = NSBundle.mainBundle().URLForResource("BackgroundMusic", withExtension: "mp3")
let player = try? AVAudioPlayer(contentsOfURL: url!)
player!.numberOfLoops = -1
return player!
}()
override func prefersStatusBarHidden() -> Bool {
return true
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.AllButUpsideDown
}
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as! SKView
skView.multipleTouchEnabled = false
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
level = Level(filename: "Level_0")
scene.level = level
scene.addTiles()
scene.swipeHandler = handleSwipe
skView.presentScene(scene)
backgroundMusic.play()
beginGame()
}
}
从聊天移到这里:
swipeHandler
声明为:
var swipeHandler: ((Swap) -> ())?
和交换是:
struct Swap: CustomStringConvertible, Hashable {
// blabla
}
如果在GameViewController
上调用此内容,则填充交换:
func handleSwipe(swap: Swap) {
view.userInteractionEnabled = false
if level.isPossibleSwap(swap) {
level.performSwap(swap)
scene.animateSwap(swap, completion: handleMatches)
} else {
scene.animateInvalidSwap(swap) {
self.view.userInteractionEnabled = true
}
}
答案 0 :(得分:1)
您有一个引用循环导致您的viewController不被释放。我建议将swipeHandler
转换为弱委托指针,然后通过该指针调用handleSwipe
。这样,你的GameScene将不会保留任何强大的指向你的GameViewController的指针,这将允许在执行展开segue时释放它。
protocol SwipeHandler: class {
func handleSwipe(swap: Swap)
}
class GameViewController: UIViewController, SwipeHandler {
var level = Level()
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
scene = GameScene()
scene.swipeHandler = self
}
func handleSwipe(swap: Swap) {
// ...
}
}
class GameScene {
weak var swipeHandler: SwipeHandler?
// function to demonstrate call to handleSwipe
func useSwipeHandler() {
let swap = Swap()
swipeHandler?.handleSwipe(swap)
}
}