Post

Replies

Boosts

Views

Activity

Which is the most efficient way to move a ball?
I'm currently have an app with 6 balls. I use. the following method to move a Ball. Once it's touched I set its .isMoving property to true, and save the node that was touched into a global variable. Of course the moment I get a touchesEnded or touchesCanceled, the first thing I do is set the moving property to false, clear the global variable and call a function that animates the ball back to its starting my point. While this all works, I'm too new to Swift to know if this method has any flaws, or is not the proper/efficient way to do this. If it makes any difference am catching all touches, and movements in the GameScene. override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){ &#9;&#9;guard let touch = touches.first else { return } &#9;&#9;let location = touch.location(in: self) &#9;&#9;let touchedNodes = self.nodes(at: location) &#9;&#9;for node in&#9;touchedNodes{ &#9;&#9;&#9;&#9;if let theNode = node as? SKSpriteNode { &#9;&#9;&#9;&#9;&#9;&#9;if theNode.name == "ball" { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;theNode.zPosition += 1 &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;node.isMoving = true &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){ &#9;&#9;guard touches.first != nil else { return } &#9;&#9; if let touch = touches.first, let node = myGlobalVars.currentBall, node.isMoving == true{ &#9;&#9;&#9;&#9;&#9;let touchLocation = touch.location(in: self) &#9;&#9;&#9;&#9;&#9;node.position = touchLocation &#9;&#9;&#9;&#9;&#9;//redraw node to emulate motion &#9;&#9;&#9;&#9;} &#9;&#9;}
0
0
338
Nov ’20
I have a problem moving an SKSpriteNode, it seems pixel vs. points related
I am trying to place a border on top of a white block. When I set the border's Y positioning only based on the height of the block, I get what I expected: The border is half into the block. Screenshot, top half The next logical step: I adjust the border's Y position to include half of its own height. What I expect is the bar resting on top of the block. But for some reason, the border is way above the block. Screenshot, bottom half Am I somehow confusing pixels for points? When I do take the border's height into account, I use this line: self.position = CGPoint(x: myGV.safeSceneRect.width/2, y: myGV.gemBaseSize.height + (self.size.height/2)) Below in order: My code for the border, Print out of sizes and positions a link to the two screen shots import Foundation import SpriteKit class MyBorder : SKSpriteNode{ &#9;&#9;var nodeType = NodeType.border &#9;&#9;init(){ &#9;&#9;&#9;&#9; //create SKSpriteNode, size it based on screen size &#9;&#9;&#9;&#9;super.init(texture: SKTexture(imageNamed: "border"), color: .clear, size: CGSize(width: myGV.safeSceneRect.width, height: myGV.safeSceneRect.height * 0.07)) &#9;&#9;&#9;&#9;self.anchorPoint = CGPoint(x: 0.5, y: 0.5) &#9;&#9;&#9;&#9;self.isHidden = true &#9;&#9;&#9;&#9;self.isUserInteractionEnabled = false &#9;&#9;&#9;&#9;self.zPosition = theZ.border &#9;&#9;&#9;&#9;self.alpha = 0.5 &#9;&#9;&#9;&#9;// position border on top of block &#9;&#9;&#9;&#9;self.position = CGPoint(x: myGV.safeSceneRect.width/2, y: myGV.blockBaseSize.height) &#9;&#9;&#9;&#9;print("Screen Size \(myGV.safeSceneRect)") &#9;&#9;&#9;&#9;print(“Block Size \(myGV.blockBaseSize)") &#9;&#9;&#9;&#9;print("Border Size \(self.size)") &#9;&#9;&#9;&#9;print("Border Pos \(self.position)") &#9;&#9;&#9;&#9;myGV.gameScene!.addChild(self) &#9;&#9;&#9;&#9;self.isHidden = false &#9;&#9;} &#9;&#9;required init?(coder aDecoder: NSCoder) { &#9;&#9;&#9;&#9;fatalError("init(coder:) has not been implemented") &#9;&#9;} } Here is the output for both runs, same order as the image > Screen Size (0.0, 44.0, 375.0, 734.0) Block Size (300.0, 146.8) Border Size (375.0, 51.380001068115234) Border Pos (187.5, 146.8000030517578) Screen Size (0.0, 44.0, 375.0, 734.0) Block Size (300.0, 146.8) Block Size (375.0, 51.380001068115234) Border Pos (187.5, 172.49000549316406) www .warptv.com/links/screens.png
1
0
249
Nov ’20
How can I pass a function a parameter
Rather than do this: let skTexture = SKTexture(imageNamed: "slot") let mySlot = SKSpriteNode(texture: skTexture, color: .clear, size: slotSize) I would like to grab the texture in the call to create the SKSprite. I know I'm supposed to use closures, yet I am unable to figure out the proper syntax. Am looking for something like: let mSlot = SKSpriteNode( {texture: SKTexture(imageNamed: "slot") -> (SKTexture)} color: SKColor.clear, size: mySlotSize) Have tried as many variants as I can think of but never get to the point where I can compile. If the closure is something that I must predefine, then there's no point in trying this.
2
0
228
Nov ’20
Why would two SKSprite objects that interact even though they don't touch?
My entire project is here www. warptv.com/DropSlot.zip It's very sloppy and kludgy because I made it while I started to learn Swift. In the code I make a pegHolder positioned at 10, 10 The pegHolder contains 6 slots, and each slot holds a different color ball The pegHolder is a child of GameScene The slots are children of the pegHolder and each ball is a child of itsslot Then I create a barrier on the left side of the screen that runs up and down on an X axis of 5 (although in the end I want it at -1. For some reason at setup, the red ball is thrown on the other side of the barrier. I can grab it and pull it back, but it shouldn't start being thrown off the screen. Oddly enough I never register a collision, so it must be something else throwing the ball over. When I tried it with the barrier at the bottom of the screen, the same thing happened. Any thoughts would be appreciated.
1
0
842
Nov ’20
I have somehow lost the ability to receive touch notifications
Two days ago I was able to receive touchesBegan (moved, canceled) and now I've lost them. So I shortened the code below, created an SKSpriteNode called redSprite within GameScene...and still I don't receive touches. While I know my redSprite doesn't fulfill all the if's in the touch functions, I'm placing a breakpoint at the start of the touch functions, and it still won't stop at the breakpoint. However...if I set GameScene's isUserInteractionEnabled to true, then I do get the touches and the debugger breaks. import UIKit import SpriteKit var redSprite : SKSpriteNode? class GameScene: SKScene, SKPhysicsContactDelegate { &#9;&#9;override func sceneDidLoad(){ &#9;&#9;&#9;&#9;super.sceneDidLoad() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GC sceneDidLoad") &#9;&#9;&#9;&#9;#endif &#9;&#9;} &#9;&#9; &#9;&#9;override func didMove(to view: SKView){ &#9;&#9;&#9;&#9;super.didMove(to: view) &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GC didMove START") &#9;&#9;&#9;&#9;#endif &#9;&#9;&#9;&#9;self.isHidden = true &#9;&#9;&#9;&#9;self.backgroundColor = mySafeColor &#9;&#9;&#9;&#9;myGlobalVars.backGround = SKSpriteNode(imageNamed: "background") &#9;&#9;&#9;&#9;myGlobalVars.backGround!.zPosition = theZ.backGround &#9;&#9;&#9;&#9;myGlobalVars.safeSceneRect = view.frame &#9;&#9;&#9;&#9;myGlobalVars.gameScene = self &#9;&#9;&#9;&#9;self.isHidden = false &#9;&#9;&#9;&#9;self.isUserInteractionEnabled = false &#9;&#9;&#9;&#9;self.addChild(myGlobalVars.backGround!) &#9;&#9;&#9;&#9;physicsWorld.contactDelegate = self &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;redSprite = SKSpriteNode(color: .red, size: CGSize(width: 100, height: 100)) &#9;&#9;&#9;&#9;redSprite?.anchorPoint = CGPoint(x: 0.5, y:0.5) &#9;&#9;&#9;&#9;redSprite?.isHidden = false &#9;&#9;&#9;&#9;redSprite?.isUserInteractionEnabled = true &#9;&#9;&#9;&#9;redSprite?.color = .orange &#9;&#9;&#9;&#9; redSprite!.name = "test" &#9;&#9;&#9;&#9; redSprite?.zPosition = 10 &#9;&#9;&#9;&#9;redSprite?.position = CGPoint(x: (myGlobalVars.safeSceneRect.width/2)-(50), y: myGlobalVars.safeSceneRect.height/2 - 50) &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;redSprite?.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 100, height: 100), center: CGPoint(x: 0.5, y: 0.5)) &#9;&#9;&#9;&#9; redSprite?.physicsBody!.affectedByGravity = false &#9;&#9;&#9;&#9; redSprite?.physicsBody!.restitution = 0.2 &#9;&#9;&#9;&#9; redSprite?.physicsBody?.categoryBitMask&#9;&#9;= bodyMasks.blankMask.rawValue &#9;&#9;&#9;&#9; redSprite?.physicsBody?.contactTestBitMask = bodyMasks.blankMask.rawValue &#9;&#9;&#9;&#9; redSprite?.physicsBody?.collisionBitMask&#9; = bodyMasks.blankMask.rawValue &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9; self.addChild(redSprite!) &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;gameTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(runTimedCode), userInfo: nil, repeats: true) &#9;&#9;&#9;&#9;gameTimer?.tolerance = 0.2 &#9;&#9;&#9;&#9;RunLoop.current.add(gameTimer!, forMode: .common) &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GC didMove END") &#9;&#9;&#9;&#9;#endif &#9;&#9;} &#9;&#9;override func touchesBegan(_ touches: Set<UITouch>, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; with event: UIEvent?){ &#9;&#9;&#9;&#9;guard let touch = touches.first else { return } &#9;&#9;&#9;&#9;let location = touch.location(in: self) &#9;&#9;&#9;&#9;let touchedNodes = self.nodes(at: location) &#9;&#9;&#9;&#9;for node in&#9;touchedNodes{ &#9;&#9;&#9;&#9;&#9;&#9;if let theNode = node as? MyGem { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;if theNode.nodeType == NodeType.gem, theNode.isMoving == false { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;theNode.isMoving = true &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;theNode.zPosition += 1 &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.currentGem = theNode &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){ &#9;&#9;&#9;&#9;guard touches.first != nil else { return } &#9;&#9;&#9;&#9;if let touch = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true { &#9;&#9;&#9;&#9;&#9;&#9;let touchLocation = touch.location(in: self) &#9;&#9;&#9;&#9;&#9;&#9;node.position = touchLocation &#9;&#9;&#9;&#9;&#9;&#9;node.isMoving = true &#9;&#9;&#9;&#9;&#9;&#9;node.inSlot = false &#9;&#9;&#9;&#9;&#9;&#9;//addTrailToTwinkle(theNode: node) &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9; &#9;&#9;override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { &#9;&#9;&#9;&#9; guard touches.first != nil else { return } &#9;&#9;&#9;&#9;if let _ = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true { &#9;&#9;&#9;&#9;&#9;&#9;returnHome(moveThis : node, origNP: node.origPoint) &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9; &#9;&#9;override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { &#9;&#9;&#9;&#9;&#9;&#9;guard touches.first != nil else { return } &#9;&#9;&#9;&#9;&#9;&#9;if let _ = touches.first, let node = myGlobalVars.currentGem, node.isMoving == true { &#9;&#9;&#9;&#9;&#9;&#9;returnHome(moveThis : node, origNP: node.origPoint) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9; &#9;&#9;@objc func runTimedCode() { &#9;&#9;&#9;timeLeft -= 1 &#9;&#9;} }
21
0
1.5k
Nov ’20
Need clarity on lifecycles for UIViewController and SKScene
Below is my abbreviated code, the full code does work. It starts at GameViewController, create GameScene, and GameScene creates an SKSpriteNode. What's confusing me is the debug output which just tracks where I am in my app (shown in the abbreviated code). The debug output is at the very bottom of this post. I wonder about the order of execution, the last debug msg is the end of GameViewController...I would have thought I'd be done with that already. i.e. How do I know that everything I'm setting in GVC is setup before it's needed in GC? On a side note, I've tried Googling "SKScene lifecycle" and can't seem to find the proper documentation. GameViewController class GameViewController: UIViewController { &#9;&#9;override func viewDidLoad() { &#9;&#9;&#9;&#9;super.viewDidLoad() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewDidLoad") &#9;&#9;&#9;&#9;#endif &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;... create myView (as an SKView) &#9;&#9;&#9;&#9;... add it as a subview of GameViewController &#9;&#9;&#9;&#9;... use myView to get constraints ... and set other properties &#9;&#9;&#9;&#9;myView.isHidden&#9;&#9;&#9;&#9;&#9;&#9; = false &#9;&#9;&#9;&#9;myView.ignoresSiblingOrder&#9;&#9;= true &#9;&#9;&#9;&#9;myView.showsFPS&#9;&#9;&#9;&#9;&#9;&#9;&#9; = true &#9;&#9;&#9;&#9;myView.showsNodeCount&#9;&#9;&#9;&#9; = true &#9;&#9;&#9;&#9;myView.showsPhysics&#9;&#9;&#9;&#9;&#9; = true &#9;&#9;} &#9;&#9;override func viewWillLayoutSubviews() { &#9;&#9;&#9;&#9;super.viewWillLayoutSubviews() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewWillLayoutSubviews") &#9;&#9;&#9;&#9;#endif &#9;&#9;} &#9;&#9; func viewDidAppear() { &#9;&#9;&#9;&#9;super.viewDidAppear(true) &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewDidAppear") &#9;&#9;&#9;&#9;#endif &#9;&#9;} &#9;&#9;override func viewDidLayoutSubviews() { &#9;&#9;&#9;&#9;super.viewDidLayoutSubviews() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewDidLayoutSubviews START") &#9;&#9;&#9;&#9;#endif &#9;&#9;&#9;&#9;... get the view.frame &#9;&#9;&#9;&#9;... record some properties in my global variables&#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9; ... launch GameScene here &#9;&#9;&#9;&#9;if myGlobalVars.gameScene == nil { &#9;&#9;&#9;&#9;&#9;&#9;let scene = GameScene(size: myView.frame.size ) &#9;&#9;&#9;&#9;&#9;&#9;scene.anchorPoint = CGPoint(x: 0.0, y: 0.0) &#9;&#9;&#9;&#9;&#9;&#9;scene.backgroundColor&#9; = .clear &#9;&#9;&#9;&#9;&#9;&#9;scene.scaleMode&#9;&#9;&#9;&#9; = .aspectFit &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.gameScene = scene &#9;&#9;&#9;&#9;&#9;&#9;myView.presentScene(scene) &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewDidLayoutSubviews END") &#9;&#9;&#9;&#9;#endif&#9;&#9;&#9;&#9; &#9;&#9;} &#9;&#9; &#9;&#9;override var shouldAutorotate: Bool { &#9;&#9;&#9;&#9;return false &#9;&#9;} &#9;&#9;override var supportedInterfaceOrientations: UIInterfaceOrientationMask { &#9;&#9;&#9;&#9;if UIDevice.current.userInterfaceIdiom == .phone { &#9;&#9;&#9;&#9;&#9;&#9;return .portraitUpsideDown &#9;&#9;&#9;&#9;} else { &#9;&#9;&#9;&#9;&#9;&#9;return .all &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;override var prefersStatusBarHidden: Bool { &#9;&#9;&#9;&#9;return false &#9;&#9;} } GameScene class GameScene: SKScene, SKPhysicsContactDelegate { &#9;&#9;override func sceneDidLoad(){ &#9;&#9;&#9;&#9;super.sceneDidLoad() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GC sceneDidLoad") &#9;&#9;&#9;&#9;#endif &#9;&#9;} &#9;&#9; &#9;&#9;override func didMove(to view: SKView){ &#9;&#9;&#9;&#9;super.didMove(to: view) &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GC didMove START") &#9;&#9;&#9;&#9;#endif &#9;&#9;&#9;&#9;... load background image &#9;&#9;&#9;&#9;physicsWorld.contactDelegate = self &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;... create just one SKSpriteNode &#9;&#9;&#9;&#9;createGems(myGemRef: &myGems) &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GC didMove END") &#9;&#9;&#9;&#9;#endif &#9;&#9;} } GVC viewDidLoad GVC viewWillLayoutSubviews GVC viewDidLayoutSubviews START GC sceneDidLoad GC didMove START SKNode create SKSPriteNode start SKNode create SKSPriteNode end GC didMove END GVC viewDidLayoutSubviews END
5
0
745
Nov ’20
Having problems subclassing an CGpath as an SKShape
I am trying to create four walls, that would surround the screen. From GameScene I call let leftWall  = MyEdge(side: Walls.left) The code below works. But then I cannot add it as a child to GameScene, also I would like to give it an SKPhysicsBody. My problem is figuring out the super.init. I've tried super.init(texture: nil, color: .clear, size: CGPath(w: 0, h: 0)) super.init() But I always get Type of expression is ambiguous without more context class MyEdge { &#9;&#9;let yourline = SKShapeNode() &#9;&#9;let pathToDraw = CGMutablePath() &#9;&#9;var color : SKColor &#9;&#9;var startAt : CGPoint &#9;&#9;var endAt : CGPoint &#9;&#9;var colMask : UInt32 &#9;&#9;var conMask : UInt32 &#9;&#9;var catMask : UInt32 &#9;&#9;var name : String &#9;&#9;init(side: Walls){ &#9;&#9;&#9;&#9;let whichWall = side &#9;&#9;&#9;&#9;switch whichWall &#9;&#9;&#9;&#9;{ &#9;&#9;&#9;&#9;&#9;&#9;case .left: myGlobalVars.backGround!.size.height+1) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;startAt = CGPoint(x: 5, y: 5) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;endAt = CGPoint(x: 5, y: myGlobalVars.safeSceneRect.size.height-5) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;color = .white &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;colMask = bodyMasks.gemMask.rawValue &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;conMask = bodyMasks.blankMask.rawValue &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;catMask = bodyMasks.edgeMask.rawValue &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;name = "left" &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;pathToDraw.move(to: startAt) &#9;&#9;&#9;&#9;pathToDraw.addLine(to: endAt) &#9;&#9;&#9;&#9;yourline.lineWidth = 2 &#9;&#9;&#9;&#9;yourline.path = pathToDraw &#9;&#9;&#9;&#9;yourline.strokeColor = color &#9;&#9;} }
5
0
396
Nov ’20
Problems with Xcode and the App Store update
Am currently using Xcode Version 12.1 (12A7403) About a week ago the App Store tried to update Xcode but went nowhere for hours. The update is dated 10/25 So from a linkI was able to downloaded Xcode 12.1.1 dated 10/30 from https://developer.apple.com/download/more/ According to the Apple website, the download is Xcode 12.1.1 dated 10/30 Now sure which to do, or if there's a way I can backup my current Xcode and it's settings just in case something goes wrong. Has anyone experienced this as well?
1
0
298
Nov ’20
Can I set the color of the safe areas programmatically?
In GameViewController I do set the safeAreaLayouts. My only problem is that the top and bottom safe areas (iPhone X) are white. Now I can change them via Main.storyboard. However, am working (or learning) my way to create apps without any storyboards. Besides, perhaps I may to vary the background colors of the safeAreas. So was looking for a way to do it with coding. Since I am hear, is there a way to also change the color of the text in the status bar as well? Am pasting the complete code for GVC, just in case that has something to do with my question. import UIKit import SpriteKit class GameViewController: UIViewController { &#9;&#9; &#9;&#9;public let myView : SKView = { &#9;&#9;&#9;&#9;let myView = SKView() &#9;&#9;&#9;&#9;myView.translatesAutoresizingMaskIntoConstraints = false &#9;&#9;&#9;&#9;return myView &#9;&#9;}() &#9;&#9;private func addConstraints(){ &#9;&#9;&#9;&#9; var constraints = [NSLayoutConstraint]() &#9;&#9;&#9;&#9;//add &#9;&#9;&#9;&#9; constraints.append(myView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)) &#9;&#9;&#9;&#9; constraints.append(myView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)) &#9;&#9;&#9;&#9; constraints.append(myView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)) &#9;&#9;&#9;&#9; constraints.append(myView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)) &#9;&#9;&#9;&#9;//activate &#9;&#9;&#9;&#9; NSLayoutConstraint.activate(constraints) &#9;&#9; } &#9;&#9;override func viewDidLoad() { &#9;&#9;&#9;&#9;super.viewDidLoad() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewDidLoad") &#9;&#9;&#9;&#9;#endif &#9;&#9;&#9;&#9; //&#9;&#9;&#9;&#9;if let view = self.view as! SKView? &#9;&#9;&#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;&#9;&#9;view.addSubview(myView) &#9;&#9;&#9;&#9;&#9;&#9;addConstraints() &#9;&#9;&#9;&#9;&#9;&#9;var scene : GameScene! //&#9;&#9;&#9;&#9;var scene = GameScene(size: myView.frame.size) //&#9;&#9;&#9;&#9;let scene = GameScene(size: myView.frame.size) &#9;&#9;&#9;&#9;&#9;&#9;DispatchQueue.main.async { [self] in scene = GameScene(size: myView.frame.size ) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;scene.anchorPoint = CGPoint(x: 0.0, y: 0.0) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;scene.backgroundColor&#9; = .clear &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;scene.scaleMode&#9;&#9;&#9;&#9; = .aspectFit &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myView.isHidden&#9;&#9;&#9;&#9;&#9; = false &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myView.ignoresSiblingOrder&#9;&#9;= true &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myView.showsFPS&#9;&#9;&#9;&#9;&#9;&#9;&#9; = true &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myView.showsNodeCount&#9;&#9;&#9;&#9; = true &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myView.showsPhysics&#9;&#9;&#9;&#9;&#9; = true &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;myView.presentScene(scene) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9; &#9;&#9;} &#9;&#9;override func viewWillLayoutSubviews() { &#9;&#9;&#9;&#9;super.viewWillLayoutSubviews() &#9;&#9;} &#9;&#9;override func viewDidLayoutSubviews() { &#9;&#9;&#9;&#9;super.viewDidLayoutSubviews() &#9;&#9;&#9;&#9;#if DEBUG &#9;&#9;&#9;&#9;&#9;&#9;print ("GVC viewDidLayoutSubviews") &#9;&#9;&#9;&#9;#endif &#9;&#9;&#9;&#9;getScreenDimensions (screen: &screenDims) &#9;&#9;&#9;&#9;if myGlobalVars.safeSceneRect == .zero { &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.sceneRect = view.frame &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.sceneRect = myView.frame &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;if #available(iOS 11.0, *) { &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.topSafeArea&#9;&#9;= view.safeAreaInsets.top &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.bottomSafeArea = view.safeAreaInsets.bottom &#9;&#9;&#9;&#9;} else { &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.topSafeArea&#9;&#9;= topLayoutGuide.length &#9;&#9;&#9;&#9;&#9;&#9;myGlobalVars.bottomSafeArea = bottomLayoutGuide.length &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9; &#9;&#9;override var shouldAutorotate: Bool { &#9;&#9;&#9;&#9;return false &#9;&#9;} &#9;&#9;override var supportedInterfaceOrientations: UIInterfaceOrientationMask { &#9;&#9;&#9;&#9;if UIDevice.current.userInterfaceIdiom == .phone { &#9;&#9;&#9;&#9;&#9;&#9;return .portraitUpsideDown &#9;&#9;&#9;&#9;} else { &#9;&#9;&#9;&#9;&#9;&#9;return .all &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;override var prefersStatusBarHidden: Bool { &#9;&#9;&#9;&#9;return false &#9;&#9;} }
1
0
6.2k
Nov ’20
I have a question about using self.view.safeAreaInsets in GameViewController
I am currently using this code in my GameViewController file to retrieve the boundaries of the safeArea &amp;#9; override func viewWillLayoutSubviews() { &amp;#9;&amp;#9;&amp;#9;&amp;#9;super.viewWillLayoutSubviews() &amp;#9;&amp;#9;&amp;#9;&amp;#9;let safeAreaInsets = self.view.safeAreaInsets &amp;#9;&amp;#9;} My concern is that if I were using a UIView (called myView below), I could automatically apply it with this code block and never think of it again. 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)) } Is there an equivalent call when I'm doing that for a UIViewController? Also, from all my reading online many posts have said to use trailing and leading rather than top and bottom. However self.view.safeAreaInsets appears to only have top and bottom.
18
0
2.5k
Nov ’20
Am having trouble moving code into a separate function
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&#9;&#9; private func addConstraints(){ &#9;&#9;&#9;&#9;var constraints = [NSLayoutConstraint]() &#9;&#9;&#9;&#9; 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 &#9;&#9;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 GameViewControlimport UIKit import SpriteKit class GameViewController: UIViewController { &#9;&#9; &#9;&#9;private let myView : UIView = { &#9;&#9;&#9;&#9;let myView = UIView() &#9;&#9;&#9;&#9;setViewAttributes(view: myView) &#9;&#9;&#9;&#9;return myView &#9;&#9;}() &#9;&#9;private func addConstraints(){ &#9;&#9;&#9;&#9; var constraints = [NSLayoutConstraint]() &#9;&#9;&#9;&#9;//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 }
17
0
1.2k
Oct ’20
Why am I getting two different screen dimensions in different projects (Swift)?
I just finished a very rough draft of my first app whilst learning Swift. So I decided to remake the app so that my code would be cleaner/more compliant, etc. I don't use storyboards, I launch from GameViewControler, both apps are set for a minimum iOS of 13.5, and both are run on the iPhoneX simulator...as well as my iPhoneX itself. But for some reason in each different app, I am getting different screen sizes! Am going to assume I did something different when I "created" the new project, but am unable to distinguish what that is. Here is my entire GameViewController.swift file and have included a photo of the different screen sizes. I break right after I get both the bounds and native bounds. The two different sizes are: In the 1st project I get wPixels 1125 hPixels 2436 wPoints 375 hPoints 812 and the 2nd wPixels 960 hPixels 1440 wPoints 320 hPoints 480 import UIKit import SpriteKit class GameViewController: UIViewController { &#9;&#9;override func viewDidLoad() { &#9;&#9;&#9;&#9;super.viewDidLoad() &#9;&#9;&#9;&#9;if let view = self.view as! SKView? { &#9;&#9;&#9;&#9;&#9;&#9;var wPix = UIScreen.main.nativeBounds.width &#9;&#9;&#9;&#9;&#9;&#9;var hPix = UIScreen.main.nativeBounds.height &#9;&#9;&#9;&#9;&#9;&#9;var wPoi&#9;= UIScreen.main.bounds.width &#9;&#9;&#9;&#9;&#9;&#9;var hPoi&#9;= UIScreen.main.bounds.height &#9;&#9;&#9;&#9;&#9;&#9;var scene : GameScene! &#9;&#9;&#9;&#9;&#9;&#9;DispatchQueue.main.async { [self] in &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; scene = GameScene(size: CGSize(width: wPoi, height: hPoi)) &#9;&#9;&#9;&#9;&#9;&#9;scene.anchorPoint = CGPoint(x: 0.0, y: 0.0) &#9;&#9;&#9;&#9;&#9;&#9;scene.backgroundColor = .red &#9;&#9;&#9;&#9;&#9;&#9;scene.scaleMode = .aspectFit &#9;&#9;&#9;&#9;&#9;&#9;view.isHidden = false &#9;&#9;&#9;&#9;&#9;&#9;view.presentScene(scene) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;view.ignoresSiblingOrder = true &#9;&#9;&#9;&#9;&#9;&#9;view.showsFPS = true &#9;&#9;&#9;&#9;&#9;&#9;view.showsNodeCount = true &#9;&#9;&#9;&#9;&#9;&#9;view.showsPhysics = true &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;override var shouldAutorotate: Bool { &#9;&#9;&#9;&#9;return false &#9;&#9;} &#9;&#9;override var supportedInterfaceOrientations: UIInterfaceOrientationMask { &#9;&#9;&#9;&#9;if UIDevice.current.userInterfaceIdiom == .phone { &#9;&#9;&#9;&#9;&#9;&#9;return .allButUpsideDown &#9;&#9;&#9;&#9;} else { &#9;&#9;&#9;&#9;&#9;&#9;return .all &#9;&#9;&#9;&#9;} &#9;&#9;} &#9;&#9;override var prefersStatusBarHidden: Bool { &#9;&#9;&#9;&#9;return false &#9;&#9;} }
2
0
895
Oct ’20