Swizzling UIView.init в Swift выдает фатальную ошибку

Я пытаюсь выпить UIView.init и его многочисленные форм-факторы, такие как initWithFrame, initWithCoder вместе с обжариванием dealloc функция.

Моя проблема в том, что всякий раз, когда я пытаюсь создать ссылку на функцию init, я получаю нулевой результат, а затем мое приложение вылетает (потому что я принудительно разворачивал во время отладки). Я добавил операторы защиты, чтобы избежать сбоев, однако теперь я просто попадаю в свой оператор возврата и не могу получить ссылку на селектор, вызывающий init. Мой код ниже. Любая помощь о том, как переключить эти функции, будет принята с благодарностью.

      // MARK: - Swizzling
internal extension UIView {
    @objc
    private class func swizzledInitWithFrame(frame: CGRect) -> UIView {
        let view = swizzledInitWithFrame(frame: frame)
        view.refreshDebugBorders()
        view.registerForDebugBorderNotifications()
        return view
    }

    @objc
    private class func swizzledInitWithCoder(coder: NSCoder) -> UIView {
        let view = swizzledInitWithCoder(coder: coder)
        view.refreshDebugBorders()
        view.registerForDebugBorderNotifications()
        return view
    }

    @objc
    private class func swizzledDealloc() {
        NotificationCenter.default.removeObserver(self)
    }

    class func swizzleDefaultUIView() {
        guard self == UIView.self else { return }
        swizzleInitWithFrame()
        swizzleInitWithCoder()
        swizzleDealloc()
    }

    private class func swizzleInitWithFrame() {
        let defaultSelector = #selector(UIView.init(frame:))
        let swizzledSelector = #selector(UIView.swizzledInitWithFrame(frame:))
        guard let defaultMethod = class_getClassMethod(self, defaultSelector) else {
            return
        }
        guard let swizzledMethod = class_getClassMethod(self, swizzledSelector) else {
            return
        }
        let didAddMethod = class_addMethod(self,
                                           defaultSelector,
                                           method_getImplementation(swizzledMethod),
                                           method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self,
                                swizzledSelector,
                                method_getImplementation(defaultMethod),
                                method_getTypeEncoding(defaultMethod))
        } else {
            method_exchangeImplementations(defaultMethod,
                                           swizzledMethod)
        }
    }

    private class func swizzleInitWithCoder() {
        let defaultSelector = #selector(UIView.init(coder:))
        let swizzledSelector = #selector(UIView.swizzledInitWithCoder(coder:))
        guard let defaultMethod = class_getClassMethod(self, defaultSelector) else {
            return
        }
        guard let swizzledMethod = class_getClassMethod(self, swizzledSelector) else {
            return
        }
        let didAddMethod = class_addMethod(self,
                                           defaultSelector,
                                           method_getImplementation(swizzledMethod),
                                           method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self,
                                swizzledSelector,
                                method_getImplementation(defaultMethod),
                                method_getTypeEncoding(defaultMethod))
        } else {
            method_exchangeImplementations(defaultMethod,
                                           swizzledMethod)
        }
    }
    
    private class func swizzleDealloc() {
        let defaultSelector = #selector(UIVIew.NSSelectorFromString("dealloc"))
        let swizzledSelector = #selector(UIView.swizzledDealloc)
        guard let defaultMethod = class_getClassMethod(self, defaultSelector) else {
            return
        }
        guard let swizzledMethod = class_getClassMethod(self, swizzledSelector) else {
            return
        }
        let didAddMethod = class_addMethod(self,
                                           defaultSelector,
                                           method_getImplementation(swizzledMethod),
                                           method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self,
                                swizzledSelector,
                                method_getImplementation(defaultMethod),
                                method_getTypeEncoding(defaultMethod))
        } else {
            method_exchangeImplementations(defaultMethod,
                                           swizzledMethod)
        }
    }
}

0 ответов

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