使用CGPoint的object_setInstanceVariable [英] object_setInstanceVariable with CGPoint
问题描述
有没有人知道如何使用object_setInstanceVariable设置struct变量?它适用于引用类型:
Does anyone know how to set struct variables using object_setInstanceVariable? It is work fine for reference types:
object_setInstanceVariable(obj, "_variable", ref);
但不适用于CGPoint等结构。尝试以下方式:
But do not work for structs such as CGPoint. Tried following ways:
1. object_setInstanceVariable(obj, "_variable", point);
2. object_setInstanceVariable(obj, "_variable", &point);
3. object_setInstanceVariable(obj, "_variable", (void **)&point);
我不确定我理解我在做什么(尤其是最后一步)... 。
I'm not sure I understand what I'm doing (especially for the last step)...
提前谢谢你!!!
推荐答案
object_setInstanceVariable
和 object_getInstanceVariable
实际上应该仅用于对象(尽管接口声明似乎另有说明)。你不应该将它们用于内置函数。
object_setInstanceVariable
and object_getInstanceVariable
are really supposed to be used for objects only (though the interface declaration seems to indicate otherwise). You should not use those for builtins.
更合适的方法是使用 class_getInstanceVariable
和 ivar_getOffset
。
The more appropriate approach is to use class_getInstanceVariable
and ivar_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 *
。
That cast up there basically turns the object pointer into a pointer to a byte, so it can be added to the offset (which gives us the pointer to the iVar). We have to go through a void*
first, because ARC does not allow a direct cast to uint8_t*
.
因此可以证明它的使用......
It's use can be demonstrated thusly...
@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 *
。
Now, you have a way to get the pointer of any iVar... just cast the returned void*
appropriately.
BTW,我不建议一般这样做,但是喜欢任何工具,都有运行时函数的用途。
BTW, I don't recommend doing this in general, but like any tool, there are uses for the runtime functions.
糟糕。忘了显示设置值...
Oops. Forgot to show setting the value...
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文件 - 德米特里
I'm sorry, it's still not really clear. Should I get this type (CGRect*) and then pass it to object_setInstanceVariable? Also, I have an error "Undefined symbols "_getIvarPointer"" - please let me know what H file should I include – Dmitry
没有。你根本不应该使用 object_setInstanceVariable
。它应该仅用于作为对象的实例变量。你的是一个CGRect,所以你根本不应该使用那个函数。
No. You should not use object_setInstanceVariable
at all. It's supposed to be used only for instance variables that are objects. Yours is a CGRect, so you should not use that function at all.
像最后一个例子一样使用它。也许这个更清楚一些(从你的例子中得到)。
Use it like the very last example. Maybe this one is a bit more clear (it takes from your example).
而不是像你提出的问题那样:
Instead of doing something like your question asked:
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
,以便链接器可以找到它。
Note, that I defined the getIvarPointer
function as static
which has file-local scope. It is not an apple-supplied function - you have to write it. If you are going to use this in multiple places, you need to remove the static
so the linker can find it.
这篇关于使用CGPoint的object_setInstanceVariable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!