Update:
iPhone OS 3.1 有关联的对象。然而,iPhone 模拟器却没有。如果您想在模拟器中测试关联的对象代码,您应该提交错误。
请参阅我的问题here https://stackoverflow.com/questions/1916130/objcsetassociatedobject-unavailable-in-iphone-simulator.
雷达://7477326
雪豹现在有关联的对象。
有没有办法在没有关联对象的情况下完成类似的事情? (特别适用于 iPhone。)
我很确定我不久前见过类似的东西,但我不记得在哪里。关于将任何对象变成 KVC 容器的事情。
objc_setAssociatedObject() 和朋友已添加到 iPhone OS 3.1,因此,如果您可以选择仅针对 3.1+ 设备,您实际上可以执行与 Snow Leopard 完全相同的操作...
如果你不能,你可以创建一个静态关联字典并猴子修补 NSObjects dealloc 方法。由于各种技术原因,该解决方案无法在 GC 存在的情况下正常工作(这就是苹果添加关联内容的原因),但由于 iPhone 不支持 GC,所以这不是问题。
如果您刚刚开始此项目的工作,我强烈建议您使用运行时函数并以 3.1 plus 为目标,但如果这不是一个选项,这里有一个示例说明您如何执行此操作。
LGAssociativeStorage.h:
#import <pthread.h>
#import <Foundation/Foundation.h>
@interface NSObject (LGAssociativeStorage)
@property (retain) id associatedObject;
@end
LG关联存储.mm
#import <objc/runtime.h>
#import "LGAssociativeStorage.h"
/* We are using STL containers because:
1) Using Objective C containers can cause deallocs which cause recursion issues
2) STL containers are high perf containers that don't introduce external code dependencies
Ideally one could include a thread safe map implementation, but I don't need one currently
*/
#include <map>
typedef std::map<id,id> idMap_t;
typedef std::pair<id,id> idPair_t;
static NSMutableDictionary * data = nil;
static pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER;
static IMP gOriginalNSObjectDealloc = nil;
static idMap_t associatedObjectMap;
static
void removeAssociatedObjectFromMap(id self) {
idMap_t::iterator iter = associatedObjectMap.find(self);
if( iter != associatedObjectMap.end() ) {
[iter->second release];
associatedObjectMap.erase(iter);
}
}
static
id newNSObjectDealloc(id self, SEL deallocSelector, ...) {
pthread_mutex_lock(&data_lock);
removeAssociatedObjectFromMap(self);
pthread_mutex_unlock(&data_lock);
return gOriginalNSObjectDealloc(self, deallocSelector);
}
static void initIfNecessary(void) {
if (!data) {
data = [[NSMutableDictionary alloc] init];
// The below line of code is abusive... in the future the Objective C runtime will use it as evidence
// that I am an unfit software engineer and take custody of all my code
gOriginalNSObjectDealloc = class_replaceMethod([NSObject class], @selector(dealloc), newNSObjectDealloc, "v@:");
}
}
@implementation NSObject (LGAssociativeStorage)
- (id) associatedObject {
id retval = nil;
pthread_mutex_lock(&data_lock);
initIfNecessary();
idMap_t::iterator iter = associatedObjectMap.find(self);
if( iter != associatedObjectMap.end() ) {
retval = iter->second;
}
pthread_mutex_unlock(&data_lock);
return retval;
}
- (void) setAssociatedObject:(id)object_ {
pthread_mutex_lock(&data_lock);
initIfNecessary();
removeAssociatedObjectFromMap(self);
[object_ retain];
associatedObjectMap.insert(idPair_t(self, object_));
pthread_mutex_unlock(&data_lock);
}
@end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)