【问题标题】:Override method using runtime library使用运行时库覆盖方法
【发布时间】:2013-05-09 11:34:58
【问题描述】:

我需要覆盖- (void)viewWillAppear:(BOOL)animated,以便在此方法中添加NSLog(@"blabla") 的所有ViewController。 IE。在每次调用 viewWillAppear 调用实现 viewWillAppear + 我的 NSLog 消息的早期实现之后。是否可以?如果是的话,请给我一个建议。

目前我已经尝试过这段代码

@implementation RuntimeTest

IMP previusImp;
IMP newIMP;
- (void)ovverrideViewWillAppearInViewController:(Class)vcClass {
    newIMP = class_getMethodImplementation([self class], @selector(viewWillAppear:));
    Method viewWillAppearMethod = class_getInstanceMethod(vcClass, @selector(viewWillAppear:));
    previusImp = method_setImplementation(viewWillAppearMethod, newIMP);
}

- (void)viewWillAppear:(BOOL)animated {
    previusImp(self, @selector(viewWillAppear:), animated);
    NSLog(@"log2");
}

@end

那我有

@implementation IRViewController2

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"log");
}

@end

我的自定义 viewWillAppear 首先调用,然后从 IRViewController2 调用 viewWillAppear。在此之后,我的应用程序因 EXC_BAD_ACCESS 而崩溃。怎么了?

【问题讨论】:

  • 也许我说得不清楚。请查看更新后的问题。
  • 你应该发布你的崩溃日志,或者至少是其中的一部分。
  • 很遗憾,崩溃日志是清晰的。
  • 从应用程序中所有其他控制器继承的巫婆创建自定义视图控制器方法,当您调用 super viewwillappear 时,父方法中的 viewdidappear 将在您的子控制器中的 viewdidappear 之前被调用,只需添加一个父方法内部也是超级的

标签: iphone ios objective-c runtime objective-c-runtime


【解决方案1】:

如果你不能使用子类,因为你想全局使用它,但又不想丢失旧版本的方法(所以类别覆盖是不可能的),那么你需要swizzle away旧方法,放入你的新方法,然后调用旧方法...我过去曾使用名为 JRSwizzle 的东西来执行此操作,它可以轻松进行调配,而无需编写一堆运行时代码。

if (![self jr_swizzleMethod:@selector(originalInit) withMethod:@selector(init) error:&err])
{
    NSLog(@"unable to jr_swizzle methods, error: %@",err);
    exit(EXIT_FAILURE);
}
if (![self jr_swizzleMethod:@selector(init) withMethod:@selector(myInit) error:&err])
{
    NSLog(@"unable to jr_swizzle methods, error: %@",err);
    exit(EXIT_FAILURE);
}

那么您的-myInit 方法可以调用-originalInit 或您正在使用的任何方法。

【讨论】:

  • 可以这样做,它非常适合调试,但请不要在生产代码中这样做!
  • @bbum 不是我拥有或将要...但是对于为什么你不想在产品代码中这样做有一个硬性规定吗?我的意思是,只要旧版本被使用......也许一些依赖检查 _cmd 的方法会被破坏?
  • 因为——即使在调用原始实现时——您也在修改系统框架的实现细节。这不仅在应用商店 (IIRC) 中被禁止,而且很脆弱并且会导致维护问题。特别是,你指望内部行为保持你认为你观察到的任何常数。任何软件更新都可以轻松破坏您的代码。 Apple 非常仔细地针对 API 测试二进制兼容性,但无法测试这样的修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多