Am having trouble moving code into a separate function - swift

From within my GameViewController's viewDidLoad() function I do two things:
1- I create a sub UIVIew, myView, which is added to the main view,
2- I call my function, addConstraints, which is in the GameViewController's code.
When I create GameScene, self.myView.frame.width & self.myView.frame.height contain the correct values, and abide by the safeAreaLayout guides.
I want to make my code clearer, so I've moved the addConstraints function to a separate file. But when I run my app that way self.myView.frame.width & self.myView.frame.height are zero.
So am curious if I am somehow translating the function incorrectly, or maybe this is something I can't move outside of the main code?
The first block is the original code, the 2nd is the function
//located with GameViewControl
private func addConstraints(){
var constraints = [NSLayoutConstraint]()
constraints.append(myView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor))
constraints.append(myView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor))
constraints.append(myView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor))
constraints.append(myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor))
NSLayoutConstraint.activate(constraints)
}
translated into a function
//called from GameViewControl
createConstraints(view: myView)
....
//located outside of GameViewControl
func createConstraints(view: UIView) {
var constraints = [NSLayoutConstraint]()
constraints.append(view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor))
constraints.append(view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor))
constraints.append(view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor))
constraints.append(view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor))
NSLayoutConstraint.activate(constraints)
}
And here is the full file of GameViewControl
import UIKit
import SpriteKit
class GameViewController: UIViewController {
private let myView : UIView = {
let myView = UIView()
setViewAttributes(view: myView)
return myView
}()
private func addConstraints(){
var constraints = [NSLayoutConstraint]()
//add
constraints.append(myView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor))
constraints.append(myView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor))
constraints.append(myView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor))
constraints.append(myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor))
//activate
NSLayoutConstraint.activate(constraints)
}
override func viewDidLoad() {
super.viewDidLoad()
#if DEBUG
print ("viewDidLoad")
#endif
if let view = self.view as! SKView? {
getScreenDimensions (screen: &screenDims)
view.addSubview(myView)
addConstraints()
var scene : GameScene!
DispatchQueue.main.async { scene = GameScene(size: CGSize(width: self.myView.frame.width, height: self.myView.frame.width))
scene.anchorPoint = CGPoint(x: 0.0, y: 0.0)
scene.backgroundColor = .clear
scene.scaleMode = .aspectFit
view.isHidden = false
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
view.showsPhysics = true
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
#if DEBUG
print ("GVC viewDidLayoutSubviews")
#endif
myGlobalVars.sceneRect = view.frame
if #available(iOS 11.0, *) {
myGlobalVars.topSafeArea = view.safeAreaInsets.top
myGlobalVars.bottomSafeArea = view.safeAreaInsets.bottom
} else {
myGlobalVars.topSafeArea = topLayoutGuide.length
myGlobalVars.bottomSafeArea = bottomLayoutGuide.length
}
}
override var shouldAutorotate: Bool {
#if DEBUG
print ("shouldAutorotate")
#endif
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
#if DEBUG
print ("supportedInterfaceOrientations")
#endif
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override var prefersStatusBarHidden: Bool {
#if DEBUG
print ("prefersStatusBarHidden")
#endif
return false
}
}
The call to function setViewAttributes does pass the view to a function, and I have verified that that function is working.
func setViewAttributes(view: UIView)
{
view.alpha = 0.0
view.frame.size.height = UIScreen.main.nativeBounds.height
view.frame.size.width = UIScreen.main.nativeBounds.width
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .clear
}

You can't just move this kind of function because the view variable inside it refers to GameViewController.view.
If you want to do a refactor like this you can move this method to an extension and call it inside your GameViewController.
public extension UIView {
func createConstraints() {
guard let superview = superview else { return }
view.translatesAutoresizingMaskIntoConstraints = false
var constraints = [NSLayoutConstraint]()
constraints.append(leadingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.leadingAnchor))
constraints.append(trailingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.trailingAnchor))
constraints.append(bottomAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.bottomAnchor))
constraints.append(topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor))
NSLayoutConstraint.activate(constraints)
}
}
And then instead of calling addConstraints() in viewDidLoad() you should call myView.createConstraints(). It should work the same as before.
You can read more about extension from Extensions — The Swift
Programming Language.
And also you should read this too Programmatically Creating
Constraints

After going through the code, over and over I realized I was calling the safeAreaLayout routine before viewDidLayoutSubviews. Now I can move my call to a function and it works. Now I'd love to know why it was working before, when I was calling it prematurely. But maybe I should be grateful that I found a substantial error.
So now my code looks the same as the code in the OP, except every call regarding screen dimensions, and safeAreaLayout, are done in the viewDidLayoutSubviews function.
And addConstraints is now an external function
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
getScreenDimensions (screen: &screenDims)
view.addSubview(myView)
addConstraints()
myGlobalVars.sceneRect = view.frame
createConstraints(view: myView)
if #available(iOS 11.0, *) {
myGlobalVars.topSafeArea = view.safeAreaInsets.top
myGlobalVars.bottomSafeArea = view.safeAreaInsets.bottom
} else {
myGlobalVars.topSafeArea = topLayoutGuide.length
myGlobalVars.bottomSafeArea = bottomLayoutGuide.length
}
}

Related

UIViewPropertyAnimator not stopping properly with pan gesture between views

I have a view controller that setups 3 children view controllers, puts the three views side by side, and centers the middle view.. like snapchat. The sliding between view controllers is controlled by using a pangesture that adjusts the left anchor constraint of the far left child view controller.
Right now... when I pan and then let go it will go to the proper constraint.
THE ISSUE: when I pan, let go, pan again the constraints snap back and the animation isn't looking proper. Any insight would be appreciated....
this link shows what I mean by the constraint and animations snapping and being funky!! (the first pan is proper, but when i try to interrupt the second pan you see my issue)
https://giphy.com/gifs/mEDld5sbR81gJBHcl1
import UIKit
class ViewController: UIViewController {
private let viewControllerOne = UIViewController()
private let viewControllerTwo = UIViewController()
private let viewControllerThree = UIViewController()
private var viewControllerOneLeftAnchorConstraint: NSLayoutConstraint?
override func loadView() {
view = UIView()
view.backgroundColor = .white
//removed code for stackoverflow readability, here i setup view controllers and pangestures
guard let viewControllerOneLeftAnchorConstraint = viewControllerOneLeftAnchorConstraint else { return }
NSLayoutConstraint.activate([
viewControllerOne.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerTwo.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerThree.view.topAnchor.constraint(equalTo: view.topAnchor),
viewControllerOne.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerTwo.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerThree.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
viewControllerOne.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerTwo.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerThree.view.widthAnchor.constraint(equalTo: view.widthAnchor),
viewControllerOneLeftAnchorConstraint,
viewControllerTwo.view.leftAnchor.constraint(equalTo: viewControllerOne.view.rightAnchor),
viewControllerThree.view.leftAnchor.constraint(equalTo: viewControllerTwo.view.rightAnchor),
])
}
private var animator: UIViewPropertyAnimator?
private var previous: CGPoint?
private var current: CGPoint?
#objc private func handlePan(gesture: UIPanGestureRecognizer) {
guard let viewControllerOneLeftAnchorConstraint = viewControllerOneLeftAnchorConstraint else { return }
if gesture.state == .began {
previous = gesture.location(in: view)
animator?.stopAnimation(true)
} else if gesture.state == .changed {
let current = gesture.location(in: view)
guard let previous = previous else { return }
let xPositionDifference = current.x - previous.x
if viewControllerOneLeftAnchorConstraint.constant + xPositionDifference < 0 && viewControllerOneLeftAnchorConstraint.constant + xPositionDifference > -(UIScreen.main.bounds.width * 2) {
self.viewControllerOneLeftAnchorConstraint?.constant += xPositionDifference
self.previous = current
}
} else if gesture.state == .ended {
viewControllerOneLeftAnchorConstraint.constant = calculateLeftAnchorConstant(viewControllerOneLeftAnchorConstraint: viewControllerOneLeftAnchorConstraint)
animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut) {
self.view.layoutIfNeeded()
}
animator?.startAnimation()
}
}
func calculateLeftAnchorConstant(viewControllerOneLeftAnchorConstraint: NSLayoutConstraint) -> CGFloat {
if viewControllerOneLeftAnchorConstraint.constant <= 0
&& viewControllerOneLeftAnchorConstraint.constant > -(UIScreen.main.bounds.width/2.0) {
return 0.0
} else if viewControllerOneLeftAnchorConstraint.constant > -(UIScreen.main.bounds.width/2.0 * 3)
&& viewControllerOneLeftAnchorConstraint.constant < -(UIScreen.main.bounds.width/2.0) {
return -(UIScreen.main.bounds.width)
} else {
return -(UIScreen.main.bounds.width * 2)
}
}
}
I'd advise you to abandon the entirety of your code. Your words and your animated gif are describing a UIPageViewController, so why not use a UIPageViewController?

I am trying to get an UIActivityIndicatorView to show when I am loading a UITableView

This problem has been answered several times before on this site, I have tried them all and none work. The difference I think is that I have a UITableView inside my UIViewController. I have tried when loading the data within viewDidLoad, here the screen I am coming from show until all is complete and my new view appears. I have also tried within viewDidAppear, here I have a blank table showing before the final view comes up.
I have tried 4 methods all from this site, I call pauseApp(n) before I start the load and restartApp(n) when completed
var spinner:UIActivityIndicatorView = UIActivityIndicatorView()
var loadingView = UIView()
var loadingLabel = UILabel()
var indicator = UIActivityIndicatorView()
#IBOutlet weak var tvTable: UITableView!
func pauseApp() {
tvTable.activityIndicatorView.startAnimating()
tvTable.activityIndicatorView.bringSubviewToFront(aIV)
UIApplication.shared.beginIgnoringInteractionEvents()
}
func pauseApp1() {
spinner = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
spinner.center = self.navBar.center
spinner.hidesWhenStopped = true
spinner.style = UIActivityIndicatorView.Style.gray
self.navigationController?.view.addSubview(spinner)
spinner.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
}
func pauseApp2() {
tvTable.activityIndicatorView.startAnimating()
indicator.startAnimating()
indicator.backgroundColor = UIColor.white
UIApplication.shared.beginIgnoringInteractionEvents()
}
func pauseApp3() {
setLoadingScreen()
UIApplication.shared.beginIgnoringInteractionEvents()
}
func restartApp() {
// sleep(2)
tvTable.activityIndicatorView.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
}
func restartApp1() {
spinner.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
}
func restartApp2() {
// sleep(2)
indicator.stopAnimating()
indicator.hidesWhenStopped = true
UIApplication.shared.endIgnoringInteractionEvents()
}
func restartApp3() {
// sleep(2)
removeLoadingScreen()
UIApplication.shared.endIgnoringInteractionEvents()
}
private func setLoadingScreen() {
let width: CGFloat = 120
let height: CGFloat = 30
let x = (view.frame.width / 2) - (width / 2)
let y = (view.frame.height / 2) - (height / 2) - 20
loadingView.frame = CGRect(x: x, y: y, width: width, height: height)
// Sets loading text
loadingLabel.textColor = .gray
loadingLabel.textAlignment = .center
loadingLabel.text = "Loading..."
loadingLabel.frame = CGRect(x: 0, y: 0, width: 140, height: 30)
// Sets spinner
spinner.style = .gray
spinner.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
spinner.startAnimating()
// Adds text and spinner to the view
loadingView.addSubview(spinner)
loadingView.addSubview(loadingLabel)
view.addSubview(loadingView)
view.bringSubviewToFront(loadingView)
}
private func removeLoadingScreen() {
spinner.stopAnimating()
spinner.isHidden = true
loadingLabel.isHidden = true
}
func activityIndicator() {
indicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
indicator.style = UIActivityIndicatorView.Style.gray
indicator.center = self.view.center
self.view.addSubview(indicator)
}
fileprivate var ActivityIndicatorViewAssociativeKey = "ActivityIndicatorViewAssociativeKey"
public var aIV: UIActivityIndicatorView = UIActivityIndicatorView()
public extension UITableView {
var activityIndicatorView: UIActivityIndicatorView {
get {
if let aIV = getAssociatedObject(&ActivityIndicatorViewAssociativeKey) as? UIActivityIndicatorView {
return aIV
} else {
let aIV = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
aIV.style = .gray
aIV.color = .gray
aIV.backgroundColor = UIColor.black
aIV.center = center
aIV.hidesWhenStopped = true
addSubview(aIV)
setAssociatedObject(aIV, associativeKey: &ActivityIndicatorViewAssociativeKey, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
aIV.bringSubviewToFront(aIV)
return aIV
}
}
set {
addSubview(newValue)
setAssociatedObject(newValue, associativeKey:&ActivityIndicatorViewAssociativeKey, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
public extension NSObject {
func setAssociatedObject(_ value: AnyObject?, associativeKey: UnsafeRawPointer, policy: objc_AssociationPolicy) {
if let valueAsAnyObject = value {
objc_setAssociatedObject(self, associativeKey, valueAsAnyObject, policy)
}
}
func getAssociatedObject(_ associativeKey: UnsafeRawPointer) -> Any? {
guard let valueAsType = objc_getAssociatedObject(self, associativeKey) else {
return nil
}
return valueAsType
}
}
Verify your Interface Builder file, specifically the order in which the components are defined. Components higher up in the hierarchy may be hidden by those defined below them. Thus it's quite possible that your tableview hides your activity view.
You should be able to confirm this fairly quickly by hiding the table view and other other views that may be on top. Depending on your activity view settings, you may also need to do tvTable.activityIndicatorView.isHidden = false. Note that since UITableView implement a built-in scrollview, adding an activity view as a child to a UITableView may not be the the best course. You are better off defining it as a child of the tableView's superview; ref:
Your attempt with pauseApp1 could work with minor modifications, but only if your view controller is hosted inside a navigation controller. You should also always define any relationship only AFTER the view is added as a subview not before.
Starting a brand new project from scratch, here's how you can display an activity indicator by code:
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// We add some delay for fun, absolutely not required!
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.showSpinner()
}
}
private func showSpinner() {
let spinner = UIActivityIndicatorView.init(style: .gray)
self.view.addSubview(spinner)
spinner.center = self.view.center
spinner.startAnimating()
spinner.isHidden = false
spinner.hidesWhenStopped = true
}
}
Thanks Again,
The solution is to add an activityIndeicatorView with Storyboard below our TableView
Then in viewDidAppear have
#IBOutlet weak var mySpinner: UIActivityIndicatorView!
override func viewDidAppear(_ animated: Bool) {
self.pauseApp()
DispatchQueue.main.asyncAfter(deadline: .now()) {
self.doScreen()
}
}
func pauseApp() {
showSpinner()
UIApplication.shared.beginIgnoringInteractionEvents()
}
func restartApp() {
mySpinner.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
}
private func showSpinner() {
mySpinner.startAnimating()
mySpinner.isHidden = false
mySpinner.hidesWhenStopped = true
}
The pauseApp call put the spinner on the screen, the doScreen does all the work and calls restartApp when it has finished. My doScreen does quite a lot of work going to a service to get the data, it takes about 2 seconds with a good internet connection, but much longer when the connection is poor.

ARSCNView not displaying object when embedded in navigation controller

I am trying to display a 3D model when a picture is tapped (See here). The picture gets tapped, it segues to 3DFloorPlanViewController (which is embedded in a navigation controller), the camera works but there is no 3D object displayed (See here).
I've tried this exact same code without a navigation controller and it works perfectly so I'm confused as to why it's not working when embedded in a navigation controller.
Storyboard picture
My 3D objects are located in a folder called "3D Objects" (See here). I've tried both named: "3D Objects/paperPlane.scn" and named: "paperPlane.scn" in the addPaperPlane function and neither worked.
Here's the code to 3DFloorPlanViewController:
import UIKit
import ARKit
import SceneKit
class _DFloorPlanViewController: UIViewController, ARSCNViewDelegate {
#IBOutlet weak var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
addPaperPlane()
//addCar()
configureLighting()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause()
}
func addPaperPlane(x: Float = 0, y: Float = 0, z: Float = -0.5) {
guard let paperPlaneScene = SCNScene(named: "3D Objects/paperPlane.scn"), let paperPlaneNode = paperPlaneScene.rootNode.childNode(withName: "paperPlane", recursively: true) else { return }
paperPlaneNode.position = SCNVector3(x, y, z)
sceneView.scene.rootNode.addChildNode(paperPlaneNode)
}
func addCar(x: Float = 0, y: Float = 0, z: Float = -0.5) {
guard let carScene = SCNScene(named: "car.dae") else { return }
let carNode = SCNNode()
let carSceneChildNodes = carScene.rootNode.childNodes
for childNode in carSceneChildNodes {
carNode.addChildNode(childNode)
}
carNode.position = SCNVector3(x, y, z)
carNode.scale = SCNVector3(0.5, 0.5, 0.5)
sceneView.scene.rootNode.addChildNode(carNode)
}
func configureLighting() {
sceneView.autoenablesDefaultLighting = true
sceneView.automaticallyUpdatesLighting = true
}
}
At the moment there is no scene set to your scene view
let scene = SCNScene()
self.sceneView.scene = scene
in general try this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Set the view's delegate
self.sceneView.delegate = self
self.sceneView.showsStatistics = true
self.sceneView.autoenablesDefaultLighting = true
let scene = SCNScene()
self.sceneView.scene = scene
}

SpriteKit make images fit screen, not stretch past

I'm working on a project, and SKNodes aren't resizing dynamically based on device size.
Example:
I'd like what happens on the first image to happen in the second.
Is there anything to make this happen automatically?
Current sizing for image shown:
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
background.size = CGSize(width: background.size.width / 5.5, height: background.size.height / 5.5)
GameViewController:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false
let scene = GameScene(size: skView.bounds.size)
scene.controller = self
scene.size = skView.bounds.size
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
If you want your whole scene to resize when the game is presented on device with a larger screen you just need to open GameViewController.swift and make sure you are using AspectFill
scene.scaleMode = .AspectFill

How to switch between scenes in Sprite Kit?

What's wrong with my code? Every time I hit the button I'm getting a default grey screen. Button for transition:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.pause {
var pauseScene = PauseScene(size: self.size)
scene?.paused = true
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
pauseScene.scaleMode = .AspectFill
pauseScene.size = skView.bounds.size
skView.presentScene(pauseScene)
}
}
}
What I have in that scene that don't want to load:
class PauseScene: SKScene {
let pauseBackground = SKSpriteNode (imageNamed: "pauseBackground")
override func didMoveToView(view: SKView) {
self.pauseBackground.anchorPoint = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.pauseBackground.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.addChild(pauseBackground)
}
}
Did I miss something?
It looks like your issue is in didMoveToView: in your PauseScene. You don't want to change your anchor point for self.pauseBackground Normally anchor point is based on 0 to 1. (.5,.5) being the center of the sprite. You are setting it to something much higher than that and if you are setting the position to half the width and hight of the scene I don't see why you would want to change the anchor point at all. Looks like just deleting the line of code should fix the issue.
class PauseScene: SKScene {
let pauseBackground = SKSpriteNode (imageNamed: "pauseBackground")
override func didMoveToView(view: SKView) {
self.pauseBackground.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.addChild(pauseBackground)
}
}
Also I see you are changing the size of your scene after you init it. I would just init it with the size you want.
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.pause {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
var pauseScene = PauseScene(size: skView.bounds.size)
scene?.paused = true
pauseScene.scaleMode = .AspectFill
skView.presentScene(pauseScene)
}
}
}
Hopefully that helps and makes sense.
Here is an updated answer swift 5, iOS 14 Using swiftUI
import SwiftUI
import SpriteKit
struct ContentView: View {
#State var switcher = false
var scene: SKScene {
let scene = GameScene.shared
scene.size = CGSize(width: 256, height: 256)
scene.scaleMode = .fill
scene.backgroundColor = .red
scene.name = "red"
return scene
}
var scene2: SKScene {
let scene2 = GameScene2.shared
scene2.size = CGSize(width: 256, height: 256)
scene2.scaleMode = .fill
scene2.backgroundColor = .blue
scene2.name = "blue"
return scene2
}
var body: some View {
if switcher {
SpriteView(scene: scene)
.frame(width: 256, height: 256)
.ignoresSafeArea()
.background(Color.red)
.onAppear {
scene2.isPaused = true
}
.onDisappear {
scene2.isPaused = false
}
} else {
SpriteView(scene: scene2)
.frame(width: 256, height: 256)
.ignoresSafeArea()
.background(Color.blue)
.onAppear {
scene.isPaused = true
}
.onDisappear {
scene.isPaused = false
}
}
Button {
withAnimation(.easeInOut(duration: 1.0)) {
switcher.toggle()
}
} label: {
Text("switch")
}
}
}
class GameScene: SKScene {
static var shared = GameScene()
override func update(_ currentTime: TimeInterval) {
// Tells your app to perform any app-specific logic to update your scene.
print("name ",scene!.name)
}
}