object_getIvar无法读取BOOL iVar的值

问题描述 投票:0回答:4

object_getIvar(id对象,Ivar ivar)正确读取iVArs的值,但在BOOL类型iVar上失败并崩溃。我需要一个类的所有iVars的值。有什么方法可以解决它。

iphone objective-c-runtime
4个回答
4
投票

object_getIvar似乎返回实际值(不是id),这与手册所说的相反。如果使用ARC,则在尝试保留不是对象的返回值时,这将立即导致处理器故障。

object_getInstanceVariable()返回指向信息的指针,但ARC拒绝接受该函数。


22
投票

可以使用ARC直接访问ivars。您可以访问基本C类型(char,short,int等)和Objective-C对象。例如,可以使用以下模式访问unsigned char ivar。用其他基本类型替换类型名称会产生该类型的ivar的访问器。

unsigned char val;

val = ((unsigned char (*)(id, Ivar))object_getIvar)(object, ivar);

NSLog(@"Looks like I got: %u (or character %c)", val, val);

在幕后,你正在雇用一些恶作剧来假装编译器认为object_getIvar()实际上是一个返回你所追求的类型的函数。这种类型转换改变了编译器调用和解释object_getIvar结果的方式,并且是必需的,因为基本C类型可以是8到64位大,并且只有编译器知道它们在用作返回值时如何处理,这是由您正在编译的体系结构使用的ABI定义的。

是的,它看起来很有趣,但它是最便携的方式,而且,它只是有效。 :-)使用直线型无法使用,ARC也不允许这样做。

如果ivar是从NSObject派生的对象,则可以直接使用返回值,或者将其强制转换为您期望的对象而不会出现问题,ARC或无ARC。


5
投票

答案有点旧。使用ARC和结构(或者在访问任何非对象iVar时是安全的),你应该这样做:

ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char *stuffBytes = (unsigned char *)(__bridge void *)object;
CGRect gilligans = * ((CGRect *)(stuffBytes + offset));

至少这是让它为我工作的唯一方法。

摘自此页:http://www.bignerdranch.com/blog/inside-the-bracket-part-5-runtime-api/


0
投票

我知道发表评论有点太晚了但是我遇到了同样的问题而且所有的方法都有不同的问题。 ivar_getOffset至少没有通过地址清理程序。但一切都适用于KVC。因此,不要使用指针,只需使用[object setValue:value forKey:key],其中value是包装值(使用@(value)表示普通/基本值),key是你的ivar的名称。

© www.soinside.com 2019 - 2024. All rights reserved.