簡體   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