[英]Objective-C runtime crash
I am trying out Objective-C runtime methods for the first time. 我第一次尝试使用Objective-C运行时方法。 I have been reading a chapter(24) on this from iOS 7 programming pushing the limits.
我一直在阅读iOS 7编程中有关这一极限的一章(24)。 As per the example in the book I have implemented a message dispatcher function which is as below:
按照本书中的示例,我实现了一个消息分发器功能,如下所示:
static const void *myMsgSend(id receiver, const char *name) {
SEL selector = sel_registerName(name);
Class receiverClass = object_getClass(receiver);
IMP methodIMP = class_getMethodImplementation(receiverClass, selector);
return CFBridgingRetain(methodIMP(receiver, selector));
}
I test this dispatcher in the function below: 我在以下函数中测试此调度程序:
void runMyMsgSend() {
// NSObject *object = [[NSObject alloc] init];
Class class = (Class)objc_getClass("NSObject");
id object = class_createInstance(class, 0);
myMsgSend(object, "init");
// id description = [object description];
id description = (__bridge id)myMsgSend(object, "description");
// const char *cstr = [description UTF8String];
const char *cstr = myMsgSend(description, "UTF8String");
printf("---------------------");
printf("%s\n", cstr);
}
The function works well for init and description for object instance of type NSObject . 该函数对于NSObject类型的对象实例的初始化和描述非常有效。 When the dispatcher function is called on object pointed by description with UTF8String as the method to run it crashes on
在以UTF8String作为运行方法的描述指向的对象上调用分派器函数时,它崩溃
return CFBridgingRetain(methodIMP(receiver, selector));
返回CFBridgingRetain(methodIMP(receiver,selector));
Now I know that NSString is a cluster and actually an object of __NSCFString is used. 现在我知道NSString是一个群集,实际上使用了__NSCFString的对象。 I think this may be the problem while calling CFBridgingRetain .
我认为这可能是调用CFBridgingRetain时出现的问题。 I need a better understanding of what is actually causing the crash.
我需要更好地了解真正导致崩溃的原因。 Thanks in advance.
提前致谢。
You are trying to call CFBridgingRetain
on all return types.. 您正在尝试在所有返回类型上调用
CFBridgingRetain
。
The documentation explicitly states that if the IMP
returns anything that is NOT void
, then you must explicitly cast it to the right function pointer type. 该文档明确指出,如果
IMP
返回的结果不是NOT void
,则必须将其明确转换为正确的函数指针类型。
Your function is: 您的功能是:
static const void *myMsgSend(id receiver, const char *name) {
SEL selector = sel_registerName(name);
Class receiverClass = object_getClass(receiver);
IMP methodIMP = class_getMethodImplementation(receiverClass, selector);
id (*imp)(id, SEL) = (id (*)(id, SEL))methodIMP;
return CFBridgingRetain(imp(receiver, selector));
}
When you called UTF8String
, it returns a const char*
which you are trying to retain. 当您调用
UTF8String
,它将返回您尝试保留的const char*
。 Not only that, but you are saying that the IMP
returns an id
and you retain that.. You can only retain Objective-C class objects. 不仅如此,您还说
IMP
返回一个id
然后保留该id
。您只能保留Objective-C类对象。 You never casted to the correct function pointer type so it crashes trying to implicitly convert const char*
to id
.. 您从未转换为正确的函数指针类型,因此尝试将
const char*
隐式转换为id
时崩溃。
Therefore your method needs to be: 因此,您的方法需要为:
static const void *myMsgSend(id receiver, const char *name) {
SEL selector = sel_registerName(name);
Class receiverClass = object_getClass(receiver);
IMP methodIMP = class_getMethodImplementation(receiverClass, selector);
void* (*imp)(id, SEL) = (void* (*)(id, SEL))methodIMP;
return imp(receiver, selector, args);
}
where it returns a simple void*
which can be NULL or BOOL or int or w/e type (primitive).. If it needed to return an object, the object is implicitly bridged so no need to retain (just cast the result to the right type). 返回简单的
void*
,该值可以为NULL或BOOL或int或w / e类型(原始)。如果需要返回对象,则该对象被隐式桥接,因此无需保留(只需将结果强制转换为正确的类型)。
However, it is probably a much better idea to use NSInvocation
as the implementation of this function because then you don't have to worry about type and arguments and so on.. 但是,使用
NSInvocation
作为此函数的实现可能是一个更好的主意,因为这样您就不必担心类型和参数等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.