UIButton Not Working After Updated to Xcode 8.3 - swift

After I updated to Xcode 8.3 the following code is not working in Xcode Playgrounds. Before on Xcode 8.2.1, I was able to click on the button and the action would follow, but now nothing is happening when I click the button.
import UIKit
import SpriteKit
import PlaygroundSupport
let view = SKView(frame: CGRect(x: 0, y: 0, width: 550, height: 575))
let scene = SKScene(size: CGSize(width: 550, height: 575))
scene.backgroundColor = UIColor.white
scene.scaleMode = SKSceneScaleMode.aspectFit
view.presentScene(scene)
class Responder: NSObject {
#objc func nextScene() {
print("Next button pressed!")
}
}
let responder = Responder()
let nextButton = UIButton(type: .system)
nextButton.frame = CGRect(x: 250, y: 557.5, width: 40, height: 15)
nextButton.setTitle("Next", for: .normal)
nextButton.titleLabel?.font = UIFont(name: "Marker Felt", size: 17)
nextButton.tintColor = .black
nextButton.addTarget(responder, action: #selector(Responder.nextScene), for: .touchUpInside)
view.addSubview(nextButton)
PlaygroundPage.current.liveView = view
EDIT: I updated my code so that it includes PlaygroundPage.current.liveView = view and the code for setting up the view and scene.

You do not set a live view for the playground in your code. Normally, a playground will execute the code and stop - it does not wait for input or events etc, unless you explicitly specify it should.
You should add the following line at the end of the playground to specify that canvas is a live view - provided it is, I can't know since you have not provided the implementation for canvas.
PlaygroundPage.current.liveView = canvas

Related

Centering buttons programatically in Swift

I am trying to center Google Sign In and Sign Out buttons programmatically. In order to put both of them in the third quarter. I create 2 views that I wanted to put buttons to their center, in Storyboard.
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance().signIn()
let gSignIn = GIDSignInButton(frame: CGRect(x: 0, y: 0, width: loginView.frame.size.width, height: loginView.frame.size.height))
loginView.addSubview(gSignIn)
gSignIn.center = loginView.center
let gSignOut = UIButton(frame: CGRect(x: 0, y: 0, width: signOutView.frame.size.width, height: signOutView.frame.size.height))
gSignOut.backgroundColor = UIColor.white.withAlphaComponent(0)
gSignOut.setTitle("Sign Out", for: .normal)
gSignOut.setTitleColor(UIColor.red, for: .normal)
gSignOut.addTarget(self, action: #selector(self.signOut(_:)), for: .touchUpInside)
gSignOut.center = signOutView.center
self.signOutView.addSubview(gSignOut)
As you can see, also I am trying to resize buttons according to view size which helps me to resize buttons depend on device size.
Here is the second half of my storyboard.
Here is the simulator screen when I run the code.
Thanks.
Use auto-layout instead of setting frame.center, it will be more flexible.
Autolayout goes like below code.
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance().signIn()
let gSignIn = GIDSignInButton(frame: CGRect(x: 0, y: 0, width: loginView.frame.size.width, height: loginView.frame.size.height))
gSignIn.translatesautoresizingmaskintoconstraints = false
loginView.addSubview(gSignIn)
NSLayoutConstraint.activate([
gSignIn.leftAnchor.constraint(equalTo: loginView.leftAnchor),
gSignIn.rightAnchor.constraint(equalTo: loginView.rightAnchor),
gSignIn.topAnchor.constraint(equalTo: loginView.topAnchor),
gSignIn.bottomAnchor.constraint(equalTo: loginView.bottomAnchor)
])

Programatically added UIButton doesn't go away after switching scenes

I'm using a game app template in Swift 3 and when I transition from my 'start' screen to my 'Game' scene, the button from the 'start' screen doesn't go away. I read other people posts similar to this but nothing helped. My button is a programatically added uibutton with a uibezierpath rounded rectangle behind the button to make it look nice. The problem is, it(the button, and the UIBezierpath) won't go away when I change scenes - it's in the exact same spot as the 'start' screen.
My Button code with the UIBezierpath:
let playAgain = UIButton()
playAgain.frame = CGRect(x: 225, y: 247, width: 115, height: 36)
playAgain.backgroundColor = SKColor.lightGray
playAgain.setTitle("Play", for: .normal)
playAgain.setTitleColor(.black, for: .normal)
self.view?.addSubview(playAgain)
playAgain.addTarget(self, action: #selector(playAgainTapped(_:)), for: .touchUpInside)
//now for the bezierpath/ rounded rect
//let doYourPath = UIBezierPath(rect: CGRect(x: 20, y: 20, width: 100, height: 36))
//this also works
let roundRect = UIBezierPath(roundedRect: CGRect(x: 218, y: 240, width: 130, height: 50), cornerRadius: 18)
let layer = CAShapeLayer()
layer.path = roundRect.cgPath
layer.strokeColor = UIColor.black.cgColor
layer.fillColor = UIColor.lightGray.cgColor
self.view?.layer.addSublayer(layer)
func playAgainTapped(_ sender: Any?) -> Void {
print("***********")
backToGame()
}
Switch scenes code:
func backToGame(){
removeAllChildren()
run(SKAction.sequence([
SKAction.wait(forDuration: 3.0),
SKAction.run() {
// 5
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
let scene = GameScene(size: self.size)
self.view?.presentScene(scene, transition:reveal)
}
]))
}
Any ideas?
You are presenting the scene on the same view as the button's superview.
Since the scene is independent from the views that are on the scene, your button will remain untouched, so you should explicitly remove the button if you want it to be removed.
Declare the button and the rounded rectangle globally and remove them from their superview/superlayer in backToGame.
let playAgain = UIButton()
let layer = CAShapeLayer()
func backToGame(){
removeAllChildren()
playAgain.removeFromSuperview()
layer.removeFromSuperlayer()
run(SKAction.sequence([
SKAction.wait(forDuration: 3.0),
SKAction.run() {
// 5
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
let scene = GameScene(size: self.size)
self.view?.presentScene(scene, transition:reveal)
}
]))
}

Programmed Button in swift is not working

http://pastebin.com/MgQ7wx3g
So I am currently trying to get this button to work called Play button
let playButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "VideoIcon.png") as UIImage?
button.backgroundImage(for: .normal)
button.addTarget(self, action: #selector(pressBackButton(button:)), for: .touchUpInside)
button.setImage(image, for: .normal)
return button
}()
func pressBackButton(button: UIButton) {
print("test")
if let playVideoButtonURL = post?.videourl {
let player = AVPlayer(url: playVideoButtonURL as URL)
let playerLayer = AVPlayerLayer(player:player)
playerLayer.frame = CGRect(x: 100, y: 200, width: 100, height: 100)
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
self.layer.addSublayer(playerLayer)
player.play()
}
}
When I click on it nothing happens even if the video code is wrong it should still print test. It's not giving me any errors on startup to work with either. The paste bin has my full code.
I tried your code given in question, with explicitly set frame.
override func viewDidLoad() {
super.viewDidLoad()
// Set Frame
self.playButton.frame = CGRect(origin: CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 2), size: CGSize(width: 30, height: 30))
self.view.addSubview(playButton)
}
And its working perfectly and the "Test" is printing.
Then I checked your code you posted in given link. There I found this method addConstraintsWithFormat to set autolayout with visual format language. I replaced my code using this method.
self.view.addConstraintsWithFormat(format: "H:|-280-[v0(44)]", view: playButton)
self.view.addConstraintsWithFormat(format: "V:|-90-[v0(44)]", view: playButton)
It is also working.
From your code I can find that it's a CollectionViewCell. Could please try to add subviews to its contentView?
The correct method signature is
button.addTarget(self, action: #selector(pressBackButton(_:)), for: .touchUpInside)
and
func pressBackButton(_ button: UIButton) {

iOS Swift: Install and Unistall views programmatically

How to install and uninstall views programmatically?
Example
Im my application I have a StackView containing three different Views: Character, Starship and Vehicle.
Now, I would like that at a certain condition, just one View will appear and the other two won't.
I'm not saying hiding and showing, but installing and uninstalling. Why? because if I keep my views installed my Xcode crash.
Any tips?
I believe the answer you're looking for is here - https://stackoverflow.com/a/36712325/2463875
If You install or uninstall view from storyboard, It is equivalent to add/remove view.
I am not sure if I understand it 100% correctly.. But if you want to add views to a stackview programatically, you can do it kind of the following way. You need to connect the UIStackView to your ViewController to have access to it. There you can add your UIViews depending on a condition.
I've created a playground example. So you can just copy it and run it in a playground and it will also show it visually to you. To make it easier, I've used UILabels. But it's pretty much the same with UIViews.
import UIKit
import PlaygroundSupport
class TestViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "Test"
self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
self.view.backgroundColor = UIColor.brown
let stackview = UIStackView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
stackview.axis = .vertical
stackview.distribution = UIStackViewDistribution.fillEqually
let text = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
text.text = "Hello, i am a label"
let condition = true
if condition {
let text2 = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
text2.text = "Hello, i am another label"
stackview.addArrangedSubview(text2)
}
stackview.addArrangedSubview(text)
self.view.addSubview(stackview)
}
}
let testController = TestViewController()
PlaygroundPage.current.liveView = testController.view
testController

Menu system for Games in SpriteKit

I've looked at a few different post surrounding menu systems in SpriteKit and nothing really focusses on how to implement from start to finish (a basic play button starting the game, background and then sharing icons).
The reason I am looking is that I am a beginner and in the process of building my first basic game. I have used a few of these guides and none seem to give a proper walk through.
Thought it would be good to create a post for all beginners to start out. I have attempted some actual code but it hasn't been successful (quite a few errors though I can post if anyone is interested in seeing what NOT to do).
Anyway, here goes nothing😊 Thanks in advance all, lets see how we can get it done!
well, i believe this is a good question and setting up something as an answer here is not a bad idea. i've setup a starting menu with a title and three buttons in this very simple menu. that can be modified to the desired result later. first of all create a new file for starting menu by adding the file through project pane on the left. then create a spritekitScene also with the same name (startMenu or whatever you want to name it) then do the same for the settings and also credits or any other item you want to add to the start menu.
the next step is the change the entry point of the game from game scene to start menu in view controller swift. change the game scene to whatever you named your menu in this line if let scene = GameScene(fileNamed:"GameScene") to if let scene = StartMenu(fileNamed:"StartMenu") that will push the start menu rather than the game scene. go the start menu and add the following codes for creating a title and buttons to the view. i created the buttons and the text and added separate functions for each for the ease of following up, and then at the end you add the functions for the selector so when the buttons are pressed the new scene gets pushed. you can also add a return button to those scenes or do whatever else you want. so here is the complete start menu code:
import Foundation
import SpriteKit
class StartMenu : SKScene {
var btnPlay : UIButton!
var btnSettings : UIButton!
var btnCredits : UIButton!
var gameTitle : UILabel!
override func didMoveToView(view: SKView) {
// self.backgroundColor = UIColor.orangeColor()
setUpTitleText()
setupButtonPlay()
setupButtonSettings()
setupButtonCredits()
}
func setUpTitleText(){
gameTitle = UILabel(frame: CGRect(x: 0, y: 0, width: view!.frame.width, height: 300))
gameTitle.textColor = UIColor.blackColor()
gameTitle.font = UIFont(name: "Futura", size: 50)
gameTitle.textAlignment = NSTextAlignment.Center
gameTitle.text = "Game Title"
//gameTitle.backgroundColor = UIColor.whiteColor()
self.view?.addSubview(gameTitle)
}
func setupButtonPlay(){
btnPlay = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 100))
btnPlay.center = CGPoint(x: view!.frame.size.width / 2, y: 250)
btnPlay.titleLabel?.font = UIFont(name: "Futura", size: 25)
btnPlay.setTitle("Play", forState: UIControlState.Normal)
btnPlay.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
//btnPlay.backgroundColor = UIColor.grayColor()
btnPlay.addTarget(self, action: #selector(StartMenu.playTheGame), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(btnPlay)
}
func setupButtonSettings(){
btnSettings = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 100))
btnSettings.center = CGPoint(x: view!.frame.size.width / 2, y: 350)
btnSettings.titleLabel?.font = UIFont(name: "Futura", size: 25)
btnSettings.setTitle("Settings", forState: UIControlState.Normal)
btnSettings.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
//btnSettings.backgroundColor = UIColor.grayColor()
btnSettings.addTarget(self, action: #selector(StartMenu.pressTheSettings), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(btnSettings)
}
func setupButtonCredits(){
btnCredits = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 100))
btnCredits.center = CGPoint(x: view!.frame.size.width / 2, y: 450)
btnCredits.titleLabel?.font = UIFont(name: "Futura", size: 25)
btnCredits.setTitle("Credits", forState: UIControlState.Normal)
btnCredits.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
//btnCredits.backgroundColor = UIColor.grayColor()
btnCredits.addTarget(self, action: #selector(StartMenu.pressTheCredits), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(btnCredits)
}
func playTheGame(){
self.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(1.0))
btnPlay.removeFromSuperview()
gameTitle.removeFromSuperview()
btnCredits.removeFromSuperview()
btnSettings.removeFromSuperview()
if let scene = GameScene(fileNamed: "GameScene"){
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
func pressTheSettings(){
self.view?.presentScene(TheSettings(), transition: SKTransition.crossFadeWithDuration(1.0))
btnPlay.removeFromSuperview()
gameTitle.removeFromSuperview()
btnCredits.removeFromSuperview()
btnSettings.removeFromSuperview()
if let scene = TheSettings(fileNamed: "TheSettings"){
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
func pressTheCredits(){
self.view?.presentScene(TheCredits(), transition: SKTransition.crossFadeWithDuration(1.0))
btnPlay.removeFromSuperview()
gameTitle.removeFromSuperview()
btnCredits.removeFromSuperview()
btnSettings.removeFromSuperview()
if let scene = TheCredits(fileNamed: "TheCredits"){
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
}
in this scenario i have hard coded the titles and the buttons, but you can add your own images if you want. this is just a simple way of creating a menu but there are many other ways to do this. as you go along you can build your own in anyway you like.
good luck.