更新时间:2022-12-04 10:32:08
首先我们必须区分属性和 ivars.如果访问器是显式编码的,或者属性不是 ivar 支持的,则称为存储属性".
First we have to differentiate between properties and ivars. If an accessor is coded explicitly or if the property is not ivar-backed, it is called a "stored property".
A.访问属性
由于属性只是访问器方法的声明,因此访问和获取属性意味着执行访问器方法.
Since a property is simply the declaration of accessor methods, accessing and getting properties means to execute a accessor method.
属性对类的所有实例对象都是通用的.所以,首先得到它:
A property is universal to all instance objects of a class. So, first get it:
Class objectsClass = object_getClass( receiver );
然后你就可以得到财产
objc_property_t property = class_getProperty( objectsClass, [propertyName cStringUsingEncoding:NSASCIIStringEnCoding] );
有了属性,你就可以得到 setter 和 getter 的标识符.
Having the property, you get the identifiers of the setter and getter.
SEL getter;
const char* getterName = property_copyAttributeValue( property, "G" )
G
用于 getter,S
用于 setter,如 此处.
G
is for getter, S
is for setter as described here.
IIRC,如果访问器没有显式设置(setter=..., getter=...),您将得到 nil,因此您必须按照命名约定获取属性名称:
IIRC, you get nil, if the accessor is not set explicitly (setter=…, getter=…), so you have to take the properties name following the naming conventions:
if (getter==NULL)
{
getter = NSSelectorFromString( propertyName );
}
else
{
getter = sel_getUid( getterName );
}
使用 setter 会稍微复杂一些,因为您必须在属性名称前加上 set
前缀,并使名称的第一个字符大写.而是简单的字符串处理.
With a setter it is a bit more complicated, because you have to prefix the property's name with set
and make the first character of the name uppercased. But simple string processing.
现在我们可以执行访问器了.这对于更复杂的 getter 来说,因为你必须与返回类型不同:integral (id
, char
, unsigned int
, ...),浮点(float
、double
、long double
)和结构.您将为每种情况找到一个函数,并应该转换结果.但是对于整型(包括指针),它看起来像这样:
Now we can execute the accessor. This is for getters more complicated, because you have to differ from the return types: integral (id
, char
, unsigned int
, …), floating-point (float
, double
, long double
) and structures. You will find a function for each case and should cast the result. However for integral types (including pointers) it looks like this:
id value = objc_msgSend( receiver, getter );
B.获取 Ivars 值
B. Getting the Ivars Value
如果要获取或设置ivar的值,获取属性的方法也是一样的.在此之后,您读取属性的 V
属性以获取 ivar 的名称.(记住:@synthesize property=differentIvarName).然后你得到了 ivar:
If you want to get or set the value of the ivar, it is the same way to get the property. After this you read the V
attribute of the property to get the ivar's name. (Remember: @synthesize property=differentIvarName). Then you get the ivar:
objc_ivar ivar = class_getInstanceVariable( objectsClass, ivarName );
得到它:
id value = object_getIvar( object, ivar );
如果是C类型,就得另辟蹊径,例如
If it is a C type, you have to go a different way, for example
ptrdiff_t offset = ivar_getOffset( ivar );
double value = *((double*)(object+offset));
类似于二传手.
所有内容均在 Safari 中输入,无需重新检查文档.但是它应该是一个深指针.
All is typed in Safari without rechecking the docs. However it should be a deep pointer.
顺便说一句:类型编码描述 这里.
BTW: The type encoding are described here.