我正试图实现一个解决方案,从 如何设置canBecomeKeyWindow? 在我的本机C应用程序中使用Objective-C运行时(应用程序已经用Objective C Runtime写好了),如何设置canBecomeKeyWindow?有没有办法在Objective-C Runtime中创建一个纯粹的子类?
现在我只是创建了 NSWindow
对象,但需要能够创建我自己的对象,以便我可以覆盖该问题中指定的函数。
objc_msgSend((id)objc_getClass("NSWindow"), sel_registerName("alloc"));
的签名 can_become_key_window_true
是略微错误的。根据文件(https:/developer.apple.comdocumentationobjectivecobjective-c_runtimeimp?语言=objc。)函数应该至少有两个参数。"self "和"_cmd"。所以签名应该是这样的。
static bool can_become_key_window_true(__unused id _self, __unused SEL _cmd) {
return true;
}
你也可以用 @encode
来构造函数的类型编码。
char encoding[10]; // should be enough
snprintf(encoding, 10, "%s%s%s", @encode(BOOL), @encode(id), @encode(SEL));
... 或者你可以从 UIWindow
并得到它的类型编码,如。
Method m = class_getInstanceMethod(objc_lookUpClass("UIWindow"), sel_getUid("canBecomeKeyWindow"));
const char *encoding = method_getTypeEncoding(m);
你可能已经注意到,你可以用 sel_getUid()
而不是 sel_registerName
因为你希望这个选择器此时已经被注册了(因为你即将覆盖一个现有的方法)。
要分配一个新的实例,你可以使用
window = class_createInstance(__UIWindow);
经过大量的代码搜索,弄明白了。
// 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"));
然后... can_become_key_window_true
被定义为。
static bool can_become_key_window_true() {
return true;
}
我使用 objc_allocateClassPair 的子类,并返回一个 Class
的对象。然后我用 class_addMethod 覆盖该方法 canBecomeKeyWindow
. 最后使用 objc_registerClassPair 注册我的新班级,然后再使用它,就像我使用一个普通的 NSWindow
.