3

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

4

2 回答 2

8

有一种方法可以实现这一点。

你不能调配deinit,但你可以调配另一种方法,比如viewDidLoadassociatedObject. 当 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后才被释放。

于 2018-06-13T11:54:11.877 回答
0

我更新了间接调用swift代码的解决方案,可能不是最好的。NSSelectorFromString您可以使用swizzling 和扩展实现来获得 de-init 实现,并通过桥接调用 swift 代码。试试这个可能对你有帮助的代码:

//
//  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

SWIFT代码:

import Foundation
import UIKit

class CustomBehaviorHandler:NSObject {

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

[更新]

于 2019-02-26T04:53:04.437 回答