展开segue(D-> B)不释放C.

时间:2016-02-06 11:26:01

标签: ios swift memory segue

这是一个具有iOS 8.0+目标的Swift 2.1项目。

this question中的用户Cyber​​mew非常相似,我有一个设置,其中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 
    } 
} 

1 个答案:

答案 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)
    }
}