为什么objc_msgSend导致EXC_BAD_ACCESS? [英] Why is objc_msgSend causing an EXC_BAD_ACCESS?
问题描述
我正在创建一个类,给定一个object
目标,一个要监视的selector
和一个displayTitle
将输出以下格式的字符串:@"displayTitle: object.selector"
.然后,它通过KVO注册自己,这样,只要object.selector
的value
更改,它就可以通知视图控制器更新视图.我将其用作一种抽象且可重用的方式来向用户显示对象的各种属性的描述.
I'm making a class, that given an object
target, a selector
to watch for, and a displayTitle
will output a string in this format: @"displayTitle: object.selector"
. It then registers itself through KVO so that anytime the value
of object.selector
changes, it can notify a view controller to update the view. I am using this as an abstract and reusable way to show a description of various properties of an object to a user.
当我尝试获取object.selector
的值时,我无法执行[object performSelector:selector]
,因为此答案所建议的:我使用了objc_msgSend(object, selector)
.
When I try to get the value of object.selector
, I can't do [object performSelector:selector]
because LLVM gives errors when you use performSelector with a dynamic selector.
So, I did exactly what this answer suggested: I used objc_msgSend(object, selector)
.
- (instancetype)initWithSelector:(SEL)selector onObject:(NSObject*)object displayTitle:(NSString*)displayTitle {
self = [super init];
if (self) {
id value;
if ([object respondsToSelector:selector) {
// Used objc_msgSend instead of performSelector to suppress a LLVM warning which was caused by using a dynamic selector.
value = objc_msgSend(object, selector);
} else {
return nil;
}
[self setItemDescription:[NSString stringWithFormat:@"%@: %@", displayTitle, value]];
}
return self;
}
我得到了EXC_BAD_ACCESS
!
如您在屏幕截图中所见,我确保
做[object selector]
的作品.
As you can see in the screenshot, I made sure that
doing [object selector]
works.
这是怎么回事,我该如何解决?
What is going on, and how can I fix it?
推荐答案
您将objc_msgSend
调用的结果分配给类型为id
的变量,以便ARC启动并尝试保留结果对象(崩溃发生在objc_retain
,如您在左侧堆栈中所见).但是,结果不是对象,而是值8的整数,objc_retain
被当作指针.但是没有如此低的有效指针,所以您得到了EXC_BAD_ACCESS
.
You assign the result of your objc_msgSend
call to a variable of type id
so ARC kicks in and tries to retain the resulting object (crash is in objc_retain
as you can see in the stack to the left). However, the result isn’t an object but an integer of value 8, which objc_retain
takes to be a pointer. But there are no valid pointers this low, so you get the EXC_BAD_ACCESS
.
只需将value
的类型更改为NSUInteger
(或任何其他非对象类型).但是,请确保所有潜在的selector
返回相同类型的数据.另外,请确保始终返回可以由ARC保留的对象(或nil
).
Just change the type of value
to be NSUInteger
(or any other non-object type). But make sure all potential selector
s return data of the same type. Alternatively, make sure to always return an object (or nil
), which can be retained by ARC.
这篇关于为什么objc_msgSend导致EXC_BAD_ACCESS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!