【问题标题】:About the callback of SKStoreReviewController.requestReview()关于 SKStoreReviewController.requestReview() 的回调
【发布时间】:2019-01-02 15:19:36
【问题描述】:

如果显示从视图控制器启动的评论弹出窗口,由于缺少SKStoreReviewController.requestReview() 的回调函数,当弹出窗口被关闭时,无法将窗口焦点切换回视图控制器。

当评论弹出窗口被关闭时,我想拨打becomeFirstResponder() 的电话。有什么想法吗?

有没有办法扩展 SKStoreReviewController 并以某种方式添加回调?

【问题讨论】:

标签: swift becomefirstresponder skstorereviewcontroller


【解决方案1】:

警告这可能会在某个时候中断。

第 1 步:将此代码添加到您的 didFinishLaunchingWithOptions

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    let windowClass: AnyClass = UIWindow.self

    let originalSelector: Selector = #selector(setter: UIWindow.windowLevel)
    let swizzledSelector: Selector = #selector(UIWindow.setWindowLevel_startMonitor(_:))

    let originalMethod = class_getInstanceMethod(windowClass, originalSelector)
    let swizzledMethod = class_getInstanceMethod(windowClass, swizzledSelector)

    let didAddMethod = class_addMethod(windowClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))

    if didAddMethod {
        class_replaceMethod(windowClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
    } else {
        method_exchangeImplementations(originalMethod!, swizzledMethod!)
    }

    return true
}

第 2 步:添加此类

class MonitorObject: NSObject {
    weak var owner: UIWindow?

    init(_ owner: UIWindow?) {
        super.init()
        self.owner = owner
        NotificationCenter.default.post(name: UIWindow.didBecomeVisibleNotification, object: self)
    }

    deinit {
         NotificationCenter.default.post(name: UIWindow.didBecomeHiddenNotification, object: self)
    }
}

第 3 步:添加此 UIWindow 扩展

private var monitorObjectKey = "monitorKey"
private var partialDescForStoreReviewWindow = "SKStore"

extension UIWindow {
    // MARK: - Method Swizzling
    @objc func setWindowLevel_startMonitor(_ level: Int) {
        setWindowLevel_startMonitor(level)

        if description.contains(partialDescForStoreReviewWindow) {
             let monObj = MonitorObject(self)
             objc_setAssociatedObject(self, &monitorObjectKey, monObj, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

第 4 步:将此添加到您想要的控制器的 ViewDidLoad 中

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    NotificationCenter.default.addObserver(self, selector: #selector(windowDidBecomeHiddenNotification(_:)), name: UIWindow.didBecomeHiddenNotification, object: nil)
}

第 5 步:为通知添加回调并检查关联对象是否匹配

@objc func windowDidBecomeHiddenNotification(_ notification: Notification?) {
    if notification?.object is MonitorObject {
        print("hello")
    }
}

现在,当审阅对话框关闭时,会触发通知并调用 'print("hello")。

【讨论】:

  • 可能是因为它被认为是相当 hacky 的代码,并且可以进一步清理,或者我没有很好地解释它。
  • 没关系。我认为不存在 unhacky 代码,因为 Apple 文档没有说明回调。感谢您的努力!
  • 是的,希望他们能在未来修复它
  • 不在 iOS 13 上工作,但在 iOS 12 上工作,对 IOS 13 有什么想法吗?
  • 今晚或明天我将研究 iOS 13。首先想到的是检查窗口描述是否已更改(步骤 3 中的 partialDescForStoreReviewWindow)。只需设置一个断点并在打开查看窗口时检查描述是否包含该字符串。如果没有,你知道该怎么做。
【解决方案2】:

有时 iOS 应用会丢失响应者链,例如上面显示 StoreKit 提示的示例。我们可以做的是检测UIApplication.sendAction中的此类事件,并通过becomeFirstResponder重新激活第一响应者链。 UIKit 将重新建立第一响应者链,我们可以重新发送相同的事件。

class MyApplication: UIApplication {

    func reactivateResponderChainWhenFirstResponderEventWasNotHandled() {
        becomeFirstResponder()
    }

    override func sendAction(_ action: Selector, to target: Any?, from sender: Any?, for event: UIEvent?) -> Bool {
        let wasHandled = super.sendAction(action, to: target, from: sender, for: event)
        if wasHandled == false, target == nil {
            reactivateResponderChainWhenFirstResponderEventWasNotHandled()
            return super.sendAction(action, to: target, from: sender, for: event)
        }
        return wasHandled
    }
}

这适用于我在 iOS 13 上,不需要任何私有 API 访问。

【讨论】:

    猜你喜欢
    • 2016-01-18
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多