SKView.presentScene with transition not working if have shown another SKView
So, as spelled out in the course of my meandering question.
How to diagnose
Adding a deinit
to do logging let me zero in on the difference between the two screens - one gets cleaned up and the other doesn't.
The Cause
in viewDidLoad
the problem screen had this
// this line, in a method called from viewWillAppear. This is calling a simple drawing kit created by PaintCode
self.thicknessSwatch.drawer = { self.hasThickness ? LinePickerKit.drawEdgeThickness() : LinePickerKit.drawNoEdge() }
The fix, which is horribly obvious in retrospect:
self.thicknessSwatch.drawer = {[weak self] in (self?.hasThickness ?? false) ? LinePickerKit.drawEdgeThickness() : LinePickerKit.drawNoEdge() }
ie: my closure had a retain cycle on the UIViewController. That retained the SKView, even though it was not used, not bound to an outlet, only loaded from the xib.
The confusing behaviour was that the presence of that floating, semi-live SKView had no effect on most SpriteKit behaviour, until there was a presentScene(transition)
SKScene Present Scene Transition not Working with SpriteKit Scene in Swift
Why are you fading for 10 seconds? Seems long. Also is this the code in your GameViewController?
SKTransitions will only work when transitioning from 1 SKScene to another SKScene. Loading the first scene from your GameViewController will not use a transition since there is technically nothing to transition from.
As a side note, in swift 2 you can get rid of the extension to unarchive the SKScene. You can also just say (if you are using GameScene.sks)
if let scene = GameScene(fileNamed: "GameScene") {
...
}
Scene transition in spritekit not transitioning
The question mark comes from optional chaining because your scene
property must have been declared like this SKScene?
. This isn't a problem though, it just means that if your scene is nil, it won't get the size property.
The real problem is probably this line:
self.scene.view.presentScene(scene, transition: transition)
Reason being, your scene
probably doesn't have a view
before it's presented.
You probably wanted something like this:
(self.view as SKView).presentScene(scene, transition: transition)
You'll notice I said probably a lot. I'm only speculating on the problem because I don't see enough code, but I appreciate the effort to try and narrow down your problem. You should post more though because it may be somewhere else.
Edit
Try replacing this:
let transitionToPlayScene = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1.0)
if CGRectContainsPoint(playButton.frame, location) {
let playView = PlayScene(size: self.scene?.size)
}
With this
if CGRectContainsPoint(playButton.frame, location) {
let transitionToPlayScene = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1.0)
let nextScene = PlayScene(size: self.size)
self.view!.presentScene(nextScene, transition: transitionToPlayScene)
}
SKView presentScene fails with transition
The solution I've stumbled across (in part thanks to this question) is to override my viewcontroller's loadView()
and insert the following line
self.view = UIView(frame: UIScreen.main.bounds)
This appears to cause everything else to fall into place. The transition now works as expected and intended, and there are not -as of yet- any unintended consequences!
SKTransition not working in Swift
SOLVED.
It turns out that there is nothing wrong with the code above. The problem was that I was trying to execute it in the update function based on a specific SKPhysicsBody's position. The transition doesn't happen instantaneously so it gave time for update to get called repeatedly which re-triggered the transition over and over again. This resulted in the transition never happening.
The fix was to add a bool to check if I have started the transition, so I only attempt it once.
SpriteKit scene transition good practices
Well the thing that was causing my trouble was inserting particle emitters every half second for 5 seconds using SKAction.repeatActionForever() to call the emitter insert function.
This repeatAction apparently was not killed by transitioning to another scene, and was causing the memory for the whole scene to be retained. I switched to SKAction.repeatAction() instead and specify how many time it should fire. The scene now returns all of its memory when I transition to the new scene.
I am not sure I understand this behavior though.
Related Topics
Xcode Creates Wrong IPA Folder Structure
Swift - Add Gesture Recognizer to Object in Table Cell
Game Center Login Dialog Not Shown Again After Cancelling It for the First Time (Ios7)
How to Properly Send an Image to Cloudkit as Ckasset
Error Using Swift - Instance Member Cannot Be Used on Type 'Viewcontroller'
Swiftui Foreach Index Out of Range Error When Removing Row
iOS 11 Search Bar Jumping to Top of Screen
Custom Uisearchbar with Uisearchcontroller
Makekeywindow VS Makekeyandvisible
How to Add Firebase to Today Extension iOS
How to Get MAC Address from Cbperipheral and Cbcenter
How to Change an iOS Device Volume Programmatically
Changing Uipageviewcontroller's Page Programmatically Doesn't Update the Uipagecontrol
iOS Facebook Login "Given Url Is Not Allowed by the Application Configuration"
Instantiateviewcontrollerwithidentifier - Storyboard Id Set But Still Not Working