Reputation: 2465
I am attempting to implement a solution from How to set canBecomeKeyWindow? Into my native C application using Objective-C runtime (The app is already written with objective C Runtime). Is there a way to create a subclass purely in Objective-C Runtime?
Right now I just create NSWindow
object but need to be able to create my own so I can override the function specified in that question.
objc_msgSend((id)objc_getClass("NSWindow"), sel_registerName("alloc"));
Upvotes: 0
Views: 372
Reputation: 1867
The signature of can_become_key_window_true
is slightly incorrect. According to the documentation (https://developer.apple.com/documentation/objectivec/objective-c_runtime/imp?language=objc) the function should have at least two arguments: "self" and "_cmd". So the signature should be like:
static bool can_become_key_window_true(__unused id _self, __unused SEL _cmd) {
return true;
}
You could also use @encode
to construct the type encoding for the function.
char encoding[10]; // should be enough
snprintf(encoding, 10, "%s%s%s", @encode(BOOL), @encode(id), @encode(SEL));
... or you could get a method from UIWindow
and get its type encoding like:
Method m = class_getInstanceMethod(objc_lookUpClass("UIWindow"), sel_getUid("canBecomeKeyWindow"));
const char *encoding = method_getTypeEncoding(m);
And as you might have noticed you could use sel_getUid()
instead of sel_registerName
as you expect this selector to be already registered by this time (because you are about to override an existing method).
To allocate a new instance you could use
window = class_createInstance(__UIWindow);
Upvotes: 1
Reputation: 2465
Figured it out after a lot of code searching:
// Subclass NSWindow with overridden function
Class __NSWindow =
objc_allocateClassPair(objc_getClass("NSWindow"), "__NSWindow", 0);
class_addMethod(__NSWindow,
sel_registerName("canBecomeKeyWindow"),
(IMP)can_become_key_window_true, "B@:");
objc_registerClassPair(__NSWindow);
// Allocate a new __NSWindow
window = objc_msgSend((id)__NSWindow, sel_registerName("alloc"));
And then can_become_key_window_true
is defined as:
static bool can_become_key_window_true() {
return true;
}
I use objc_allocateClassPair to subclass the object and return a Class
of that object. Then I use class_addMethod to override the method canBecomeKeyWindow
. And finally use objc_registerClassPair to register my new class before using it as I would a normal NSWindow
.
Upvotes: 0