SKLabelNode Won't Update Text From Function

189 Views Asked by At

I have this game project and it has a coin system. I also have an option for users to watch a video ad to get 50 coins added to their total. Since the shop page is a SKScene, I run the ad through the view controller and when it is done presenting, the viewcontroller runs a function inside the scene that should update the amount of coins and the label that displays them.

Here is the code for my view controller:

class GameViewController: UIViewController , GADRewardBasedVideoAdDelegate {

var rewardBasedVideo: GADRewardBasedVideoAd!
var rewardvideoisinprogress = false
var interstitial: GADInterstitial!

var adcounter = 0

override func viewDidLoad() {
    super.viewDidLoad()

    adcounter = UserDefaults.standard.integer(forKey: "AdCounter")
    print(adcounter)

    createandloadvideoad()

    interstitial = GADInterstitial(adUnitID: "ca-app-pub-3343126174384559/7308554354")
    let request = GADRequest()
    interstitial.load(request)

    ThemeShop().updatecoins()

    NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.presentvideoad), name: NSNotification.Name("video"), object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.inter), name: NSNotification.Name("inter_"), object: nil)

    if let view = self.view as! SKView? {
        // Load the SKScene from 'GameScene.sks'
        if let scene = SKScene(fileNamed: "MainMenu") {
            // Set the scale mode to scale to fit the window
            scene.scaleMode = .aspectFill

            // Present the scene
            view.presentScene(scene)
        }

        view.ignoresSiblingOrder = true 
    }
}

@objc func inter(){
    adcounter = adcounter + 1
    print(adcounter)
    if adcounter == 2{
        adcounter = 0
        if interstitial.isReady {
            interstitial.present(fromRootViewController: self)
            interstitial = createad()
        } else {
            print("Ad wasn't ready")
        }
    }
    UserDefaults.standard.set(adcounter, forKey: "AdCounter")  
}

func createad() -> GADInterstitial {
    let inter = GADInterstitial(adUnitID: "ca-app-pub-3343126174384559/7308554354`")

    inter.load(GADRequest())

    return inter
}

func createandloadvideoad(){
    rewardBasedVideo = GADRewardBasedVideoAd.sharedInstance()
    rewardBasedVideo?.delegate = self
    if !rewardvideoisinprogress && rewardBasedVideo?.isReady == false{

        //ca-app-pub-3343126174384559/3425197396
        rewardBasedVideo?.load(GADRequest(), withAdUnitID: "ca-app-pub-3940256099942544/1712485313")
        rewardvideoisinprogress = true
    }
}

@objc func presentvideoad(){
    if rewardBasedVideo?.isReady == true{
        rewardBasedVideo?.present(fromRootViewController: self)

    }else{
        print("Was NOt Reardyadjfsjfsalfkj")

    }
    createandloadvideoad()
}

func rewardBasedVideoAd(_ rewardBasedVideoAd: GADRewardBasedVideoAd,
                        didFailToLoadWithError error: Error) {
    print("Reward based video ad failed to load: \(error.localizedDescription)")
    rewardvideoisinprogress = false
}

func rewardBasedVideoAdDidReceive(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
    print("Reward based video ad is received.")
}

func rewardBasedVideoAdDidOpen(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
    print("Opened reward based video ad.")
}

func rewardBasedVideoAdDidStartPlaying(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
    print("Reward based video ad started playing.")
}

func rewardBasedVideoAdDidClose(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
    rewardvideoisinprogress = false

    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1500) , execute: {
        print("Brikdsajfaslkd")
        ThemeShop().updatecoins()
    })
}

func rewardBasedVideoAd(_ rewardBasedVideoAd: GADRewardBasedVideoAd,
                        didRewardUserWith reward: GADAdReward) {
    var coins = UserDefaults.standard.integer(forKey: "Coins")
    coins = coins + 50
    UserDefaults.standard.set(coins, forKey: "Coins")  
}

}

This is the function inside the SKScene:

func updatecoins(){
    print("Updating")
    coins = UserDefaults.standard.integer(forKey: "Coins")
    print("Coins: \(coins)")

    self.coinlabel.text = String(self.coins)
    print(self.coinlabel.text)  
}

I know that the coins are being added to the balance behind the scenes because if I exit the scene and reenter, the coins show up like they should.

2

There are 2 best solutions below

4
Ron Myschuk On

you're trying to call a function on a class variable of ThemeShop you need to be calling the func on an instance variable of the class.

you don't show your ViewController code so you may have to adapt this accordingly

have a scene variable at the top of your viewController

private var themeShop: ThemeShop!

then in your viewDidLoad when you load the scene put it inside of the variable

//this is if you are loading your scene from an sks file. 
//your code may be different if it is just loaded from code with no sks file
if let scene = SKScene(fileNamed: "ThemeShop") {
    self.themeShop = scene

then in your viewController when you need to access the scene

func rewardBasedVideoAdDidClose(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
    rewardvideoisinprogress = false

    sleep(1)
    themeShop.updatecoins()  
}
1
Nico S. On

I think you label is not updating because you are not on the main queue. Also I made some changes to your code. You shouldn't use sleep() better use asyncAfter:

func rewardBasedVideoAdDidClose(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
    isRewardVideoInProgress = false

    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        ThemeShop().updatecoins()  
    }
}

func rewardBasedVideoAd(_ rewardBasedVideoAd: GADRewardBasedVideoAd,
                    didRewardUserWith reward: GADAdReward) {
    var coins = UserDefaults.standard.integer(forKey: "Coins")
    coins = coins + 50
    UserDefaults.standard.set(coins, forKey: "Coins")   
}

func updatecoins(){
    print("Updating")
    coins = UserDefaults.standard.integer(forKey: "Coins")
    print("Coins: \(coins)")

    DispatchQueue.main.async {
        self.coinlabel.text = "\(self.coins)"
        print(self.coinlabel.text)  
    }
}