【问题标题】:How to swizzle a method of a private class如何调配私有类的方法
【发布时间】:2014-04-17 04:08:06
【问题描述】:

我有一个私有类(都在 .m 中声明和定义)作为不同类的实现的补充,它恰好在内部使用该私有类。

我想调配那个私有类的方法之一。

我定义了一个类别并照常进行:

+(void)load 
{
    Method original, swizzled;

    original = class_getInstanceMethod(objc_getClass("SomePrivateClass"), @selector(somePrivateMethod:));
    swizzled = class_getInstanceMethod(self, @selector(swizzled_somePrivateMethod:));
    method_exchangeImplementations(original, swizzled); 
}

问题是我的实现显然对这个私有类一无所知,而 self 指的是我要添加类别的类,无论可能是哪个类。所以我无法调用原始实现并且通常使用私有类。

解决这个问题的正确方法是什么?

【问题讨论】:

    标签: ios runtime swizzling


    【解决方案1】:

    设法让它工作,实际上非常简单。

    所以我是这样做的:

    • 做了一个NSObject类:@interface NSObject(PrivateSwizzleCategory)
    • 混搭:

      +(void)load
      {
          Method original, swizzled;
      
          original = class_getInstanceMethod(objc_getClass("SomePrivateClass"), @selector(somePrivateMethod:));
          swizzled = class_getInstanceMethod(self, @selector(swizzled_somePrivateMethod:));   
          method_exchangeImplementations(original, swizzled);
      }
      
    • 要调用原始实现,我必须将 self 转换为 NSObject:

      id ret = [(NSObject *)self swizzled_somePrivateMethod:someParam];
      
    • 为了访问私有类的私有属性,我在 self 上使用了 valueForKey:

      id privateProperty = [self valueForKey:@"__privateProperty"];
      

    一切正常!

    【讨论】:

    • 你能用这样的混合私有方法将应用程序发送到 AppStore 吗?
    • 在我的情况下,它是 3rd 方库的私有方法,所以这不是问题,应用程序通过了审核过程没有任何问题。
    • 效果很好,但是我不需要强制转换为 NSObject 来调用原始私有方法
    • Swizzling 应始终在 dispatch_once 中完成。我从nshipster.com/method-swizzling得到它
    猜你喜欢
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 2012-07-02
    • 2016-09-20
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    相关资源
    最近更新 更多