Skip to content

Swizzling for automatic check #2

@jazzbox

Description

@jazzbox

Hi, just my 2 cents, because I don‘t want to manually add viewWillDisappear(_:) to all of my view controllers I swizzled the UIViewController method for the check:

import UIKit

private func swizzle(forClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) {
    let originalMethod = class_getInstanceMethod(forClass, originalSelector)
    let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
    method_exchangeImplementations(originalMethod, swizzledMethod)
}

extension UIViewController {
    
    class func swizzleForDeallocationCheck() {
        #if DEBUG
            swizzle(forClass: self, originalSelector: #selector(viewWillDisappear(_:)), swizzledSelector: #selector(swizzledViewWillDisappear(animated:)))
        #endif
    }
    
    @objc
    private func swizzledViewWillDisappear(animated: Bool) {
        #if DEBUG
            self.swizzledViewWillDisappear(animated: animated)
            
            //print("viewWillDisappear: class \(type(of: self))")
            
            let delay: TimeInterval = 2.0
            
            // We don't check `isBeingDismissed` simply on this view controller because it's common
            // to wrap a view controller in another view controller (e.g. a stock UINavigationController)
            // and present the wrapping view controller instead.
            if isMovingFromParentViewController || rootParentViewController.isBeingDismissed {
                let type = type(of: self)
                let disappearanceSource: String = isMovingFromParentViewController ? "removed from its parent" : "dismissed"
                
                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: { [weak self] in
                    assert(self == nil, "\(type) not deallocated after being \(disappearanceSource)")
                })
            }
        #endif
    }
    
    private var rootParentViewController: UIViewController {
        var root = self
        while let parent = root.parent {
            root = parent
        }
        return root
    }

}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        UIViewController.swizzleForDeallocationCheck()
        // ...
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions