Unwrapping UILabel always returns nil - swift

I've hooked a UILabel to my VC using the storyboard, does generating a weak var but connected to a storyboard reference. Anyway, whenever I try to unwrap it, all I get is a nil value. What confuses me the most is that I'm able to access it on another method. I've already safe unwrapped it, it avoids the compiler errors, but doesn't solve my problem.
The compiler message is: fatal error: unexpectedly found nil while unwrapping an Optional value
Here is some of the code:
#IBOutlet weak var linesLeftCountLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
skView = SKView(frame: sceneView.frame)
skView.multipleTouchEnabled = false
//Create and configure the scene.
scene = LogoRefactoryScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
skView.presentScene(scene)
tapGesture = UITapGestureRecognizer(target: self, action: "eraseLine:")
tapGesture.delegate = self
view.addGestureRecognizer(tapGesture)
view.addSubview(skView)
}
Here I'm able to access it:
#IBAction func colorPickerOfColor(sender: UIButton) {
var pickerName = ""
switch sender.tag {
case 0:
pickerName = "green"
case 1:
pickerName = "red"
case 2:
pickerName = "blue"
default:
pickerName = "orange"
}
pickerName += "ColorPicker"
colorPickerView.image = UIImage(named: pickerName)
currentColorName = ColorSelection.fromRaw(sender.tag + 1)!.colorName
let color = ColorSelection.fromRaw(sender.tag + 1)!.getSKColor()
scene.lineColor = color
linesLeftCountLabel.textColor = color
}
Here is where the compiler complains:
func lineHasBeenDrawn() {
linesLeftCountLabel.text = "Any String"
}

Sorry for that guys. lineHasDrawn is a delegate method, that's why the strange behaviour.
My bad.

Please check if you have connected the referencing outlet in the storyboard to the IBOutlet of your code

Related

Call selector from nother class - Swift 3

I'm creating an UIbutton from "Utils_class", and return it to my "getBtsDetails" class.
I successfully achieve to call "buttonAction" function implemented into "getBtsDetails", but then it return an error
"Unexpectedly found nil while unwrapping an Optional value"
getBtsDetails :
let Utils_Class = Utils()
var labelY : Int = 90
override func viewDidLoad() {
super.viewDidLoad()
WS_Class.GetDiplomaSubject(id: Int(self.BTS_id)!) { number, responseObject, error in
if((error) == nil) {
#let's create an UIbutton from Utils_class which gonna call the buttonAction below
self.scrollview.addSubview(self.Utils_Class.createButton(text: "Calcul", buttonY:self.labelY+30))
self.scrollview.contentSize.height = CGFloat(self.labelY+40)
}
}
}
#objc func buttonAction(_ sender:UIButton!)
{
#the error occurs here
print(self.Utils_Class.getTextFields(view : self.scrollview)/1)
}
And my second class, Utils :
public func createButton(text: String!, buttonY: Int!) -> UIButton {
helpClasses = GetBTSDetails.init()
let button = UIButton(type: UIButtonType.system) as UIButton
button.frame = CGRect(x:0, y:buttonY, width:self.screenWidth/5, height:15)
button.backgroundColor = UIColor.lightGray
button.setTitle(text, for: UIControlState.normal)
button.tintColor = UIColor.black
button.addTarget(btsClasse, action: #selector(btsClasse.buttonAction(_:)), for: .touchUpInside)
return button
}
var btsClasse: GetBTSDetails!
Ok, i finally succeed, by simply creating a new instance of my class and replacing :
var btsClasse: GetBTSDetails!
by
var btsClasse = GetBTSDetails()
This way, my class "GetBTSDetails", all functions, variables are already initialized allowing myself to call the UIButton action.
Because you didn't init it
var btsClasse: GetBTSDetails!
so when target runs
button.addTarget(btsClasse, action: #selector(btsClasse.buttonAction(_:)),for: .touchUpInside
what in buttonAction will be nil , so you have to linkbtsClasse object to the presented instance that you reference the selector from

Where do you declare UITapGestureRecognizer() in relation to addGestureRecognizer() in Swift?

Problem
centerLabelGesture is being defined outside of the scope of viewDidLoad(), so at the time that .addGestureRecognizer(centerLabelGesture) is called, centerLabelGesture is not defined yet.
import UIKit
import SnapKit
class ViewController: UIViewController {
var screen: UIView!
var centerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
screen = UIView()
centerLabel = UILabel()
view.addSubview(screen)
screen.addSubview(centerLabel)
screen.backgroundColor = .white
screen.snp.makeConstraints { (make) in
make.top.equalTo(view)
make.right.equalTo(view)
make.left.equalTo(view)
make.bottom.equalTo(view)
}
centerLabel.text = "I hope I'm centered."
centerLabel.snp.makeConstraints { (make) in
make.center.equalTo(screen)
}
centerLabel.isUserInteractionEnabled = true
centerLabel.addGestureRecognizer(centerLabelGesture)
}
let centerLabelGesture = UITapGestureRecognizer(target: self, action: #selector(centerLabelTapped))
#objc func centerLabelTapped() {
centerLabel.text = "Ouch, you tapped me!"
}
}
Update 1/19/2019
matt pointed out that centerLabelGesture needs to be declared prior to centerLabel.addGestureRecognizer(centerLabelGesture), inside viewDidLoad()
This is a subtle mistake. The problem is the place you've put this line:
let centerLabelGesture = UITapGestureRecognizer(target: self, action: #selector(centerLabelTapped))
Move that line into the viewDidLoad code:
centerLabel.isUserInteractionEnabled = true
let centerLabelGesture = UITapGestureRecognizer(target: self, action: #selector(centerLabelTapped))
centerLabel.addGestureRecognizer(centerLabelGesture)
The reason is that where you've got that line, it's an instance property, and when you say self as the target in an instance property initializer, it doesn't mean what you think it does (it means the class, not the instance), so the message when you tap is misdirected and does nothing.
I have filed a bug on this issue; in my opinion the compiler should at least warn you that you're making a potential mistake.
Try adding this line in viewDidLoad
centerLabelGesture.numberOfTapsRequired = 1

UIButton become nil when I open settings viewController

I have map and zoom in/out button on it as strong outlet and settings viewController, where show/hide settings crash app because outlet button become nil. How to resolve this?
In mainViewController:
#IBOutlet var zoomIn: UIButton!
#IBOutlet var zoomOut: UIButton!
...
and
func setZoomFalse(){
zoomIn.isHidden = true
zoomOut.isHidden = true
}
func setZoomTrue(){
zoomIn.isHidden = false
zoomOut.isHidden = false
}
SettingsViewController is open with:
self.present(self.settingsViewController, animated: true, completion: nil)
from slide menu
and this call make crash in settingsViewController:
#objc func switchChanged1(_ sender : UISwitch!){
let defaults = UserDefaults.standard
defaults.set(sender.isOn, forKey: settingsView.settingsIsZoom)
isZoom = sender.isOn
if isZoom {
mainViewController.setZoomTrue()
} else {
mainViewController.setZoomFalse()
}
}
I resolve this on this way, I set global variable to true in settingsViewController, which is defined as global in maonViewController, above class definition and in viewWillApear check if this variable is true and if yes I call setZoomTrue and it works on this way, when it's called from different viewController it crashes with nil message ...

flip card causes fatal error in swift

I am following this card flipping tutorial and instead of creating the UIView and the UIImageViews programmatically I have created these in my storyboard.
When I click the card, the animation kicks in and turns over to the front image, but when I click again, this creates a fatal error:
unexpectedly found nil while unwrapping an Optional value.
I can not figure out why this error occurs.
Here is the code which is the transformation of the above mentioned tutorial:
class FirstViewController: UIViewController {
#IBOutlet weak var flashCardView: UIView!
#IBOutlet weak var backImage: UIImageView!
#IBOutlet weak var frontImage: UIImageView!
var showingBack = true
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(target: self, action: Selector("tapped"))
singleTap.numberOfTapsRequired = 1
flashCardView.addGestureRecognizer(singleTap)
flashCardView.addSubview(backImage)
view.addSubview(flashCardView)
}
func tapped() {
if (showingBack) {
UIView.transitionFromView(backImage, toView: frontImage, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
showingBack = false
} else {
UIView.transitionFromView(frontImage, toView: backImage, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromLeft, completion: nil)
//here I get the error when flipping the card back to the back image
showingBack = true
}
}
}
I believe that when you transition, the old image's reference count is decremented, and since they're declared as weak it is getting destroyed. Try removing the weak declarations, and it will probably work. Looking at the tutorial, they don't have weak.

Hiding or Showing Google Ad View in Swift with Sprite Kit

In my game I would like there to be an Google Banner View in the main menu scene and game over scene. Here's what I have in the GameViewController:
override func viewWillLayoutSubviews(){
super.viewWillLayoutSubviews()
let skView = self.view as! SKView
googleBannerView = GADBannerView(adSize: kGADAdSizeSmartBannerPortrait)
googleBannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
googleBannerView.rootViewController = self
var request: GADRequest = GADRequest()
googleBannerView.loadRequest(request)
googleBannerView.frame = CGRectMake(0, skView.bounds.height - googleBannerView.frame.size.height, googleBannerView.frame.size.width, googleBannerView.frame.size.height)
self.view.addSubview(googleBannerView!)
if skView.scene == nil{
let mainMenuScene = MainMenuScene(size: skView.bounds.size)
mainMenuScene.scaleMode = SKSceneScaleMode.AspectFill
mainMenuScene.backgroundColor = UIColor.whiteColor()
skView.presentScene(mainMenuScene)
}
}
func showBanner(){
if googleBannerView != nil{
self.googleBannerView!.hidden = false
var request: GADRequest = GADRequest()
self.googleBannerView.loadRequest(request)
}
}
func hideBanner(){
println("hideBanner() called")
self.googleBannerView.hidden = true
}
In the GameScene I have this:
override init(size: CGSize) {
super.init(size: size)
let gameViewController = GameViewController()
gameViewController.hideBanner()
When I run this it starts up fine, but when I press play it crashes and says: fatal error: unexpectedly found nil while unwrapping an Optional value. This doesn't make much sense because it can't be nil because I know there is an ad banner, right? What I am doing wrong. Thank you in advance.
-Vinny
There could possibly be an error in your show banner function. Try taking out the exclamation in:
self.googleBannerView!.hidden = false
If the banner view is not nil, then it doesn't need to unwrapped