是否有可能使用swift来调整deinit。如果是,那么如何实现这一点

时间:2016-11-17 05:44:58

标签: ios swift swizzling deinit

我想在我的项目中的UIViewController的每个子类中以deinit记录一些语句。我不想在每个视图控制器子类中复制/粘贴相同的行。

2 个答案:

答案 0 :(得分:3)

有一种方法可以达到这个目的。

你无法调动deinit,但你可以调动另一种方法,例如viewDidLoad,以associatedObject来毒害这个类。当viewController释放时,关联对象也会被解除分配。

final class Deallocator {

    var closure: () -> Void

    init(_ closure: @escaping () -> Void) {
        self.closure = closure
    }

    deinit {
        closure()
    }
}

private var associatedObjectAddr = ""

extension UIViewController {

    @objc fileprivate func swizzled_viewDidLoad() {
        let deallocator = Deallocator { print("Deallocated") }
        objc_setAssociatedObject(self, &associatedObjectAddr, deallocator, .OBJC_ASSOCIATION_RETAIN)
        swizzled_viewDidLoad()
    }

    static let classInit: Void = {
        let originalSelector = #selector(viewDidLoad)
        let swizzledSelector = #selector(swizzled_viewDidLoad)
        let forClass: AnyClass = UIViewController.self
        let originalMethod = class_getInstanceMethod(forClass, originalSelector)
        let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
        method_exchangeImplementations(originalMethod!, swizzledMethod!)
    }()
}

<强>买者

当取消分配viewController时,闭包不会被称为 ,因为在 viewController被完全取消分配后Deallocator被解除分配

答案 1 :(得分:0)

我更新了间接调用swift代码的解决方案,可能不是最好的方法。您可以使用NSSelectorFromString获得取消初始化的实现,并通过扩展扩展实现,并通过桥接调用快速代码。尝试使用此代码可能会帮助您:

//
//  UIViewController+ExtendDealloc.h
//  extension
//
//  Created by Amir Kamali on 26/2/19.
//  Copyright © 2019 Amir Kamali. All rights reserved.
//

@import UIKit;

@interface UIViewController (ExtendDealloc)


@end

.m文件:

//
//  UIViewController+ExtendDealloc.m
//  extension
//
//  Created by Amir Kamali on 26/2/19.
//  Copyright © 2019 Amir Kamali. All rights reserved.
//

#import "UIViewController+ExtendDealloc.h"
#import <objc/runtime.h>
#import "test_objc-Swift.h"


@implementation UIViewController (ExtendDealloc)

#pragma mark - Swizzle Dealloc
+ (void)load {
    // is this the best solution?
    method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"dealloc")),
                                   class_getInstanceMethod(self.class, @selector(swizzledDealloc)));
}

- (void)swizzledDealloc {
    [CustomBehaviorHandler printMe];
    [self swizzledDealloc];
}

@end

快捷代码:

import Foundation
import UIKit

class CustomBehaviorHandler:NSObject {

    @objc
    static func printMe() {
        print("deinitializing ....")
    }
}

[已更新]