我尝试将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:¤tVal atIndex:i];
}
[anInvocation1 invoke];
当这个(getValue:)
方法实现'i'的值从2变为类似:1130102784时,在(setArgument:atIndex:)
中我有一个SIGABRT因为索引i超出界限。
那么为什么[NSValue getValue:(*void) buffer]
会改变其他变量?
(P.S。我在函数中这样做,所以我简化了一个例子并直接初始化数组。 如果我直接设置在索引:2,它工作得很完美。但是我很难过,我简化了一点,我需要将i传递给atIndex:)
感谢Tom Dalling(特别是)和塞尔吉奥问题解决了。我删除了这个:
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真的很有帮助的网站与聪明的人。
答案 0 :(得分:8)
您无法将NSRect
纳入void*
。正确的代码是:
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
的值正在改变,因为您的代码会导致其他堆栈分配的变量溢出。
答案 1 :(得分:2)
在:
void *bufferForValue;
[currentVal getValue:&bufferForValue];
您正在将currentVal
值复制到大小为void*
(指针)的缓冲区;现在,请参阅getValue
reference:
的getValue:
将接收者的值复制到给定的缓冲区中。
缓冲
复制接收者值的缓冲区。缓冲区必须足够大才能保存该值。
由于复制到缓冲区的值不适合void*
,因此您将覆盖堆栈,因为您正在写入局部变量的地址;这可能会覆盖i
局部变量,因此可以解释发生了什么。