Small valley bottom exploration collection
- Brothers. Explore a wave today
associations
~
1. Use associated objects
-
- We already know:
classification
using@property
Define a property that will only generate variablessetter
.getter
A method declaration does not generate an implementation of the method.
- We already know:
-
- Then we can prepare a test code:
@interface LGPerson (LG)
@property (nonatomic.copy) NSString *cate_name;
@end
@implementation LGPerson (LG)
@end
Copy the code
-
- In this case, if you give
cate_name
Assign, and the run crashes.
- In this case, if you give
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.
-
- 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.
-
- In the source code project, we can click
objc_setAssociatedObject
Go into the method and explore
- In the source code project, we can click
Brothers, see the source code method, feel different from the original (Apple has made adjustments, mine is still relatively new, 😆)
-
- Some of you guys might not have used it
C++
forC++
Not really. But it doesn’t matter. Click on it
- Some of you guys might not have used it
-
- 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.
-
- We can look at these
strategy
What is the:
- We can look at these
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
-
- Let’s dig deeper and see what structure it is, how does it exist
-
- We look at the
acquireValue()
methods
- We look at the
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 ~
-
- 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
-
- We breakpoint debug to output a wave
-
- So let’s draw this relationship. Otherwise easy to meng ~
-
- 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
-
- Finally, I drew a whole wave of the structure. Let’s see if we can be satisfied