开发者

Objective-C, how can i hook up a method in another class

Objective-C keeps all its 开发者_如何学编程methods in a huge hashtable - so shouldn't it possible to patch this table and replace an existing method with my own patched method (which then calls the original)?

I need a way to hook up the NSWindow KeyUp method in a window which i can't subclass cause it's already created.

I need some code or at least some keywords i can use for further searching.


You should NOT swizzle methods for this. This is deprecated behavior. This will affect ALL windows in your app not just the one you wanted to change. However, what you should do instead is to subclass NSWindow already and then change the class of that window at runtime. This can be done using this runtime function:

Class object_setClass(id object, Class cls)

Reference is here: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/doc/uid/TP40001418-CH1g-SW12

Your code should then look like this:

object_setClass(theWindow, [MyWindowSubclass class]);

On problem you might experience is that window already being a subclass of NSWindow. If that's the case there are more complicated ways to achieve this. You can construct a class dynamically at runtime. Here's some more code. Given that window is the target window:

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);

I'm not totally sure this does not change the implementation of the superclass. The documentation is a bit unspecific about it. However, you should still try it. If it does not work, replace the second and third line by this one:

class_replaceMethod(newWindowClass, @selector(keyUp:), new_NSWindow_keyUp_, "v@:@");

In any case you need to define the new Method implementation. It could look like that (partially by KennyTM):

void new_NSWindow_keyUp_(NSWindow* self, SEL _cmd, NSEvent* evt) {
  [super keyUp: evt];
  ... // do your changes
}


Of course it is possible. In fact, you don't even need to look into the hash table — there's standard API for this.

For example:

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_);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜