在Objective C Runtime中的子类化。

问题描述 投票:0回答:1

我正试图实现一个解决方案,从 如何设置canBecomeKeyWindow? 在我的本机C应用程序中使用Objective-C运行时(应用程序已经用Objective C Runtime写好了),如何设置canBecomeKeyWindow?有没有办法在Objective-C Runtime中创建一个纯粹的子类?

现在我只是创建了 NSWindow 对象,但需要能够创建我自己的对象,以便我可以覆盖该问题中指定的函数。

objc_msgSend((id)objc_getClass("NSWindow"), sel_registerName("alloc"));
c nswindow objective-c-runtime
1个回答
1
投票

的签名 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);

0
投票

经过大量的代码搜索,弄明白了。

        // 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.

© www.soinside.com 2019 - 2024. All rights reserved.