这段代码给了我EXC_BAD_ACCESS,为什么?
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
IMP imp= [d methodForSelector:@selector(setObject:forKey:) ];
imp(d, @selector( setObject:forKey:), @"obj", @"key");
我刚刚开始使用IMP,第一次尝试..没有运气。不知道为什么我得到错误,也..在过去,当我得到EXC_BAD_ACCESS时,消息在控制台打印,这次错误行突出显示。
一些说明: 启用ARC,XCode 4.3.2,该项目使用Objective-C ++作为默认语言/编译器,此代码位于项目的最开始
谢谢你们
答案 0 :(得分:20)
你需要正确地转换函数指针,否则ARC不知道它应该做什么。 IMP是一个通用函数指针,它接受id,选择器和可变数量的其他未定义参数并返回一个id。您尝试调用的方法实现需要一个id,一个选择器后跟两个id参数,并且返回类型为void。您可以通过更改为以下代码来修复它:
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
void (*imp)(id, SEL, id, id) = (void(*)(id,SEL,id,id))[dict methodForSelector:@selector(setObject:forKey:)];
if( imp ) imp(dict, @selector(setObject:forKey:), @"obj", @"key");
在取消引用它之前,你应该总是检查你确实得到了一个函数指针,因为它也会崩溃。上面的代码甚至可以在ARC环境中工作。此外,即使您不使用ARC,也应始终将函数指针转换为实际原型而不是IMP。你永远不应该使用IMP。其他会导致重大问题的地方是方法返回结构或方法是否采用浮点参数等等。
好习惯:如果发现函数指针语法不和,总是为你抛出函数指针或为它们创建typedef。
答案 1 :(得分:1)
问题是IMP有一个返回类型“id”,ARC将尝试管理它。您需要将函数指针强制转换为返回类型为void(与您调用的方法一致):
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
IMP imp= [d methodForSelector: @selector(setObject:forKey:)];
void (*func)(__strong id,SEL,...) = (void (*)(__strong id, SEL, ...))imp;
func( d, @selector(setObject:forKey:), @"obj", @"key" );