Я хочу регистрировать некоторые операторы в deinit в каждом подклассе UIViewController в моем проекте. Я не хочу копировать/вставлять одни и те же строки в каждый подкласс контроллера представления.
Можно ли прокачать дейнит с помощью swift. если да то как этого добиться
comment
Вы говорите только о настраиваемых контроллерах представления, которые вы создаете, или вам также нужно это для стандартных контроллеров представления, предоставляемых iOS SDK?
- person rmaddy   schedule 17.11.2016
comment
В настоящее время мне нужны настраиваемые контроллеры представления, но я беспокоюсь о том, чтобы проверить доступность swizzle для deint.
- person ZaEeM ZaFaR   schedule 17.11.2016
comment
Вы нашли какие-то решения?
- person Paul   schedule 26.05.2017
comment
Все еще не найдено. @Павел
- person ZaEeM ZaFaR   schedule 06.06.2017
comment
Ааааааа, нам это нужно!
- person ullstrm   schedule 15.06.2017
Ответы (2)
Есть способ добиться этого.
Вы не можете использовать 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, так как Deallocator
освобождается после полного освобождения viewController.
person
farzadshbfn
schedule
13.06.2018
Я обновил решение, которое косвенно вызывает быстрый код, возможно, не самое лучшее. Вы можете получить реализацию de-init с помощью NSSelectorFromString
и расширить реализацию с помощью swizzling и вызвать быстрый код через мост. Попробуйте этот код, который может вам помочь:
//
// 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
.м файл:
//
// 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 ....")
}
}
[ОБНОВЛЕНО]
person
Amir.n3t
schedule
26.02.2019
Вопрос для Swift, можете ли вы также добавить пример использования Swift?
- person Cristik; 26.02.2019
Не удалось найти прямого решения, однако я обновил приведенный выше код, который косвенно вызывает быстрые коды.
- person Amir.n3t; 26.02.2019
Вы больше не можете вызывать +load для любого расширения (здесь
UIViewController (ExtendDealloc)
), начиная с Xcode 10.2 beta 3.
- person Cœur; 26.02.2019