如何在Obj-C类别中“伪造”ivars(iPhone)

前端之家收集整理的这篇文章主要介绍了如何在Obj-C类别中“伪造”ivars(iPhone)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
更新:

iPhone OS 3.1具有关联的对象.但是,iPhone模拟器没有.如果要在模拟器中测试关联对象代码,则应该提交错误.

看我的问题here.

rdar:// 7477326

Snow Leopard现在有相关的对象.

有没有办法在没有相关对象的情况下完成类似的事情? (专门针对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

LGAssociativeStorage.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

猜你在找的C&C++相关文章