【问题标题】:Replacing a class method in objective C and calling original implementation替换目标 C 中的类方法并调用原始实现
【发布时间】:2015-05-11 15:46:29
【问题描述】:

我正在尝试用我自己的实现替换 UIImage 的类方法。

在某些情况下,我的实现可能只想调用原始 UIImage 实现。

这是我的代码

#import "UIImage+SkinnedImage.h"
#import <objc/runtime.h>

@interface UIImage (SkinnedImagePrivate)

+ (UIImage *)originalImageNamed:(NSString*)name;

@end


@implementation UIImage (SkinnedImage)

+ (void)allowSkinning {
    Method imageNamedMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
    IMP originalImageNamedIMP = class_getMethodImplementation_stret([UIImage class], @selector(imageNamed:));
    Method swizzled = class_getClassMethod([UIImage class], @selector(skinnedImageNamed:));
    method_exchangeImplementations(imageNamedMethod, swizzled);
    const char *signatureEnconding = method_getTypeEncoding(imageNamedMethod);
    class_addMethod([UIImage class], @selector(originalImageNamed:), originalImageNamedIMP, signatureEnconding);

}


+ (UIImage *)skinnedImageNamed:(NSString *)name {
    //XXX 
    return [UIImage originalImageNamed:name];
}

@end
  1. + (void)allowSkinning 被调用。
  2. 调用 + (UIImage *)skinnedImageNamed:(NSString *)name 而不是 + (UIImage *)imageNamed:(NSString *)name;
  3. return [UIImage originalImageNamed:name]; 崩溃错误:

原因:'+[UIImage originalImageNamed:]:无法识别的选择器发送到 类

为什么 class_addMethod([UIImage class], @selector(originalImageNamed:), originalImageNamedIMP, signatureEnconding);未能为我提供实现?

请注意函数class_addMethod返回true

【问题讨论】:

  • Other Linker Flags下的构建设置中添加-ObjC标志
  • @Wongzigii 我已经拥有了它

标签: objective-c introspection objective-c-runtime


【解决方案1】:

此行将实例方法-originalImageNamed: 添加到UIImage

class_addMethod([UIImage class], @selector(originalImageNamed:), originalImageNamedIMP, signatureEnconding);

你可以改成:

class_addMethod(object_getClass([UIImage class]), @selector(originalImageNamed:), originalImageNamedIMP, signatureEnconding);

或者,等效地:

class_addMethod(objc_getMetaClass("UIImage"), @selector(originalImageNamed:), originalImageNamedIMP, signatureEnconding);

类方法是类元类的实例方法。因此,向该元类添加一个实例方法会向该类添加一个类方法。

您拨打class_getMethodImplementation_stret() 时遇到类似问题。该函数获取实例方法的实现。因此,如果你想获取一个类的方法,你必须通过该类的元类:

IMP originalImageNamedIMP = class_getMethodImplementation(object_getClass([UIImage class]), @selector(imageNamed:));

或者,既然你已经有了对应的Method,你可以这样做:

IMP originalImageNamedIMP = method_getImplementation(imageNamedMethod);

顺便问一下,你为什么用class_getMethodImplementation_stret()+imageNamed: 不返回结构。

【讨论】:

  • 我尝试使用 both objc_getMetaClass("UIImage")object_getClass([UIImage class]),使用 _stret 和不使用(文档对两者之间的区别不是很清楚)但是,当我尝试时,应用程序仍然以相同的方式崩溃调用 originalImageNamed...
  • 我已经更新了我的答案。您在获取原始实现时遇到了类似的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 2018-12-17
相关资源
最近更新 更多