我在这里看到了一个很好的样本: Subclass UIButton to add a property
这是什么?您无法将对象添加到类别。但现在有了这个技巧,你可以。
那是什么?它是如何工作的?
Objective-c对象已经有一些常数的ivar指针了吗?
现在你又添加一个?他们是怎么想出来的?
我必须承认一个非常丑陋的符号。
答案 0 :(得分:4)
使用关联引用技巧,您实际上并未将任何实例数据添加到UIButton对象。相反,您正在使用一个完全独立的Cocoa工具来创建一个新的字典映射(或关联)现有的UIButton对象与存储在堆中其他位置的数据。
如果不使用Cocoa的关联引用,你可以做同样的事情;它会更加丑陋甚至可能效率低下。在Objective-C ++中它会是这样的。 (我甚至不会尝试在Objective-C中编写它,因为CFMutableDictionary
和NSMutableDictionary
在两个级别上都有错误的行为,我不会写整个从头开始。但是,C ++的std::map
不能像我想要的那样使用__weak
引用,所以我要回到这个效率低下的std::vector
算法。对于那些不熟悉C ++:std::vector
大致相当于NSMutableArray
,除了你可以选择是否保留其内容。)
重点是UIButton对象没有被改变;这个附加字典的内容正在发生变化。属性getter和setter只知道如何在该字典中查找内容,以便它出现,好像UIButton有一个新属性。
#import "UIButton+Property.h"
#import <algorithm>
#import <vector>
typedef std::pair<__weak id, __strong id> EntryType;
static std::vector<EntryType> myAR;
@implementation UIButton(Property)
-(void) setProperty:(id)property
{
for (int i=0; i < myAR.size(); ++i) {
if (myAR[i].first == self) {
myAR[i].second = property;
return;
}
}
myAR.push_back(EntryType(self, property));
}
-(id) property
{
/* To save space, periodically erase the dictionary entries for
* UIButton objects that have been deallocated. You can skip this
* part, and even use NSMutableDictionary instead of this C++
* stuff, if you don't care about leaking memory all over the place.
*/
size_t n = myAR.size();
for (size_t i=0; i < n; ++i) {
if (myAR[i].first == nil)
myAR[i] = myAR[--n];
}
myAR.resize(n);
/* Look up "self" in our dictionary. */
for (size_t i=0; i < myAR.size(); ++i) {
EntryType &entry = myAR[i];
if (entry.first == self) {
return entry.second;
}
}
return nil;
}
@end
另请参阅:http://labs.vectorform.com/2011/07/objective-c-associated-objects/
答案 1 :(得分:-1)
git上提供的示例代码!点击here!