【问题标题】:Swizzling of a function - and function known at runtime onlySwizzling 函数 - 仅在运行时已知的函数
【发布时间】:2016-05-05 05:23:50
【问题描述】:

我想在 Objective-c 中调配一个函数。问题是 - 我知道只在运行时需要调整的函数。现在代码中的不同方法会有不同的返回类型、输入参数等。

我应该如何编写一个(通用)代码,如果给定它所属的函数和类的名称,我可以创建一个块,然后使用 imp_implementationWithBlock 创建 IMP,然后用这个新创建的 IMP 调动原始方法.

【问题讨论】:

    标签: ios objective-c method-swizzling libffi


    【解决方案1】:

    您可以使用NSSelectorFromString() 动态查找选择器名称,然后执行混合。有很多助手,所以我不需要重复确切的混乱逻辑。例如。如果您使用Aspects,代码可能如下所示:

    [_singleTapGesture aspect_hookSelector:NSSelectorFromString(@"setState:") withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        NSLog(@"%@: %@", aspectInfo.instance, aspectInfo.arguments);
    } error:NULL];
    

    对于运行时调配,您应该确保您知道自己在做什么,并且如果选择器不存在,则优雅地失败。

    【讨论】:

    • 可以说,我有一个抛出异常的函数 foo。我想用一个 try-catch 块包围这个函数的主体。因此,我需要从这个函数 foo 中创建一个块,并且该块必须具有完全相同的签名。这个块将有一个try-catch,我将在它之间调用原始方法。之后,我会将原始代码混合到新块中。因此,对 foo 的任何进一步调用都将通过块中实现的 try-catch。我无法在运行时创建块,因为在编译时我不知道它的参数和返回类型。
    • Aspects 只提供 before、after 和代替 - 我需要用 try-catch 包围它,有没有办法使用 Aspects 来做到这一点?
    • 另外,示例中的这个块将如何将参数传递给函数?我们需要在 usingBlock 中提供它。
    • 您可以使用替换选项轻松包装它,然后调用原始实现 - 请参阅 AspectInfo 和 repo 中的自述文件。
    猜你喜欢
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 2018-10-02
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多