5

我在这里看到了一个非常好的示例: Subclass UIButton to add a property

它是什么?您不能将对象添加到类别中。但是现在有了这个技巧,你就可以了。

那是什么?它是如何工作的?

Objective-c 对象已经有一些恒定数量的 ivar 指针,对吧?

现在又加了一个?他们是怎么想出来的?

我必须承认这是一个非常丑陋的符号。

4

2 回答 2

6

使用关联引用技巧,您实际上并没有向 UIButton 对象添加任何实例数据。相反,您使用一个完全独立的 Cocoa 工具来创建一个新的字典映射(或关联)现有 UIButton 对象与存储在堆中其他位置的数据。

你可以在不使用 Cocoa 的关联引用的情况下做同样的事情;它只会更丑陋,而且效率可能更低。在 Objective-C++ 中它会变成这样。(我什至不会尝试用 Objective-C 编写它,因为CFMutableDictionary两者NSMutableDictionary在几个层面上都有错误的行为,而且我不会从头开始编写整个东西。但是,C++std::map不能以我想使用的方式与__weak引用一起使用,所以我回退到这种低效std::vector的算法。对于那些不熟悉 C++ 的人:std::vector大致相当于 an 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/

于 2012-10-28T19:41:00.297 回答
-1

git 上有一个示例代码!点击这里

于 2013-08-25T05:08:41.587 回答