我可以在UIViewController中扩展viewWillAppear吗?

时间:2016-11-17 15:42:40

标签: swift

我正在寻找一种方法来扩展UIViewController类中函数viewWillAppear的实现,以使它在每次调用此函数时打印调用的视图的类名。

我知道它不可能覆盖扩展中的函数,所以我想知道是否有办法做这样的事情。

2 个答案:

答案 0 :(得分:2)

好的,找到这个http://nshipster.com/swift-objc-runtime/之后我尝试了类似的东西,可以达到预期的效果。

代码如下:

extension UIViewController {
public override class func initialize() {
    struct Static {
        static var token: dispatch_once_t = 0
    }

    // make sure this isn't a subclass
    if self !== UIViewController.self {
        return
    }

    dispatch_once(&Static.token) {
        let originalSelector = #selector(UIViewController.viewWillAppear(_:))
        let swizzledSelector = #selector(UIViewController.nsh_viewWillAppear(_:))

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

        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

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

// MARK: - Method Swizzling

func nsh_viewWillAppear(animated: Bool) {
    self.nsh_viewWillAppear(animated)
    NSLog("viewWillAppear: \(self)")
}
}

答案 1 :(得分:0)

Swift 5

@objc func newViewWillAppear(_ animated: Bool) {
    self.newViewWillAppear(animated) //Incase we need to override this method
    let viewControllerName = String(describing: type(of: self)).replacingOccurrences(of: "ViewController", with: "", options: .literal, range: nil)
    print("Swizzled viewWillAppear", viewControllerName)
}

static func swizzleViewWillAppear() {
    //Make sure This isn't a subclass of UIViewController, So that It applies to all UIViewController childs
    if self != UIViewController.self {
        return
    }
    let _: () = {
        let originalSelector = #selector(UIViewController.viewWillAppear(_:))
        let swizzledSelector = #selector(UIViewController.newViewWillAppear(_:))
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        method_exchangeImplementations(originalMethod!, swizzledMethod!);
    }()
}

然后在 AppDelegate 上:

UIViewController.swizzleViewWillAppear()