關聯物件總結
預設情況下,因為分類底層結構的限制,不能新增成員變數到分類中。但可以通過關聯物件來間接實現
關聯物件提供了以下API
新增關聯物件
void objc_setAssociatedObject(id object, const void * key,
id value, objc_AssociationPolicy policy)
獲得關聯物件
id objc_getAssociatedObject(id object, const void * key)
移除所有的關聯物件
void objc_removeAssociatedObjects(id object)
key的常見用法
static void *MyKey = &MyKey;
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, MyKey)static char MyKey;
objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, &MyKey)使用屬性名作為key
objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj, @"property");使用get方法的@selecor作為key
objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
示例:
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
// 隱式引數
// _cmd == @selector(name)
return objc_getAssociatedObject(self, _cmd);
}
objc_AssociationPolicy
關聯物件的原理
實現關聯物件技術的核心物件有
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation
objc4原始碼解讀:objc-references.mm
void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
// retain the new value (if any) outside the lock.
ObjcAssociation old_association(0, nil);
id new_value = value ? acquireValue(value, policy) : nil;
{
AssociationsManager manager;
AssociationsHashMap &associations(manager.associations());
disguised_ptr_t disguised_object = DISGUISE(object);
if (new_value) {
// break any existing association.
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
// secondary table exists
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
j->second = ObjcAssociation(policy, new_value);
} else {
(*refs)[key] = ObjcAssociation(policy, new_value);
}
} else {
// create the new association (first time).
ObjectAssociationMap *refs = new ObjectAssociationMap;
associations[disguised_object] = refs;
(*refs)[key] = ObjcAssociation(policy, new_value);
object->setHasAssociatedObjects();
}
} else {
// setting the association to nil breaks the association.
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
refs->erase(j);
}
}
}
}
// release the old value (outside of the lock).
if (old_association.hasValue()) ReleaseValue()(old_association);
}
class AssociationsManager {
// associative references: object pointer -> PtrPtrHashMap.
static AssociationsHashMap *_map;
public:
AssociationsManager() { AssociationsManagerLock.lock(); }
~AssociationsManager() { AssociationsManagerLock.unlock(); }
AssociationsHashMap &associations() {
if (_map == NULL)
_map = new AssociationsHashMap();
return *_map;
}
};
注意
關聯物件不會強引用物件,而是儲存了物件的值給了一個新的物件
關聯物件沒有弱引用的效果,使用時需要注意
相關文章
- iOS底層原理總結 - 關聯物件實現原理iOS物件
- 模型關聯使用總結模型
- 關於 FormData 物件陣列傳值總結ORM物件陣列
- 關於JS的物件導向的思考和總結JS物件
- JS 總結之物件JS物件
- 聯考總結
- java集合物件排序總結Java物件排序
- 物件導向概念總結物件
- Object物件常用方法總結Object物件
- js 物件導向總結JS物件
- AssociatedObject關聯物件原理實現Object物件
- iOS關聯物件技術原理iOS物件
- 【物件導向依賴關係概念總結】物件導向程式設計的五種依賴關係物件程式設計
- 關聯物件的實現原理【OC】物件
- Category的本質<三>關聯物件Go物件
- 週報 物件導向總結物件
- JavaScript遍歷物件方法總結JavaScript物件
- 初學 PHP 總結建立物件PHP物件
- 物件導向(理解物件)——JavaScript基礎總結(一)物件JavaScript
- 最新 Objective-C 關聯物件 AssociatedObject 原理Object物件
- 關聯物件(防止自己忘記記錄)物件
- Swift在擴充套件中關聯物件Swift套件物件
- 類和物件部分知識總結物件
- JAVA物件導向詳細總結Java物件
- JS知識總結之BOM物件JS物件
- javascript的物件問題及總結JavaScript物件
- Ajax 相關總結
- 2024.11.19隨筆&聯考總結
- 聯考總結 - pre NOIP 2024
- 10.17noip聯考總結
- 10.18noip聯考總結
- noip多校聯考總結
- 10.8日noip聯考總結
- 物件導向第二單元總結物件
- Java類和物件知識點總結Java物件
- JS知識總結之內建物件JS物件
- 好程式設計師web前端分享javascript關聯陣列用法總結程式設計師Web前端JavaScript陣列
- 關於Servlet小總結Servlet