简体   繁体   English

如何从 NSObject 访问 SwiftUI 环境 object?

[英]How can I access an SwiftUI environment object from an NSObject?

I'm trying to increment the variable adsWatched by 1 when an ad is dismissed by changing the environment object from a UIViewController and passing it to a SwiftUI view.当通过从 UIViewController 更改环境 object 并将其传递给 SwiftUI 视图来消除广告时,我试图将变量 adsWatched 增加 1。 I've tried putting an environment object in my NSObject class AdManager, which contains the function I want to change the environment object in, but I get the error message "Unknown attribute 'EnvironmentObject'": I've tried putting an environment object in my NSObject class AdManager, which contains the function I want to change the environment object in, but I get the error message "Unknown attribute 'EnvironmentObject'":

    public protocol AdManagerRewardDelegate{
func rewardAdGiveRewardToUser(type:String, amount: NSDecimalNumber)
func rewardAdFailedToLoad()
func rewardAdDidReceive(
    rewardViewController: UIViewController?,
    rewardedAd: GADRewardedAd?,
    delegate: AdManager
)
func rewardAdDidOpen()
func rewardAdDidClose()
func rewardAdFailedToPresent()
}


//default implementation AdManagerRewardDelegate
public extension AdManagerRewardDelegate{
func rewardAdGiveRewardToUser(type:String, amount: NSDecimalNumber) {}
func rewardAdFailedToLoad() {}
func rewardAdDidReceive(
    rewardViewController: UIViewController?,
    rewardedAd: GADRewardedAd?,
    delegate: AdManager
) {
    if rewardedAd?.isReady == true {
        if let rewardViewController = rewardViewController {
            rewardedAd?.present(fromRootViewController: rewardViewController, delegate: delegate)
        }
    }
}
func rewardAdDidOpen() {}
func rewardAdDidClose() {}
func rewardAdFailedToPresent() {}
}

public class AdManager: NSObject {
public static let shared = AdManager()
public var ADS_DISABLED = false

public var delegateReward: AdManagerRewardDelegate?

private var viewController:UIViewController?
private var bannerViewContainer:UIView?
private var rewardViewController:UIViewController?

var interestial:GADInterstitial?
private var testDevices:[String] = [""]


private var rewardedAd: GADRewardedAd?

let borderSizeBetweenBannerAndContent:CGFloat = 5

@EnvironmentObject var settings: UserSettings


public override init() {
    super.init()
}

public func configureWithApp(){
    GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = testDevices
}

public func setTestDevics(testDevices: [String]){
    self.testDevices = testDevices
    self.testDevices += [kGADSimulatorID as! String ] //all simulator
}

private func getGADRequest() -> GADRequest{
    let request = GADRequest()
    return request
}



// MARK:- Reward Video Ads
public func loadAndShowRewardAd(_ adUnit: String, viewController: UIViewController){
    self.rewardViewController = viewController
    
    rewardedAd = GADRewardedAd(adUnitID: adUnit)
    rewardedAd?.load(getGADRequest()) { error in
      if let error = error {
        // Handle ad failed to load case.
        print("Reward based video ad failed to load. \(error.debugDescription)")
        self.delegateReward?.rewardAdFailedToLoad()
      } else {
        // Ad successfully loaded.
        print("Reward based video ad is received.")
        self.delegateReward?.rewardAdDidReceive(
            rewardViewController: self.rewardViewController,
            rewardedAd: self.rewardedAd,
            delegate: self
        )
      }
    }
}
}


// MARK:- GADRewardBasedVideoAdDelegate
extension AdManager : GADRewardedAdDelegate {
public func rewardedAdDidPresent(_ rewardedAd: GADRewardedAd) {
    print("Rewarded ad presented.")
    delegateReward?.rewardAdDidOpen()
}

public func rewardedAd(_ rewardedAd: GADRewardedAd, didFailToPresentWithError error: Error) {
    print("Rewarded ad failed to present.")
    delegateReward?.rewardAdFailedToPresent()
}

public func rewardedAdDidDismiss(_ rewardedAd: GADRewardedAd) {
    print("Rewarded ad dismissed.")
    // i want to increase adsWatched by 1 here
    settings.adsWatched += 1
    delegateReward?.rewardAdDidClose()
}

public func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) {
    print("Reward received with currency: \(reward.type), amount \(reward.amount).")
    delegateReward?.rewardAdGiveRewardToUser(type: reward.type, amount: reward.amount)
}
}

I've tried passing the object to it from my view controller, but I get the error message: "Instance member 'environmentObject' of type 'View' cannot be used on instance of nested type 'Ads.ViewController'" for this:我已经尝试将 object 从我的视图 controller 传递给它,但我收到错误消息:“实例成员 'view' 类型的 'environmentObject' 不能用于嵌套类型 'Ads.ViewController' 的实例”:

    struct Ads: UIViewControllerRepresentable {
    
    @EnvironmentObject var settings: UserSettings
    
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    

typealias UIViewControllerType = UIViewController
    

func makeUIViewController(context: Context) -> UIViewController {
    return ViewController()
}

func updateUIViewController(_ uiView: UIViewController, context: Context) {
}

class ViewController: UIViewController, GADRewardedAdDelegate, AdManagerRewardDelegate {
    
var rewardedAd: GADRewardedAd?
    
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    @EnvironmentObject var settings: UserSettings
    
override func viewDidLoad() {
super.viewDidLoad()
        
    AdManager.shared.loadAndShowRewardAd(AdIds.rewarded.rawValue, viewController: self, environmentObject(settings))
    // error messages here^: "Extra argument in call","Instance member 'environmentObject' of type 'View' cannot be used on instance of nested type 'Ads.ViewController'"
    AdManager.shared.delegateReward = self
    }
    

    func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) {
      print("Reward received: \(reward.type), amount \(reward.amount).")
    }
    
}
}

Is there any way I can change the variable from an NSObject?有什么办法可以从 NSObject 更改变量?

The settings here is just a reference so you can pass it via arguments这里的settings只是一个参考,所以您可以通过 arguments 传递它

public func loadAndShowRewardAd(_ adUnit: String, viewController: UIViewController,
                                settings: UserSettings) {
    self.rewardViewController = viewController
    // ... other code
}

and in your representable在你的代表

struct Ads: UIViewControllerRepresentable {

    @EnvironmentObject var settings: UserSettings
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>


    typealias UIViewControllerType = UIViewController


    func makeUIViewController(context: Context) -> UIViewController {
        return ViewController(settings: settings, mode: presentationMode)
    }

    func updateUIViewController(_ uiView: UIViewController, context: Context) {
    }

    class ViewController: UIViewController, GADRewardedAdDelegate, AdManagerRewardDelegate {

        var rewardedAd: GADRewardedAd?
        var presentationMode: Binding<PresentationMode>
        var settings: UserSettings

        init(settings: UserSettings, mode: Binding<PresentationMode>) {
            self.settings = settings
            self.presentationMode = mode
        }

        override func viewDidLoad() {
            super.viewDidLoad()

            AdManager.shared.loadAndShowRewardAd(AdIds.rewarded.rawValue, viewController: self, settings: settings)
            // error messages here^: "Extra argument in call","Instance member 'environmentObject' of type 'View' cannot be used on instance of nested type 'Ads.ViewController'"
            AdManager.shared.delegateReward = self
        }


        func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) {
            print("Reward received: \(reward.type), amount \(reward.amount).")
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM