簡體   English   中英

objc_setAssociatedObject在iPhone模擬器中不可用

[英]objc_setAssociatedObject unavailable in iPhone simulator

在3.1 SDk中,Apple添加了對關聯對象的支持。

但是,模擬器不會編譯包含對objc_setAssociatedObject,objc_getAssociatedObject等的引用的代碼。 (未聲明的錯誤)

有沒有解決的辦法? 我可以讓iPhone模擬器編譯此代碼嗎? 我討厭必須在設備上進行所有測試。


更新資料

提起錯誤:rdar:// 7477326

我認為這不會在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

快速而骯臟的解決方法(大部分未經測試,可能有錯誤):

#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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM