我在NSObject上有一个类别,它应该有一些东西。当我在一个对象上调用它时,我想覆盖它的dealloc方法来做一些清理。
我想用方法swizzling来实现它,但是不知道怎么做。我找到的唯一的例子是如何替换整个类的方法实现(在我的例子中,它会覆盖所有NSObjects的dealloc-我不想这样做)。
我想覆盖特定NSObject示例的dealloc方法。
@interface NSObject(MyCategory)
-(void)test;
@end
@implementation NSObject(MyCategory)
-(void)newDealloc
{
// do some cleanup here
[self dealloc]; // call actual dealloc method
}
-(void)test
{
IMP orig=[self methodForSelector:@selector(dealloc)];
IMP repl=[self methodForSelector:@selector(newDealloc)];
if (...) // 'test' might be called several times, this replacement should happen only on the first call
{
method_exchangeImplementations(..., ...);
}
}
@end
字符串
4条答案
按热度按时间jhdbpxl91#
你不能真正做到这一点,因为对象没有自己的方法表。只有类才有方法表,如果你改变这些方法表,它会影响该类的每个对象。不过有一个简单的方法:在运行时将对象的类更改为动态创建的子类。这种技术,也称为isa-swizzling,被Apple用来实现自动KVO。
这是一个强大的方法,它有它的用途。但对于您的情况,有一个更简单的方法使用关联对象。基本上,您使用
objc_setAssociatedObject
将另一个对象关联到您的第一个对象,该对象在其dealloc
中进行清理。您可以在this blog post on Cocoa is my Girlfriend中找到更多细节。6ovsh4lw2#
方法选择是基于对象示例的 class 的,因此方法混合会影响同一个类的所有示例-正如您所发现的。
但是你可以改变一个示例的类,但是你必须小心!这里是大纲,假设你有一个类:
字符串
现在,如果你想改变
doSomething
的某些示例的行为,你首先要定义一个子类:型
现在你可以清楚地创建
MyFancyObject
的示例,但是我们需要做的是将MyPlainObject
的一个 * 预先存在的 * 示例变成一个MyFancyObject
,这样我们就可以获得新的行为。为此,我们可以混合类,将以下内容添加到MyFancyObject
:型
现在,对于任何
MyPlainClass
的 * 原始 * 示例,您可以切换为MyFancyClass
的行为,反之亦然:型
(一些)警告:
如果子类重写或添加方法,并添加
static
(类)变量,您可以仅这样做。你还需要一个子类来改变你想要改变的类的行为,你不能有一个单独的类来改变许多不同类的行为。
mcvgt66p3#
我做了一个swizzling API,它也具有特定于示例的swizzling功能。
它的工作原理是为您在运行时正在swizzling的特定示例创建一个动态子类。
vjrehmav4#
我做了一个工具来做这件事。https://github.com/623637646/SwiftHook
字符串
https://github.com/623637646/SwiftHook/blob/9d2d85a64059617f8272d01ff59c10ede7305a48/SwiftHookTests/SwiftAPITests/HookSpecificInstanceTests.swift#L254参考此单元测试。