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

2024-01-10

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(使用前将#替换为@)

如何在 Obj-C 类别中“伪造”ivars (iPhone) 的相关文章

随机推荐

  • 如何自定义FBLoginVIew?

    为了在我的 ios 应用程序中连接到 facebook 我正在使用 FBLoginVIew适用于 iOS 的 Facebook SDK http developers facebook com docs sdk reference ioss
  • 在ggplot2facet_grid中旋转切换的facet标签

    我想使用facet grid 在彼此之上绘制一些条形图 library ggplot2 df lt group by mpg manufacturer gt summarise cty mean cty hwy mean hwy gt un
  • 我希望 shell 脚本可执行但不可读

    我创建了一个脚本 我希望其他用户使用我们的共享系统 to 执行但不读取 我将权限设置为所有可执行文件 但撤销了读 写权限 x x x 1 dilletante staff 0 2013 04 02 11 42 expect sh 然而脚本无
  • 使用 lambda 表达式参数调用泛型方法的反射

    我正在寻找一种使用 lambda 表达式调用通用方法的方法 该表达式在项目数组中调用 Contains 在本例中 我使用实体框架Where方法 但该场景可以应用于其他IEnumerables 我需要通过 Reflection 调用上面代码的
  • 如何检查 SQL Server 当前池大小

    有没有办法检查 SQL Server 中当前连接池的大小 我不是在谈论最大连接池大小 而是当前池大小 假设最大池大小为 100 并且有 49 个打开的连接 它现在应该显示 51 个可用连接或 49 个已消耗连接 那么 有这样的查询吗 其中很
  • Golang写入套接字而不用担心数据不完整

    我们都知道 Write 方法不能保证从缓冲区中写入高字节 因此 使用原始 Write 方法将字节写入套接字的规范方法如下所示 how many bytes we have written written 0 for written lt l
  • 无法让 QWindow::fromWinId 正常工作

    我的 Qt 5 9 程序 在 X11 Linux 上 使用以下命令启动其他应用程序QProcess 我想控制这些应用程序生成的窗口 所以我获得了它们winId价值和用途QWindow fromWinId得到一个QWindow实例 问题是这些
  • Laravel $request->expectsJson()

    我正在为我的 Laravel 应用程序进行 Ajax 登录 我正在使用角度 http method POST url admin login headers Content Type application json data email
  • 如何读取图像上的文字?

    我需要将一些扫描文档解析为文本数据 是否可以使用某些软件解析图像上写的文本 如果是 请推荐任何此类在线实用程序或软件 也许一些 OCR 软件会有帮助 http en wikipedia org wiki Optical character
  • 忽略“证书未知”警报

    我有以下简单的 Python 脚本 import socket import ssl if name main s socket socket socket AF INET socket SOCK STREAM s bind 443 s l
  • 销毁 Bootstrap 弹出窗口时出现 Javascript 错误

    尝试随时更改引导程序弹出窗口的标题和内容 我遇到了一些麻烦 我在销毁选择器中的弹出窗口内容时遇到此问题 错误是这样的 TypeError undefined is not a function evaluating data option
  • T-SQL删除插入的记录

    我知道标题可能看起来很奇怪 但这就是我想做的 我有很多记录的表 我想获取其中一些记录并将它们插入到其他表中 像这样的东西 INSERT INTO TableNew SELECT FROM TableOld WHERE 棘手的部分是我希望我插
  • Jquery UI 工具提示不支持 html 内容

    今天 我将所有 jQuery 插件升级为 jQuery 1 9 1 我开始将 jQueryUI 工具提示与 jquery ui 1 10 2 一起使用 一切都很好 但是当我在内容中使用 HTML 标签时 在title我正在应用工具提示的元素
  • 我怎样才能使这个模式持久化?

    我正在寻找一种方法 让这种模式在出现后持久存在 正如此处所示 用户只需在 div 外部单击一下即可将其关闭
  • 如何制作一个反应本机输入,向用户提供验证状态反馈。 [有效、Printine、错误、编辑]

    我希望输入能够随着用户键入而不断更新 然后失去焦点 反馈将是输入周围的边框 1 Green when valid 2 Amber when typing and is in error state Green when valid 3 Re
  • 一面一示例 T 测试 Python

    在 Python 中 我使用 SciPy 进行单样本 t 检验 from scipy import stats one sample data 177 3 182 7 169 6 176 3 180 3 179 4 178 5 177 2
  • Checkstyles + Gradle 抛出引起:java.lang.IllegalArgumentException:给定名称 COMPACT_CTOR_DEF

    我最近将 checkstyle 插件添加到项目中以进行静态代码分析 但更新之后google style xml从最新的大师那里 我开始收到以下异常 org gradle api tasks TaskExecutionException Ex
  • grails 2.0 - 正确使用 serverURL 进行生产?

    Grails 2 0 改变了它使用 grails serverURL 进行开发和测试环境的方式 如manual http grails org doc 2 0 x guide single html upgradingFromPreviou
  • Python从视频文件中提取wav

    Related 如何使用python从视频文件中提取音频 https stackoverflow com questions 19216450 how to extract audio from a video file using pyt
  • 如何在 Obj-C 类别中“伪造”ivars (iPhone)

    Update iPhone OS 3 1 有关联的对象 然而 iPhone 模拟器却没有 如果您想在模拟器中测试关联的对象代码 您应该提交错误 请参阅我的问题here https stackoverflow com questions 19