我已经开始准备一个旧项目来支持arm64架构。但是,当我尝试在64位设备上执行此代码时,我在[invocation keepArguments]上遇到EXC_BAD_ACCESS崩溃;线
- (void)makeObjectsPerformSelector: (SEL)selector withArguments: (void*)arg1, ...
{
va_list argList;
NSArray* currObjects = [NSArray arrayWithArray: self];
for (id object in currObjects)
{
if ([object respondsToSelector: selector])
{
NSMethodSignature* signature = [[object class] instanceMethodSignatureForSelector: selector];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];
invocation.selector = selector;
invocation.target = object;
if (arg1 != nil)
{
va_start(argList, arg1);
char* arg = arg1;
for (int i = 2; i < signature.numberOfArguments; i++)
{
const char* type = [signature getArgumentTypeAtIndex: i];
NSUInteger size, align;
NSGetSizeAndAlignment(type, &size, &align);
NSUInteger mod = (NSUInteger) arg % align;
if (mod != 0)
arg += (align - mod);
[invocation setArgument: arg
atIndex: i];
arg = (i == 2) ? (char*) argList : (arg + size);
}
va_end(argList);
}
[invocation retainArguments];
[invocation invoke];
}
}
}
看来参数有些问题。
这就是具有相同目的的东西。
+ (void)callSelectorWithVarArgs:(SEL)selector onTarget:(id)target onThread:(id)thread wait:(BOOL)wait, ...
{
NSMethodSignature *aSignature = [[target class] instanceMethodSignatureForSelector:selector];
if (aSignature)
{
NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
void * arg;
int index = 2;
[anInvocation setSelector:selector];
[anInvocation setTarget:target];
va_list args;
va_start(args, wait);
do
{
arg = va_arg(args, void *);
if (arg)
{
[anInvocation setArgument:arg atIndex:index++];
}
}
while (arg);
va_end(args);
[anInvocation retainArguments];
if (thread == nil)
{
[anInvocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];
}
else
{
[anInvocation performSelector:@selector(invoke) onThread:thread withObject:nil waitUntilDone:wait];
}
}
}
请考虑到,此代码在执行类型转换的必要时可能不安全。当被调用的方法具有传递给我的更长的参数时callSelectorWithVarArgs:onTarget:onThread:wait:
(例如,被调用的方法接收NSUInteger(在arm64上为64位),但是我通过int(在arm和arm64上均为32位),这导致从开始读取64位32位变量的地址-以及数据中的垃圾)。无论如何,您的实现有潜在的危险-您将传递给包装方法的所有参数都视为与调用方法中的参数具有相同类型。
这是修改后的代码,可以正常工作:
- (void)makeObjectsPerformSelector:(SEL)selector withArguments: (void*)arg1, ...
{
NSArray* currObjects = [NSArray arrayWithArray: self];
for (id object in currObjects)
{
if ([object respondsToSelector: selector])
{
NSMethodSignature* signature = [[object class] instanceMethodSignatureForSelector: selector];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];
invocation.selector = selector;
invocation.target = object;
[invocation setArgument:&arg1 atIndex:2];
NSInteger index = 3;
void * arg;
va_list args;
va_start(args, arg1);
do
{
arg = va_arg(args, void *);
if (arg)
{
[invocation setArgument:&arg atIndex:index++];
}
}
while (arg);
va_end(args);
[invocation retainArguments];
[invocation invoke];
}
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句