使用CGPoint的object_setInstanceVariable

时间:2012-09-04 13:56:58

标签: ios iphone iphone-privateapi

有没有人知道如何使用object_setInstanceVariable设置struct变量?它适用于参考类型:

object_setInstanceVariable(obj, "_variable", ref);

但不适用于CGPoint等结构。尝试以下方式:

1. object_setInstanceVariable(obj, "_variable", point);
2. object_setInstanceVariable(obj, "_variable", &point);
3. object_setInstanceVariable(obj, "_variable", (void **)&point);

我不确定我理解我在做什么(特别是最后一步)......

提前谢谢你!!!

2 个答案:

答案 0 :(得分:10)

object_setInstanceVariableobject_getInstanceVariable实际上只能用于对象(尽管接口声明似乎另有说明)。你不应该将它们用于内置。

更合适的方法是使用class_getInstanceVariableivar_getOffset

例如......

static void* getIvarPointer(id object, char const *name) {
    Ivar ivar = class_getInstanceVariable(object_getClass(object), name);
    if (!ivar) return 0;
    return (uint8_t*)(__bridge void*)object + ivar_getOffset(ivar);
}

那里的转换基本上将对象指针转换为指向字节的指针,因此可以将其添加到偏移量(它为我们提供指向iVar的指针)。我们必须首先审核void*,因为ARC不允许直接转换为uint8_t*

因此可以证明它的用途......

@implementation Foo {
    CGRect _rect;
}

- (CGRect*)rectPointer {
    CGRect *ptr = getIvarPointer(self, "_rect");
    NSAssert(ptr == &_rect, @"runtime discovered pointer should be same as iVar pointer");
    return ptr;
}

现在,您可以获取任何iVar的指针...只需适当地转换返回的void*

顺便说一下,我不建议这样做,但是像任何工具一样,运行时函数都有用。

糟糕。忘了显示设置值......

CGRect *rectPtr = getIvarPointer(someObject, "_rect");
if (rectPtr) {
    *rectPtr = CGRectMake(1, 2, 3, 4);
} else {
    // Handle error that the ivar does not exist...
}

修改

  

对不起,现在还不是很清楚。我应该得到这种类型吗?   (CGRect *)然后将它传递给object_setInstanceVariable?还有,我有   错误“未定义的符号”_getIvarPointer“” - 请告诉我   我应该包括什么H文件 - 德米特里

没有。你根本不应该使用object_setInstanceVariable。它应该仅用于作为对象的实例变量。你的是一个CGRect,所以你根本不应该使用该功能。

像最后一个例子一样使用它。也许这个更清楚一点(从你的例子中得到)。

而不是像你的问题那样做:

object_setInstanceVariable(obj, "_variable", point);

这样做......

// Get a pointer to the instance variable.  Returns NULL if not found.
CGPoint *pointPtr = getIvarPointer(obj, "_variable");
if (pointPtr) {
    // Now, assign to the point, by de-referencing the pointer.
    *pointPtr = point;
}

注意,我将getIvarPointer函数定义为具有文件本地范围的static。它不是苹果提供的功能 - 你必须写它。如果要在多个位置使用它,则需要删除static,以便链接器可以找到它。

答案 1 :(得分:-1)

好的,我找到了答案。我看一下SELF地址和变量地址之间的区别:

NSLog(@"%d",self);
NSLog(@"%d",&variable);

例如,差异是24 - 然后我写下面的代码:

CGPoint *variable = (int)self + 24;
*variable = myCGPoint;

我甚至无法解释它是多么脏兮兮!但它有效:)

感谢Jody的帮助,我竖起大拇指回答