繁体   English   中英

如何从 NSObject 访问 SwiftUI 环境 object?

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

当通过从 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'":

    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)
}
}

我已经尝试将 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).")
    }
    
}
}

有什么办法可以从 NSObject 更改变量?

这里的settings只是一个参考,所以您可以通过 arguments 传递它

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

在你的代表

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