Objective-C, how can I connect a method in another class

Objective-C stores all of its methods in a huge hash table - so should you not correct this table and replace the existing method with my own corrected method (which then calls the original)?

I need a way to hook up the NSWindow KeyUp method in a window that I cannot subclass because it is already created.

I need code or at least some keywords that I can use for further searches.

+3
source share
2 answers

Of course it is possible. In fact, you don’t even need to look at the hash table - there is a 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_); 
+2
source

You should not use swizzle methods for this. This is an outdated behavior. This will affect ALL windows in your application, not just what you would like to change. However, instead, you must subclass NSWindow instead, and then change the class of this window at run time. This can be done using this runtime function:

 Class object_setClass(id object, Class cls) 

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

Your code should look like this:

 object_setClass(theWindow, [MyWindowSubclass class]); 

For a problem that may arise, this window is already a subclass of NSWindow. If in this case there are more complex ways to achieve this. You can build the class dynamically at runtime. Here is another code. Given that the 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 entirely sure that this will not change the implementation of the superclass. The documentation is a bit non-specific. However, you should still try. If this does not work, replace the second and third line as follows:

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

In any case, you need to define a new implementation of the method. It might look like this (partially KennyTM):

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

All Articles