5

我在 ARMv7 IOS 设备上使用标准方法 swizzling,它对我来说非常完美。

但是当我为 arm64 编译代码时 - 它无法从新方法调用原始方法

我调配的主要目的 - 在另一种方法中使用来自我的应用程序内部方法的参数。

我有原始方法-(void)insertdata:(id)text,我想更改它-(void)patchedCall:(id)text并在新方法中调用原始方法。

代码:

static IMP sOriginalImp = NULL;

@interface TextOverrides: NSObject
+(void)load;
-(void)patchedinsert:(id)text;
@end

@implementation TextOverrides

+(void)load
{
    //Get Implementation of original method

    Class originalClass = NSClassFromString(@"DataViewController");
    Method originalMeth = class_getInstanceMethod(originalClass, @selector(insertdata:));

    //Save original method implementation
    sOriginalImp = method_getImplementation(originalMeth);

    // Get implementation of replacement method
    Method replacementMeth = class_getInstanceMethod(NSClassFromString(@"TextOverrides"), @selector(patchedCall:));

    //Replace methods
    method_exchangeImplementations(originalMeth, replacementMeth);
}

-(void)patchedCall:(id)text
{
    @synchronized(self){
        //Call of original method that we save
        sOriginalImp(self, @selector(insertdata:), text);

        //Make our code for argument "text"
        printf("Here is data%s\n", [text UTF8String]);
    }
}

@end

代码在 arm64 架构上调用原始方法失败:

//Call of original method that we save
sOriginalImp(self, @selector(insertdata:), text);

如何改进我的代码以在 armv7 和 arm64 上工作?

4

2 回答 2

2

通过对https://github.com/square/PonyDebugger/issues/84的讨论,我认为要点是https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ ConvertingYourAppto64-Bit.html#//apple_ref/doc/uid/TP40013501-CH3-SW22以及IMP定义为可变参数函数并且您使用固定参数调用它的事实。就我而言,将函数指针转换为真实签名修复了崩溃。我相信你的情况,比如

//Call of original method that we save
((void(*)(id, SEL, id))ssOriginalImp)(self, @selector(insertdata:), text);

可以修复崩溃。

于 2015-02-12T15:43:13.847 回答
0

我不认为所有类的加载顺序都在某处指定。所以可能是TextOverrides该类之前DataViewController在 arm64 上加载,但在 armv7 上没有加载。见https://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html

为了使其稳定,您应该只在 category +load 方法中调配方法。例如:

@interface DataViewController (TextOverrides)
+(void)load;
-(void)patchedinsert:(id)text;
@end

@implementation DataViewController (TextOverrides)

+(void)load
{
    // swizzle here
}
...
于 2014-12-10T10:36:29.497 回答