objective-c 用类别给类加属性以及原理
转载请注明出处 uxyheaven csdn博客
如何在类别里给类加属性呢,有鸭子模样的我们就认为他是鸭子了.
@interface NSObject (XY) @property ( nonatomic , strong ) id tempObject; @end @implementation NSObject (XY) @dynamic tempObject;- ( id )tempObject- { id object = objc_getAssociatedObject( self , NSObject_key_tempObject); return object;}- ( void )setTempObject:( id )tempObject- { [ self willChangeValueForKey:@ "tempObject" ]; objc_setAssociatedObject( self , NSObject_key_tempObject, tempObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [ self didChangeValueForKey:@ "tempObject" ];} @end
属性取变量是直接偏移地址得到,关联是取了2次map.
下面来看一下set get 还有dealloc时候发生的事情吧
void
objc_setAssociatedObject(id
object
,
const
void
*key, id
value
, objc_AssociationPolicy policy) {
#if SUPPORT_GC
if
(UseGC) {
if
((policy & OBJC_ASSOCIATION_COPY_NONATOMIC) == OBJC_ASSOCIATION_COPY_NONATOMIC) {
value
= objc_msgSend(
value
, SEL_copy); } auto_zone_set_associative_ref(gc_zone,
object
, (
void
*)key,
value
); }
else
#endif
{
// Note, creates a retained reference in non-GC.
_object_set_associative_reference(
object
, (
void
*)key,
value
, policy); }}PRIVATE_EXTERN
void
_object_set_associative_reference(id
object
,
void
*key, id
value
, uintptr_t policy) {
// retain the new value (if any) outside the lock.
uintptr_t old_policy =
0
;
// NOTE: old_policy is always assigned to when old_value is non-nil.
id new_value =
value
? acquireValue(
value
, policy) : nil, old_value = nil; {
// 有个管理关联的单利
AssociationsManager manager; AssociationsHashMap &associations(manager.associations());
if
(new_value) {
// 如果有值
// break any existing association.
AssociationsHashMap::iterator i = associations.find(
object
);
if
(i != associations.end()) {
// 如果在map里有object的话
// secondary table exists
ObjectAssociationMap *refs = i->second; ObjectAssociationMap::iterator j = refs->find(key);
if
(j != refs->end()) {
// 如果在ObjectAssociationMap里没找到key对应的值就new一个,塞进去
ObjcAssociation &old_entry = j->second; old_policy = old_entry.policy; old_value = old_entry.
value
; old_entry.policy = policy; old_entry.
value
= new_value; }
else
{
// 找到了就直接赋值
(*refs)[key] = ObjcAssociation(policy, new_value); } }
else
{
// 没有object就创建
// create the new association (first time).
ObjectAssociationMap *refs =
new
ObjectAssociationMap; associations[
object
] = refs; (*refs)[key] = ObjcAssociation(policy, new_value); _class_setInstancesHaveAssociatedObjects(_object_getClass(
object
)); } }
else
{
// 没值就清空
// setting the association to nil breaks the association.
AssociationsHashMap::iterator i = associations.find(
object
);
if
(i != associations.end()) { ObjectAssociationMap *refs = i->second; ObjectAssociationMap::iterator j = refs->find(key);
if
(j != refs->end()) { ObjcAssociation &old_entry = j->second; old_policy = old_entry.policy; old_value = (id) old_entry.
value
; refs->erase(j); } } } }
// release the old value (outside of the lock).
if
(old_value) releaseValue(old_value, old_policy);}id objc_getAssociatedObject(id
object
,
const
void
*key) {
#if SUPPORT_GC
if
(UseGC) {
return
auto_zone_get_associative_ref(gc_zone,
object
, (
void
*)key); }
else
#endif
{
return
_object_get_associative_reference(
object
, (
void
*)key); }}PRIVATE_EXTERN id _object_get_associative_reference(id
object
,
void
*key) { id
value
= nil; uintptr_t policy = OBJC_ASSOCIATION_ASSIGN; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); AssociationsHashMap::iterator i = associations.find(
object
);
if
(i != associations.end()) {
// 取值的时候就在AssociationsHashMap里面先找到object
ObjectAssociationMap *refs = i->second; ObjectAssociationMap::iterator j = refs->find(key);
if
(j != refs->end()) {
// 然后找到的key对应的值
ObjcAssociation &entry = j->second;
value
= (id)entry.
value
; policy = entry.policy;
if
(policy & OBJC_ASSOCIATION_GETTER_RETAIN) objc_msgSend(
value
, SEL_retain); } } }
if
(
value
&& (policy & OBJC_ASSOCIATION_GETTER_AUTORELEASE)) { objc_msgSend(
value
, SEL_autorelease); }
return
value
;}
void
*objc_destructInstance(id obj) {
if
(obj) { Class isa = _object_getClass(obj);
if
(_class_hasCxxStructors(isa)) { object_cxxDestruct(obj); }
// 在释放的代码里,释放关联的属性
if
(_class_instancesHaveAssociatedObjects(isa)) { _object_remove_assocations(obj); }
if
(!UseGC) objc_clear_deallocating(obj); }
return
obj;}