Richard Murff Richard Murff - 3 months ago 39
iOS Question

Swift iOS: How can I get player's name in SpriteKit?

I have built a game using SpriteKit and I have it fully functional except for getting the user to input their name to store with their high scores. I'm using NSUserDefaults to store the scores as an array of their top 5 scores. I'd like to store their name as well because eventually I plan to move the storage to a server instead of NSUserDefaults to allow for players to compete for high scores.

My thought was to present a UIAlertController when the game first runs on the device, to grab their name via a text input field, then store it in NSUserDefaults. But no matter where I put the code for UIAlertController (GameScene.swift, GameViewController.swift, and even AppDelegate.swift) it doesn't pop up.

The code I'm using for the alert is:

let ac = UIAlertController(title: "Enter Name", message: nil, preferredStyle: .Alert)
ac.addTextFieldWithConfigurationHandler(nil)

ac.addAction(UIAlertAction(title: "OK", style: .Default) { [unowned self, ac] _ in
let playerName = ac.textFields![0]

})

ac.presentViewController(ac, animated: true, completion: nil)


This is the UPDATED CODE based on comments below, including the entire viewDidLoad function:

override func viewDidLoad() {
super.viewDidLoad()

let ac = UIAlertController(title: "Enter Name", message: nil, preferredStyle: .Alert)
ac.addTextFieldWithConfigurationHandler(nil)

ac.addAction(UIAlertAction(title: "OK", style: .Default) { [unowned self, ac] _ in
let playerName = ac.textFields![0]

})

self.presentViewController(ac, animated: true, completion: nil)

if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false

/* 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)
currentGame = scene
scene.viewController = self
}

}

Answer

Presenting a view controller won't generally work inside of viewDidLoadsince it is called after the view is loaded into memory, but before it is presented on the screen (see the view controller lifecycle here). You can set things up there (like your scenes) but any animations or interactive elements must be done later.

A safer place to put this would be in viewDidAppear (along with some logic to make sure it doesn't get repeatedly presented) or in response to a tap on a button.

Also, you have to call presentViewController from a view controller that is already on the screen for it to be shown. So, if you have this code somewhere in your GameViewController, you could change

ac.presentViewController(ac, animated: true, completion: nil)

to

self.presentViewController(ac, animated: true, completion: nil)