The oc adds attributes and principles to the class, and the oc class
Oc adds attributes and principles to classes in categories
How can we add attributes to a category? If there is a duck, we think it is a duck.
@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
The attribute is obtained from the direct offset address, and the association is obtained twice.
Let's take a look at the events that happen when set get and dealloc are available.
Void objc_setAssociatedObject (id object, const void * key, id value, objc_AssociationPolicy policy) {# if SUPPORT_GC if (UseGC) {if (policy & attributes) = 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_as Sociative_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; {// there is a single-profit AssociationsManager manager for managing associations; AssociationsHashMap & associations (manager. associations (); if (new_value) {// if there is a value // break any existing association. associationsHashMap: iterator I = associations. find (object); if (I! = Associations. end () {// if there is an object in map // secondary table exists ObjectAssociationMap * refs = I-> second; ObjectAssociationMap :: iterator j = refs-> find (key); if (j! = Refs-> end () {// if the value corresponding to the key is not found in ObjectAssociationMap, a new one is added, and 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 {// assign a value directly after finding it (* refs) [key] = ObjcAssociation (policy, new_value );}} else {// create without an object // create the new association (first time ). objectAssociationMap * refs = new Objec TAssociationMap; associations [object] = refs; (* refs) [key] = ObjcAssociation (policy, new_value); _ class_setInstancesHaveAssociatedObjects (_ object_getClass (object ));}} else {// empty. // 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 partition (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 () {// when the value is set, first find the object ObjectAssociationMap * refs = I-> second; ObjectAssociationMap: iterator j = refs-> find (key) in AssociationsHashMap ); if (j! = Refs-> end () {// then find the value of the 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 & Authorization) {objc_msgSend (value, sel_autorelsend );} return value;} void * objc_destructInstance (id obj) {if (obj) {Class isa = _ object_getClass (obj ); If (_ class_hasCxxStructors (isa) {object_cxxDestruct (obj);} // release the associated attribute in the released code if (_ class_instancesHaveAssociatedObjects (isa )) {_ object_remove_assocations (obj);} if (! UseGC) objc_clear_deallocating (obj);} return obj ;}