Small valley bottom exploration collection

  • Brothers. Explore a wave todayassociations~

1. Use associated objects

    1. We already know:classificationusing@propertyDefine a property that will only generate variablessetter.getterA method declaration does not generate an implementation of the method.
    1. Then we can prepare a test code:
@interface LGPerson (LG)

@property (nonatomic.copy) NSString *cate_name;

@end

@implementation LGPerson (LG)

@end
Copy the code
    1. In this case, if you givecate_nameAssign, and the run crashes.

However, compilation does not, which shows that a property defined by a class with @property only generates declarations of setters and getters for variables, not implementations of methods.

    1. Let’s modify the code:
@interface LGPerson (LG)

@property (nonatomic.copy) NSString *cate_name;

@end

@implementation LGPerson (LG)

- (void)setCate_name:(NSString *)cate_name{
    objc_setAssociatedObject(self."cate_name", cate_name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)cate_name{
    objc_getAssociatedObject(self."cate_name");
}

@end
Copy the code

We give him a setter and getter, and he’s fine

This is where associative objects are used a lot.

2. The nature of the associated object

Let’s explore how this works when we associate objects.

    1. In the source code project, we can clickobjc_setAssociatedObjectGo into the method and explore

Brothers, see the source code method, feel different from the original (Apple has made adjustments, mine is still relatively new, 😆)

    1. Some of you guys might not have used itC++forC++Not really. But it doesn’t matter. Click on it

    1. Let’s analyze these parameters
- (void)setCate_name:(NSString *)cate_name{
    objc_setAssociatedObject(self, "cate_name", cate_name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

static void
_base_objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
{
  _object_set_associative_reference(object, key, value, policy);
}
Copy the code

Parameter 1: ID object: To add an attribute to an object, in this case to add an attribute to yourself, use self

Parameter 2: void * key: specifies the property name. The property value of the associated object is obtained by key. In objc_getAssociatedObject, the property value is obtained by secondary key and returned

Parameter 3: id value: the associated value, that is, the value passed by the set method to the attribute to save

Parameter 4: objc_AssociationPolicy Policy: indicates the policy in which attributes are saved.

    1. We can look at thesestrategyWhat is the:
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0./**< Specifies a weak reference to the associated object. */
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1./**< Specifies a strong reference to the associated object. * The association is not made atomically. */
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3./**< Specifies that the associated object is copied. * The association is not made atomically. */
    OBJC_ASSOCIATION_RETAIN = 01401./**< Specifies a strong reference to the associated object. * The association is made atomically. */
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied. * The association is made atomically. */
};
Copy the code

Just so you know, this strategy is really just: the modifier corresponding to the property

    1. Let’s dig deeper and see what structure it is, how does it exist

    1. We look at theacquireValue()methods
    inline void acquireValue(a) {
        if (_value) {
            switch (_policy & 0xFF) {
            case OBJC_ASSOCIATION_SETTER_RETAIN:
                _value = objc_retain(_value);
                break;
            case OBJC_ASSOCIATION_SETTER_COPY:
                _value = ((id(*)(id, SEL))objc_msgSend)(_value, @selector(copy));
                break; }}}Copy the code

After clicking on it, I found that this is a policy judgment, and then there is a message forwarding, which is not important ~

    1. The focus should be on the folded code block
{
        AssociationsManager manager;
        
        AssociationsHashMap &associations(manager.get());

        if (value) {
            auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});
            if (refs_result.second) {
                /* it's the first association we make */
                object->setHasAssociatedObjects();
            }

            /* establish or replace the association */
            auto &refs = refs_result.first->second;
            auto result = refs.try_emplace(key, std::move(association));
            if (!result.second) {
                association.swap(result.first->second);
            }
        } else {
            auto refs_it = associations.find(disguised);
            if(refs_it ! = associations.end()) {auto &refs = refs_it->second;
                auto it = refs.find(key);
                if(it ! = refs.end()) { association.swap(it->second); refs.erase(it);if (refs.size() == 0) {
                        associations.erase(refs_it);

                    }
                }
            }
        }
    }
Copy the code
    1. We breakpoint debug to output a wave

    1. So let’s draw this relationship. Otherwise easy to meng ~

    1. It looks so complicated. Let’s get this straight: Find the key
  std: :pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) {
    BucketT *TheBucket;
    if (LookupBucketFor(Key, TheBucket))
      return std: :make_pair(
               makeIterator(TheBucket, getBucketsEnd(), true),
               false); // Already in map.

    // Otherwise, insert the new element.
    TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...) ;return std: :make_pair(
             makeIterator(TheBucket, getBucketsEnd(), true),
             true);
  }

  iterator makeIterator(BucketT *P, BucketT *E,
                        bool NoAdvance=false) {
    return iterator(P, E, NoAdvance);
  }
Copy the code

A wave of soul painters is needed

    1. Finally, I drew a whole wave of the structure. Let’s see if we can be satisfied