I explain my problem.
I just made a game with 3 views.
the game presentation with a playbutton
the game scene
the game over scene with a button to play again or go back to the presentation scene.
My problem is when there is a transition between two scenes, the active memory will be 30MB more and each scene transition will increase the active memory about 30MB and will never decrease.
How can I fix it and release memory ?
Thank you all
My transition code :
// Transition in presentationViewController file
func transition(sender:UIButton!)
{
println("transition")
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("GameViewController") as UIViewController
let window = UIApplication.sharedApplication().windows[0] as UIWindow
UIView.transitionFromView(
window.rootViewController!.view,
toView: secondViewController.view,
duration: 0.65,
options: .TransitionCrossDissolve,
completion: {
finished in window.rootViewController = secondViewController
})
}
// transition in GameScene file
func removeCountDownTimerView()
{
defaults.setInteger(balloonDestroyed, forKey: "score")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let gameOverScene: UIViewController = storyboard.instantiateViewControllerWithIdentifier("GameOverViewController") as UIViewController
let vc = self.view?.window?.rootViewController
vc?.presentViewController(gameOverScene, animated: true, completion: nil)
}
// transition in gameOverViewController file
func transition(sender:UIButton!)
{
println("play transition")
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("GameViewController") as UIViewController
let window = UIApplication.sharedApplication().windows[0] as UIWindow
UIView.transitionFromView(
window.rootViewController!.view,
toView: secondViewController.view,
duration: 0.65,
options: .TransitionCrossDissolve,
completion: {
finished in window.rootViewController = secondViewController
})
}
instantiateViewControllerWithIdentifier("GameViewController") as UIViewController
This code is creating new ViewController each time user press the button. I advise you to use singletone pattern for this.
private let _SomeManagerSharedInstance = GameViewController()
class GameOverViewController {
class var sharedInstance: GameOverViewController {
return _GameOverViewController
}
You can also create a private class method for instantiating the View Controller from storyboard.
Related
I have split my app into UIStoryboards representing the key components of that app.
I am wanting to move from Storyboard A (main) to Storyboard B.
Currently I transition from A to B like this;
let sb:UIStoryboard = UIStoryboard(name: "Second", bundle: nil)
let vc : SecondViewController = sb.instantiateInitialViewController() as! SecondViewController
// change to desired number of seconds
let when = DispatchTime.now() + 0.5
DispatchQueue.main.asyncAfter(deadline: when) {
SVProgressHUD.dismiss()
// Your code with delay
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let window:UIWindow = appDelegate.window!
UIView.transition(with: window, duration: 0.2, options: [UIViewAnimationOptions.transitionCrossDissolve], animations:{
}, completion: { (finished: Bool) -> () in
window.rootViewController = nil
window.rootViewController = vc
window.makeKeyAndVisible()
})
}
But it doesn't have the same animation as a tradition view controller push as generated from a traditional UINavigation or storyboard segue.
My question is, how can I animate it so that the storyboard I am moving to animates like a UINavigation push?
Many thanks
I want to navigate from a SKScene to a UIViewController. My code is as follows. However, when the method showViewController() is clicked the view doesn't get navigated. How can I solve this ?
I am using SWIFT3 and XCODE 8.1
class GameScene: SKScene, SKPhysicsContactDelegate {
func showViewController() {
print("button clicked")
self.view!.window!.rootViewController!.performSegue(withIdentifier: "DashboardVIewControllerSegue", sender: self)
}
}
What i have done to acheive this without having memory issue is.
first create some protocol(delegate) in the root viewController. This viewcontroller Contains the view as SKView where we load skscene.
so whenever you want to open a new viewcontroller from the skscene just call the protocol.
here is some code
In mainViewcontroller:
protocol GameProtocol {
func displayViewController()
}
.
extension MainViewController: GameProtocol {
internal func displayViewController() {
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let popoverVC = storyboard.instantiateViewController(withIdentifier: "SettingViewController") as! SettingViewController
// popoverVC.modalPresentationStyle = .fullScreen
// popoverVC.modalPresentationStyle = .popover
popoverVC.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
popoverVC.view.backgroundColor = UIColor.popBackgroundColor
popoverVC.modalPresentationStyle = .popover
popoverVC.popoverPresentationController!.delegate = self
popoverVC.popoverPresentationController!.sourceView = self.view
popoverVC.popoverPresentationController!.sourceRect = CGRect(x: 0.5, y: 0.5, width: 0, height: 0)
popoverVC.preferredContentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height)
self.present(popoverVC,animated: false,completion: nil)
}
}
I have this code in maincontroller for popup alert when needed. within in gamescene.
and in game scene
func showViewController() {
let viewe = self.view as! GameSceneView
viewe.myDelegate?. displayViewController()
}
Hope you get this.
Here is the way I navigate between different ViewControllers:
let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController3")
UIApplication.topViewController()?.present(newViewController, animated: true, completion: nil)
with the following extension:
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
And here is the way I invoke scene transitions in my SKScene (several):
let transition = SKTransition.fade(withDuration: 2)
let nextScene = NewScene(size: scene!.size)
nextScene.scaleMode = .aspectFill
scene?.view?.presentScene(nextScene, transition: transition)
Everything work fine before switching ViewControllers. Once the switching has been succeeded, I can not invoke transition anymore in my SKScene, the app get frozen without any error from Xcode (iPad connected to the Mac with live debugging)
Do you know what happens ?
I use Swift 3 and SpriteKit with ViewControllers to be able to use Vuforia static lib in a direct ViewController scene (UIView).
I have finally found the solution, it's necessary to dismiss the actual ViewController before changing with the new one:
self.dismiss(animated: false)
let newViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewController2")
UIApplication.topViewController()?.present(newViewController, animated: true, completion: nil)
If the dismiss call is not done, it's not possible to do new transition scene in the new ViewController.
I'm stuck on transitioning from an SKScene to a ViewController that I've added to the Main.storyboard. I know there are tons of the same question but nothing works for me.
I would be grateful if I get an answer, anyway.
My code to transition:
func presentNextVC() {
let vc = UIViewController(nibName: "NextVC", bundle: nil) as UIViewController
if let responder = self.view?.nextResponder() {
let vc = responder as UIViewController
vc.presentViewController(NextVC(), animated:true, completion:nil)
}
This function will be called by a TouchedNode-event. When node is touched, I think it moves to the NextVC, but I only get a black screen.
// EDIT: The solution:
func presentNextVC() {
let vc = UIStoryboard(name: "Main", bundle:nil).instantiateViewControllerWithIdentifier("NextVc") as UIViewController
let currentViewController = (UIApplication.sharedApplication().delegate as AppDelegate)
currentViewController.window?.rootViewController?.presentViewController(vc, animated: true, completion: nil)
}
I'm looking for changing my ViewController from a gameScene with SpriteKit.
I have 3 scenes with 3 different ViewControllers.
When my application starts with the PresentationViewController (see the screenshot 1) my transition code from my GameScene (GameViewController) to the GameOverViewController doesn't work and I can read an error message.
error message :
whose view is not in the window hierarchy!
My code is :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let settingController: UIViewController = storyboard.instantiateViewControllerWithIdentifier("PresentationViewController") as UIViewController
let vc = self.view?.window?.rootViewController
vc?.presentViewController(settingController, animated: true, completion: nil)
And when my app starts with the GameViewController (see the screenshot 2) the transition code works perfectly.
I don't know why is there a difference between this 2 cases.
For information the transition between PresentationViewController and GameViewController is with a UIButton with this code :
override func viewDidLoad() {
super.viewDidLoad()
var playButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
let image = UIImage(named: "playButton.png") as UIImage
playButton.frame = CGRectMake(0, 0, 100, 100)
playButton.center = CGPointMake(self.view.frame.width/2, self.view.frame.height/1.7)
playButton.addTarget(self, action: "transition:", forControlEvents: UIControlEvents.TouchUpInside)
playButton.setBackgroundImage(image, forState: UIControlState.Normal)
self.view.addSubview(playButton)
}
func transition(sender:UIButton!)
{
println("transition")
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("GameViewController") as UIViewController
secondViewController.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
self.presentViewController(secondViewController, animated: true, completion: nil)
}
Well I found by myself a way to navigate between several ViewController.
I set the secondViewController to be the rootViewController in replace this code in my PresentationViewController file func transition():
self.presentViewController(secondViewController, animated: true, completion: nil)`
by this code (with options) :
secondViewController.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
let window = UIApplication.sharedApplication().windows[0] as UIWindow
UIView.transitionFromView(
window.rootViewController!.view,
toView: secondViewController.view,
duration: 0.65,
options: .TransitionCrossDissolve,
completion: {
finished in window.rootViewController = secondViewController
})