Q:

How to update a variable in SKScene from GameViewController?

I have added admob reward video to my app. Everything is ok with admob. However, I can't update live label after watching rewarded video. If I go another scene and come back, it is updated and shows new value.
//GameViewController.swift
 func rewardBasedVideoAd(_ rewardBasedVideoAd: GADRewardBasedVideoAd,
                            didRewardUserWith reward: GADAdReward) {
        print("Reward received with currency: \(reward.type), amount \(reward.amount).")

        GameData.shared.lives = GameData.shared.lives + 1
        UserDefaults.standard.set(GameData.shared.lives, forKey: "lives")
        UserDefaults.standard.synchronize()
    }

//MainScene.swift
var lives = UserDefaults.standard.integer(forKey: "lives") {
        didSet{
            livesLabel?.text = "\(lives)"
        }
    }

//

A:

My personal recommendation would be to establish a connection via computed properties with the scene:
class ViewController : UIViewController
{
    var mainScene : MainScene? { return (self.view as SKView?).scene as? MainScene}
    var lives : Int
    {
        get
        {
            return mainScene?.lives ?? 0
        }
        set
        {
           mainScene?.lives = newValue
           //perhaps do some error handling if mainscne is nil
        }
   }
}

Then in your main scene, you control how lives writes to userdefaults
class MainScene : SKScene
{
    private var _lives : Int?
    var lives : Int
    {
        get
        {
            _lives = _lives ?? UserDefaults.standard.integer(forKey: "lives")
            return _lives!
        }
        set
        {
            _lives = newValue
            UserDefaults.standard.set(_lives, forKey: "lives")
            UserDefaults.standard.synchronize()
            livesLabel?.text = "\(_lives)"
        }
    }
}

Finally to use it, you would do:
 func rewardBasedVideoAd(_ rewardBasedVideoAd: GADRewardBasedVideoAd,
                        didRewardUserWith reward: GADAdReward) {
    print("Reward received with currency: \(reward.type), amount \(reward.amount).")

    lives += 1
}

We can then avoid having to deal with global variables, which means less opportunity for errors and bugs

