![](/img/trans.png)
[英]Property wrappers and SwiftUI environment: how can a property wrapper access the environment of its enclosing 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.