iPhone 模拟器中的 objc_setAssociatedObject 不可用

Posted

技术标签:

【中文标题】iPhone 模拟器中的 objc_setAssociatedObject 不可用【英文标题】:objc_setAssociatedObject unavailable in iPhone simulator 【发布时间】:2010-12-27 07:57:51 【问题描述】:

在 3.1 SDk 中,Apple 添加了对关联对象的支持。

但是,模拟器不会编译包含对 objc_setAssociatedObject、objc_getAssociatedObject 等的引用的代码。 (未声明的错误)

这附近有吗?我可以让 iPhone 模拟器编译这段代码吗?我不想在设备上进行所有测试。


更新

提交的错误: rdar://7477326

【问题讨论】:

你是使用 10.5 还是 10.6 进行开发? 请通过bugreport.apple.com 提交错误并编辑您的问题以包含#。 谢谢。错误归档,rdar://7477326 【参考方案1】:

我认为这不会在 3.x SDK 中得到解决,因此另一个解决方法是仅定义函数并通过动态查找调用下一个定义。

标题:

#if TARGET_IPHONE_SIMULATOR
enum 
    OBJC_ASSOCIATION_ASSIGN = 0,
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
    OBJC_ASSOCIATION_RETAIN = 01401,
    OBJC_ASSOCIATION_COPY = 01403
;
typedef uintptr_t objc_AssociationPolicy;

void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, void *key);
void objc_removeAssociatedObjects(id object);
#endif

实施:

#if TARGET_IPHONE_SIMULATOR
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy) 
    ((void (*)(id, void *, id, objc_AssociationPolicy))
     dlsym(RTLD_NEXT, "objc_setAssociatedObject")) (object, key, value, policy);

id objc_getAssociatedObject(id object, void *key) 
    return ((id (*)(id, void *))
            dlsym(RTLD_NEXT, "objc_getAssociatedObject"))(object, key);

void objc_removeAssociatedObjects(id object) 
    ((void (*)(id))
     dlsym(RTLD_NEXT, "objc_removeAssociatedObjects"))(object);

#endif

【讨论】:

谢谢!我还必须添加 #define _GNU_SOUCE 来解析 RTLD_NEXT。【参考方案2】:

一种快速而肮脏的解决方法(大部分未经测试,可能有问题):

#if TARGET_IPHONE_SIMULATOR

#import <objc/runtime.h>

enum 
    OBJC_ASSOCIATION_ASSIGN = 0,
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
    OBJC_ASSOCIATION_RETAIN = 01401,
    OBJC_ASSOCIATION_COPY = 01403
;
typedef uintptr_t objc_AssociationPolicy;

@implementation NSObject (OTAssociatedObjectsSimulator)

static CFMutableDictionaryRef theDictionaries = nil;

static void Swizzle(Class c, SEL orig, SEL new) // swizzling by Mike Ash

    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);
    if (class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
        method_exchangeImplementations(origMethod, newMethod);


- (NSMutableDictionary *)otAssociatedObjectsDictionary

    if (!theDictionaries)
    
        theDictionaries = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
        Swizzle([NSObject class], @selector(dealloc), @selector(otAssociatedObjectSimulatorDealloc));
    

    NSMutableDictionary *dictionary = (id)CFDictionaryGetValue(theDictionaries, self);
    if (!dictionary)
    
        dictionary = [NSMutableDictionary dictionary];
        CFDictionaryAddValue(theDictionaries, self, dictionary);
    

    return dictionary;


- (void)otAssociatedObjectSimulatorDealloc

    CFDictionaryRemoveValue(theDictionaries, self);
    [self otAssociatedObjectSimulatorDealloc];


@end

void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)

    NSCAssert(policy == OBJC_ASSOCIATION_RETAIN_NONATOMIC, @"Only OBJC_ASSOCIATION_RETAIN_NONATOMIC supported");

    [[object otAssociatedObjectsDictionary] setObject:value forKey:[NSValue valueWithPointer:key]];


id objc_getAssociatedObject(id object, void *key)

    return [[object otAssociatedObjectsDictionary] objectForKey:[NSValue valueWithPointer:key]];


void objc_removeAssociatedObjects(id object)

    [[object otAssociatedObjectsDictionary] removeAllObjects];


#endif

【讨论】:

以上是关于iPhone 模拟器中的 objc_setAssociatedObject 不可用的主要内容,如果未能解决你的问题,请参考以下文章

PrototypeCell 中的 UITextView 在两个 iPhone 模拟器中具有不同的行为

如何解决图像未显示在模拟器或 iPhone for Xcode 中的问题

Xcode 8.2.1 中的 iPhone 模拟器运行速度有点慢 [关闭]

Xcode中的iPhone模拟器是否支持蓝牙低功耗?

iPhone 模拟器中的 objc_setAssociatedObject 不可用

iPhone设备中的Json Parse错误,但在模拟器中正确