Objective-C将所有方法保存在一个巨大的哈希表中 - 所以不应该修补这个表并用我自己的修补方法(然后调用原始方法)替换现有方法吗?
我需要一种方法来将NSWindow KeyUp方法挂钩在一个窗口中,我无法将其子类化,因为它已经创建了。
我需要一些代码或至少一些我可以用来进一步搜索的关键字。
答案 0 :(得分:4)
你不应该为此调整方法。这是不推荐使用的行为。这将影响您应用中的所有窗口,而不仅仅是您想要更改的窗口。但是,您应该做的是将NSWindow子类化,然后在运行时更改该窗口的类。这可以使用此运行时函数来完成:
Class object_setClass(id object, Class cls)
您的代码应如下所示:
object_setClass(theWindow, [MyWindowSubclass class]);
在可能体验的问题上,该窗口已经是NSWindow的子类。如果是这种情况,有更复杂的方法来实现这一目标。您可以在运行时动态构造一个类。这是一些更多的代码。鉴于该窗口是目标窗口:
Class newWindowClass = objc_allocateClassPair([window class], "MyHackyWindowSubclass", 0);
Method upMethod = class_getInstanceMethod(newWindowClass, @selector(keyUp:));
method_setImplementation(upMethod, new_NSWindow_keyUp_);
object_setClass(window, newWindowClass);
我不完全确定这不会改变超类的实现。文档有点不明确。但是,你仍然应该尝试一下。如果它不起作用,请将第二行和第三行替换为:
class_replaceMethod(newWindowClass, @selector(keyUp:), new_NSWindow_keyUp_, "v@:@");
无论如何,您需要定义新的Method实现。它可能看起来像那样(部分来自KennyTM):
void new_NSWindow_keyUp_(NSWindow* self, SEL _cmd, NSEvent* evt) {
[super keyUp: evt];
... // do your changes
}
答案 1 :(得分:3)
当然有可能。实际上,您甚至不需要查看哈希表 - 这是标准的API。
例如:
typedef void (*NSWindow_keyUp__IMP)(NSWindow* self, SEL _cmd, NSEvent* evt);
static NSWindow_keyUp__IMP original_NSWindow_keyUp_;
void replaced_NSWindow_keyUp_(NSWindow* self, SEL _cmd, NSEvent* evt) {
NSLog(@"Entering keyUp:. self = %@, event = %@", self, evt);
original_NSWindow_keyUp_(self, _cmd, evt);
NSLog(@"Leaving keyUp:. self = %@, event = %@", self, evt);
}
...
Method m = class_getInstanceMethod([NSWindow class], @selector(keyUp:));
original_NSWindow_keyUp_ = method_setImplementation(m, replaced_NSWindow_keyUp_);