Changing a property of an object from GameViewController.swift in GameScene.swift - ios

I'm new to Swift, so sorry if this seems like an obvious question.
I'm trying to write a game in Swift, and I have designed a label and a play button in the storyboard.
I've added references to these objects in the GameViewController.swift file as seen here:
// MARK: Objects
#IBOutlet var gameLabel: UILabel!
#IBOutlet var playButton: UIImageView!
// MARK: Actions
#IBAction func playButtonTapped(sender: UITapGestureRecognizer) {
GameScene().gameStart()
}
This belongs to the GameViewController class: class GameViewController: UIViewController.
However, the main game itself takes place in GameScene.swift. This involves me having to hide the label and image as soon as the game starts. I'm unsure how to set the properties for these objects to hide, since if I did the following in GameScene.swift:
GameViewController().playButton.hidden = true
...the game crashes with a fatal error. The error says: fatal error: unexpectedly found nil while unwrapping an Optional value.
Does anyone have a suggestion for this problem? Any help is much appreciated. Sorry if the information was difficult to understand.
Cheers.

You are creating a new instance of 'GameViewController(), but you want you want use your already existent one. If you only want to create oneGameViewController`, which is probably the case, you could use a static instance variable.
In GameViewController, put:
static var instance: GameViewController!
In it's viewDidLoad(), put:
GameViewController.instance = self
Finally, in your GameScene, switch GameViewController() with GameViewController.instance.

Related

How can an outlet be nil even though it has been set

I have a viewController with two embedded viewControllers through containers. I then created outlets from the parent viewController's containers to the parent class. I want to either hide or show the containers depending on certain conditionals.
But if I simply write:
#IBOutlet var twoArmsContainer: UIView! {
didSet {
print("SETTING TWO ARM")
}
}
override func viewDidLoad() {
super.viewDidLoad()
twoArmsContainer.isHidden = true //container is nil
}
Then it crashes with twoArmsContainer being nil after the print in didSet has been triggered. How is it possible that the outlet is set, but then becomes nil? I have tried hiding it inside didSet and that works fine:
#IBOutlet var twoArmsContainer: UIView! {
didSet {
print("SETTING TWO ARM")
twoArmsContainer.isHidden = true //WORKS
}
}
What else can I say? The class I'm working in inherits from another class so there is a super.viewDidLoad. Not sure if that is relevant. I tried putting the outlets in the super class but with the same results. I also tried removing and readding the outlets again. Have never experienced this problem before. Let me know if I should show more code; perhaps the entire class. Not really sure what's relevant as I'm clueless of where to start.
Ok, so I found out what was wrong; an issue impossible to detect without access to the code, so in retrospect I should have posted both the parent class and container class. Sorry about that.
Anyway the issue was that the container viewController inherited from the parent viewController. This enabled me to share code in the two container viewControllers.
So the structure was basically this:
class WizardChooseArmViewController: WizardViewController {
...
This is the parent viewController which inherits from a base viewController. Then the container viewControllers looked like this:
final class WizardTwoArmsViewController: WizardChooseArmViewController {
...
Apparently it's a bad idea for containers to inherit from its parent, so I refactored and changed it to:
final class WizardTwoArmsViewController: WizardViewController {
...
Not quite sure why its not possible for containers to inherit from its parent. Would be great if someone could brief me.

this class is not key value coding-compliant error? Xcode 11

Currently, I've been following a Coursera course called Intro to Swift Programming 5. The video I was following was about the Xcode's MVC, and I'm getting the following error, even though I did what the person on screen had done:
Thread 1: Exception: "[< UIViewController 0x7fd2b6c053d0>
setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key colorLabel."
I've tried looking it up, but I don't see where I would have referenced something and deleted it. I've also checked to see if there are any warning signs near any of my reference outlets on the Main Storyboard, but everything seems to be in order there as well.
My code is as follows:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var modelLabel: UILabel!
#IBOutlet weak var colorLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let appleProduct = AppleProduct(name: "iPhone X", color: "Space Gray", price: 999.99)
modelLabel.text = appleProduct.name
colorLabel.text = "in \(appleProduct.color)"
priceLabel.text = "$\(appleProduct.price)"
}
}
Has anyone else experienced this issue and can help me? I'd greatly appreciate it, and I'm happy to provide any other code that's needed if this is unclear. Thanks!
CustomPrettyView is the class of the view. But you also need to declare the class of the view controller itself; otherwise Xcode will decide that it's UIViewController.
Click on the scene and in the inspector in the "Custom Class" section it will say that the class is UIViewController and it will be faded because you haven't overridden it. Change that to be the name of your view controller, which is ViewController.
I would also recommend that you change that class name to be something more meaningful, maybe PrettyViewController or something like that.

App fails to replace label text with UUID

I am trying to work on a program that will change a label to a user's UUID but for some reason it does not work and I can't seem to figure out since I'm still learning the language. Below is my attempt. This is the ViewController.swift file:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var text: UILabel!
#IBAction func getuuid(sender: AnyObject) {
text.text = UIDevice.currentDevice().identifierForVendor!.UUIDString
}
}
Place a breakpoint on the line where you set the text.text value to the UUID. Odds are, you are missing the connection from your storyboard to the function call. To test this, click on the button once the breakpoint is in place, and if you see it freeze the code at that spot, then your connection is at least working. If it does not freeze there, then you need to connect the getuuid function to your button.

Using the same property name/reference for Outlets in a base class and potential bugs

So I have a base class UIViewController called UITabBarTopLevelViewController:
class UITabBarTopLevelViewController: UIViewController {
#IBOutlet weak var uiNavItemTitle: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
uiNavItemTitle.titleView = CoreUtility.LogoForUINavBarGet()
// Do any additional setup after loading the view.
}
I then have two UIViewControllers that inherit from my base class and both look like this, except the second is called MyViewController2:
class MyViewController1: UITabBarTopLevelViewController {
//#IBOutlet weak var uiNavItemTitle: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
//uiNavItemTitle.titleView = CoreUtility.LogoForUINavBarGet()
}
I add a Navigation Bar object to each child UIViewController super view and then I CTRL drag and add a new outlet to each UIViewController child class:
And here is the second CTRL drag outlet:
These are different references, but I can comment out the #IBOutlet weak var uiNavItemTitle: UINavigationItem! in my child classes and reference one time only in the base class UITabBarTopLevelViewController, for both MyViewController1 and MyViewController2.
You can see, when I hover over the outlet circle, in my base class, it highlights both UINavigationItem in the Story Board:
I am surprised this works, its nice for me that it works because I only need to set the uiNavItemTitle.titleView for my logo one time for both views. This is what I want but there seems to be a bit of magic that I can reference multiple outlet references one time in my base class and there is no bugs or crashes.
I currently have no memory leaks or crashes and my app is working just fine and doing exactly as I desire.
Will there be any bugs with this?
Could someone explain how this is working?
Is the fact that this works, not surprising to experienced Swift developers?
That's how subclass exactly works.
You placed a UINavigationItem in the base class UITabBarTopLevelViewController through
uiNavItemTitle.titleView = CoreUtility.LogoForUINavBarGet()
Also, MyViewController1 and MyViewController2 inherit from the base class UITabBarTopLevelViewController. That's say these child viewControllers both have a UINavigationItem which inherit from their UITabBarTopLevelViewController.
This is not a bug, on the other hand, more like a topic about design pattern though. You could place all the base stuff into a base class, inherit from those classes and implement the specific detail within the child class.
HTH.

UIActivityIndicatorView Swift stopanimation

I have a swift project and hav3 an Activity Indicator declared in my ViewController. When I click a UIButton, the indicator starts. However, I can not access this indicator in my other class to stop it when the code is completed. Any help would be appreciated.
#IBOutlet var spinner: UIActivityIndicatorView! // <--- want to access in another class
#IBAction func sendClick(sender: UIButton) {
spinner.startAnimating()
var msg = Message()
msg.send()
}
Take a look at your scopes and access control!
If the two classes are not within the same module, you need to declare the object as public. If the object is even declared to be private, you can't access it from another file's class.
For more information about access control read this article from Apple's swift blog: https://developer.apple.com/swift/blog/?id=5
or here in the documentation:
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html

Resources