3

我尝试将 CGRect 传递给 NSInvocation (setArgument:atIndex:)。我用 NSValue 包装它,推送到 NSArry,然后从 NSArray 获取并使用 NSValue (getValue:)。(getValue:) 方法的调用导致之前声明的索引 NSInteger i 发生变化。谁能说出为什么会这样?

 NSString className = @"UIButton";
    Class cls = NSClassFromString(className);
    cls pushButton5 = [[cls alloc] init];
    CGRect rect =CGRectMake(20,220,280,30);
    NSMethodSignature *msignature1;
    NSInvocation *anInvocation1;

    msignature1 = [pushButton5 methodSignatureForSelector:@selector(setFrame:)];
    anInvocation1 = [NSInvocation invocationWithMethodSignature:msignature1];

[anInvocation1 setTarget:pushButton5];
[anInvocation1 setSelector:@selector(setFrame:)];
NSValue* rectValue = [NSValue valueWithCGRect:rect];
NSArray *params1;
params1= [NSArray arrayWithObjects:rectValue,nil];
id currentVal = [params1 objectAtIndex:0];
NSInteger i=2;
if ([currentVal isKindOfClass:[NSValue class]]) {
    void *bufferForValue;
    [currentVal getValue:&bufferForValue];
    [anInvocation1 setArgument:&bufferForValue atIndex:i];
}else {
    [anInvocation1 setArgument:&currentVal atIndex:i];
}
[anInvocation1 invoke];

当此(getValue:)方法实现“i”的值从 2 更改为:1130102784 时,(setArgument:atIndex:)我有一个 SIGABRT,因为索引 i 超出范围。

那么为什么要[NSValue getValue:(*void) buffer]改变其他变量呢?

(PS我是在函数中做的,所以我简化了一个例子并直接初始化数组。如果我直接设置atIndex:2,它就完美了。但我很伤心我简化了一点,我需要将i传递给atIndex: )


感谢汤姆达林(特别是)和塞尔吉奥问题解决了。我删除这个:

void *bufferForValue;
[currentVal getValue:&bufferForValue];
[anInvocation1 setArgument:&bufferForValue atIndex:i];

并粘贴这个

NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentVal objCType], &bufferSize, NULL);
void* buffer = malloc(bufferSize);
[currentVal getValue:buffer];
[anInvocation1 setArgument:buffer atIndex:i];

谢谢你。Stackoverflow.com 对聪明人很有帮助的网站。

4

2 回答 2

10

你不能将 aNSRect放入 avoid*中。正确的代码是:

NSRect buffer;
[currentVal getValue:&buffer];

或者,如果您不知道NSValue对象的内容:

NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentVal objCType], &bufferSize, NULL);
void* buffer = malloc(bufferSize);
[currentVal getValue:buffer]; //notice the lack of '&'
//do something here
free(buffer);

的值i正在发生变化,因为您的代码会导致溢出到其他堆栈分配的变量中。

于 2011-08-12T07:17:40.833 回答
3

在:

 void *bufferForValue;
 [currentVal getValue:&bufferForValue];

您正在将currentVal值复制到大小为void*(指针)的缓冲区;现在,请参阅getValue参考

获取值:

将接收者的值复制到给定的缓冲区中。

缓冲

将接收者的值复制到其中的缓冲区。缓冲区必须足够大以容纳该值。

由于您复制到缓冲区的值不适合 a void*,因此您正在覆盖堆栈,因为您正在写入局部变量的地址;这可能具有覆盖i局部变量的效果,因此可以解释正在发生的事情。

于 2011-08-12T07:13:26.453 回答