как поменять didReceiveRemoteNotification из AppDelegate из фреймворка

Я разрабатываю фреймворк для приложений iOS (под). Я хочу выпить

application(_:didReceiveRemoteNotification:fetchCompletionHandler:)

с методом, определенным в моей структуре. это мой код:

class MyClass {
    @objc
    func myCustomizedMethod(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // my code
    }

    private func swizzleDidReceiveRemoteNotification() {
        guard let appDelegateClass = object_getClass(UIApplication.shared.delegate) else { return }

        let originalSelector = #selector((appDelegateClass as! UIApplicationDelegate).application(_:didReceiveRemoteNotification:fetchCompletionHandler:))
        let swizzledSelector = #selector(MyClass.self.myCustomizedMethod(_:didReceiveRemoteNotification:fetchCompletionHandler:))

        guard let originalMethod = class_getInstanceMethod(appDelegateClass, originalSelector) else { return }
        guard let swizzledMethod = class_getInstanceMethod(MyClass.self, swizzledSelector) else { return }

        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
}

но когда я запускаю свой код, кажется, что originalMethod имеет значение nil и поэтому

class_getInstanceMethod(appDelegateClass, originalSelector)

возвращает ноль. что я делаю не так? (учтите, что у меня нет доступа к AppDelegate, потому что, как я уже сказал, я разрабатываю фреймворк)

2 ответа

Решение

Это код, который у меня сработал:

class MyClass {
    @objc
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // my code
    }

    private func swizzleDidReceiveRemoteNotification() {
        let appDelegate = UIApplication.shared.delegate
        let appDelegateClass = object_getClass(appDelegate)

        let originalSelector = #selector(UIApplicationDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:))
        let swizzledSelector = #selector(MyClass.self.application(_:didReceiveRemoteNotification:fetchCompletionHandler:))

        guard let swizzledMethod = class_getInstanceMethod(MyClass.self, swizzledSelector) else {
            return
        }

        if let originalMethod = class_getInstanceMethod(appDelegateClass, originalSelector)  {
            // exchange implementation
            method_exchangeImplementations(originalMethod, swizzledMethod)
        } else {
            // add implementation
            class_addMethod(appDelegateClass, swizzledSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        }
    }
}

Этот метод не является обязательным. Если он не существует, вам нужно добавить его вместо того, чтобы расширять реализацию.

Другие вопросы по тегам