Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Adding MAZeroingWeakRef namespaced.

  • Loading branch information...
commit 83bb5263345d0d3c67a4188c14d39d5b5e31726e 1 parent de4d45b
@gabriel authored
View
73 Classes/MAZeroingWeakRef/GH_MAZeroingWeakRef.h
@@ -0,0 +1,73 @@
+//
+// GH_MAZeroingWeakRef.h
+// ZeroingWeakRef
+//
+// Created by Michael Ash on 7/5/10.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface GH_MAZeroingWeakRef : NSObject
+{
+ id _target;
+ BOOL _nativeZWR;
+#if NS_BLOCKS_AVAILABLE
+ void (^_cleanupBlock)(id target);
+#endif
+}
+
++ (BOOL)canRefCoreFoundationObjects;
+
++ (id)refWithTarget: (id)target;
+
+- (id)initWithTarget: (id)target;
+
+#if NS_BLOCKS_AVAILABLE
+// ON 10.7:
+// cleanup block runs while the target's memory is still
+// allocated but after all dealloc methods have run
+// (it runs at associated object cleanup time)
+// you can use the target's pointer value but don't
+// manipulate its contents!
+
+// ON 10.6 AND BELOW:
+// cleanup block runs while the global ZWR lock is held
+// so make it short and sweet!
+// use GCD or something to schedule execution later
+// if you need to do something that may take a while
+//
+// it is unsafe to call -target on the weak ref from
+// inside the cleanup block, which is why the target
+// is passed in as a parameter
+// note that you must not resurrect the target at this point!
+- (void)setCleanupBlock: (void (^)(id target))block;
+#endif
+
+- (id)target;
+
+@end
+
+#ifndef __has_feature
+#define __has_feature(feature) 0
+#endif
+
+#define GH_MAWeakVar(var) __weak_ ## var
+
+#if __has_feature(objc_arc_weak)
+
+#define GH_MAWeakDeclare(var) __weak __typeof__((var)) GH_MAWeakVar(var) = var
+#define GH_MAWeakImport(var) __typeof__((GH_MAWeakVar(var))) var = GH_MAWeakVar(var)
+#define GH_MAWeakImportReturn(var) GH_MAWeakImport(var); do { if(var == nil) return; } while(NO)
+
+#else
+
+#define GH_MAWeakDeclare(var) __typeof__((var)) GH_MAWeakVar(var) = (id)[GH_MAZeroingWeakRef refWithTarget:var]
+#define GH_MAWeakImport(var) __typeof__((GH_MAWeakVar(var))) var = [(GH_MAZeroingWeakRef *)GH_MAWeakVar(var) target]
+#define GH_MAWeakImportReturn(var) GH_MAWeakImport(var); do { if(var == nil) return; } while(NO)
+
+#endif
+
+#define GH_MAWeakSelfDeclare() GH_MAWeakDeclare(self)
+#define GH_MAWeakSelfImport() GH_MAWeakImport(self)
+#define GH_MAWeakSelfImportReturn() GH_MAWeakImportReturn(self)
View
862 Classes/MAZeroingWeakRef/GH_MAZeroingWeakRef.m
@@ -0,0 +1,862 @@
+//
+// GH_MAZeroingWeakRef.m
+// ZeroingWeakRef
+//
+// Created by Michael Ash on 7/5/10.
+//
+
+#import "GH_MAZeroingWeakRef.h"
+
+#import "GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h"
+
+#if __APPLE__
+#import <CommonCrypto/CommonDigest.h>
+
+#import <dlfcn.h>
+#import <libkern/OSAtomic.h>
+#import <objc/runtime.h>
+#import <mach/mach.h>
+#import <mach/port.h>
+#import <pthread.h>
+#else
+#import <pthread.h>
+#endif
+
+
+/*
+ The COREFOUNDATION_HACK_LEVEL macro allows you to control how much horrible CF
+ hackery is enabled. The following levels are defined:
+
+ 3 - Completely insane hackery allows weak references to CF objects, deallocates
+ them asynchronously in another thread to eliminate resurrection-related race
+ condition and crash.
+
+ 2 - Full hackery allows weak references to CF objects by doing horrible
+ things with the private CF class table. Extremely small risk of resurrection-
+ related race condition leading to a crash.
+
+ 1 - Mild hackery allows foolproof identification of CF objects and will assert
+ if trying to make a ZWR to one.
+
+ 0 - No hackery, checks for an "NSCF" prefix in the class name to identify CF
+ objects and will assert if trying to make a ZWR to one
+ */
+#ifndef COREFOUNDATION_HACK_LEVEL
+#define COREFOUNDATION_HACK_LEVEL 0
+#endif
+
+/*
+ The KVO_HACK_LEVEL macro allows similar control over the amount of KVO hackery.
+
+ 1 - Use the private _isKVOA method to check for a KVO dynamic subclass.
+
+ 0 - No hackery, uses the KVO overridden -class to check.
+ */
+#ifndef KVO_HACK_LEVEL
+#define KVO_HACK_LEVEL 0
+#endif
+
+/*
+ The USE_BLOCKS_BASED_LOCKING macro allows control on the code structure used
+ during lock checking. You want to disable blocks if you want your app to work
+ on iOS 3.x devices. iOS 4.x and above can use blocks.
+
+ 1 - Use blocks for lock checks.
+
+ 0 - Don't use blocks for lock checks.
+ */
+#ifndef USE_BLOCKS_BASED_LOCKING
+#define USE_BLOCKS_BASED_LOCKING 1
+#endif
+
+#if KVO_HACK_LEVEL >= 1
+@interface NSObject (KVOPrivateMethod)
+
+- (BOOL)_isKVOA;
+
+@end
+#endif
+
+
+static void EnsureCustomSubclass(id obj);
+
+@interface GH_MAZeroingWeakRef ()
+
+- (void)_zeroTarget;
+- (void)_executeCleanupBlockWithTarget: (id)target;
+
+@end
+
+
+static id (*objc_loadWeak_fptr)(id *location);
+static id (*objc_storeWeak_fptr)(id *location, id obj);
+
+@interface _GH_MAZeroingWeakRefCleanupHelper : NSObject
+{
+ GH_MAZeroingWeakRef *_ref;
+ id _target;
+}
+
+- (id)initWithRef: (GH_MAZeroingWeakRef *)ref target: (id)target;
+
+@end
+
+@implementation _GH_MAZeroingWeakRefCleanupHelper
+
+- (id)initWithRef: (GH_MAZeroingWeakRef *)ref target: (id)target
+{
+ if((self = [self init]))
+ {
+ objc_storeWeak_fptr(&_ref, ref);
+ _target = target;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ GH_MAZeroingWeakRef *ref = objc_loadWeak_fptr(&_ref);
+ [ref _executeCleanupBlockWithTarget: _target];
+ objc_storeWeak_fptr(&_ref, nil);
+
+ [super dealloc];
+}
+
+@end
+
+
+@implementation GH_MAZeroingWeakRef
+
+#if COREFOUNDATION_HACK_LEVEL >= 2
+
+typedef struct __CFRuntimeClass { // Version 0 struct
+ CFIndex version;
+ const char *className;
+ void (*init)(CFTypeRef cf);
+ CFTypeRef (*copy)(CFAllocatorRef allocator, CFTypeRef cf);
+ void (*finalize)(CFTypeRef cf);
+ Boolean (*equal)(CFTypeRef cf1, CFTypeRef cf2);
+ CFHashCode (*hash)(CFTypeRef cf);
+ CFStringRef (*copyFormattingDesc)(CFTypeRef cf, CFDictionaryRef formatOptions); // str with retain
+ CFStringRef (*copyDebugDesc)(CFTypeRef cf); // str with retain
+ void (*reclaim)(CFTypeRef cf);
+} CFRuntimeClass;
+
+extern CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID);
+
+typedef void (*CFFinalizeFptr)(CFTypeRef);
+static CFFinalizeFptr *gCFOriginalFinalizes;
+static size_t gCFOriginalFinalizesSize;
+
+#endif
+
+#if COREFOUNDATION_HACK_LEVEL >= 1
+
+extern Class *__CFRuntimeObjCClassTable;
+
+#endif
+
+static pthread_mutex_t gMutex;
+
+#if __APPLE__
+static CFMutableDictionaryRef gObjectWeakRefsMap; // maps (non-retained) objects to CFMutableSetRefs containing weak refs
+#else
+static NSMapTable *gObjectWeakRefsMap;
+#endif
+
+static NSMutableSet *gCustomSubclasses;
+static NSMutableDictionary *gCustomSubclassMap; // maps regular classes to their custom subclasses
+
+#if COREFOUNDATION_HACK_LEVEL >= 3
+static CFMutableSetRef gCFWeakTargets;
+static NSOperationQueue *gCFDelayedDestructionQueue;
+#endif
+
++ (void)initialize
+{
+ if(self == [GH_MAZeroingWeakRef class])
+ {
+ pthread_mutexattr_t mutexattr;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&gMutex, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+
+#if __APPLE__
+ gObjectWeakRefsMap = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
+#else
+ gObjectWeakRefsMap = [[NSMapTable mapTableWithWeakToStrongObjects] retain];
+#endif
+ gCustomSubclasses = [[NSMutableSet alloc] init];
+ gCustomSubclassMap = [[NSMutableDictionary alloc] init];
+
+ // see if the 10.7 ZWR runtime functions are available
+ // nothing special about objc_allocateClassPair, it just
+ // seems like a reasonable and safe choice for finding
+ // the runtime functions
+#if __APPLE__
+ Dl_info info;
+ int success = dladdr(objc_allocateClassPair, &info);
+ if(success)
+ {
+ // note: we leak the handle because it's inconsequential
+ // and technically, the fptrs would be invalid after a dlclose
+ void *handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_GLOBAL);
+ if(handle)
+ {
+ objc_loadWeak_fptr = dlsym(handle, "objc_loadWeak");
+ objc_storeWeak_fptr = dlsym(handle, "objc_storeWeak");
+
+ // if either one failed, make sure both are zeroed out
+ // this is probably unnecessary, but good paranoia
+ if(!objc_loadWeak_fptr || !objc_storeWeak_fptr)
+ {
+ objc_loadWeak_fptr = NULL;
+ objc_storeWeak_fptr = NULL;
+ }
+ }
+ }
+#endif
+
+#if COREFOUNDATION_HACK_LEVEL >= 3
+ gCFWeakTargets = CFSetCreateMutable(NULL, 0, NULL);
+ gCFDelayedDestructionQueue = [[NSOperationQueue alloc] init];
+#endif
+ }
+}
+
+#if USE_BLOCKS_BASED_LOCKING
+#define BLOCK_QUALIFIER __block
+static void WhileLocked(void (^block)(void))
+{
+ pthread_mutex_lock(&gMutex);
+ block();
+ pthread_mutex_unlock(&gMutex);
+}
+#define WhileLocked(block) WhileLocked(^block)
+#else
+#define BLOCK_QUALIFIER
+#define WhileLocked(block) do { \
+ pthread_mutex_lock(&gMutex); \
+ block \
+ pthread_mutex_unlock(&gMutex); \
+ } while(0)
+#endif
+
+static void AddWeakRefToObject(id obj, GH_MAZeroingWeakRef *ref)
+{
+#if __APPLE__
+ CFMutableSetRef set = (void *)CFDictionaryGetValue(gObjectWeakRefsMap, obj);
+ if(!set)
+ {
+ set = CFSetCreateMutable(NULL, 0, NULL);
+ CFDictionarySetValue(gObjectWeakRefsMap, obj, set);
+ CFRelease(set);
+ }
+ CFSetAddValue(set, ref);
+#else
+ NSHashTable *set = [gObjectWeakRefsMap objectForKey:obj];
+ if (!set)
+ {
+ set = [NSHashTable hashTableWithWeakObjects];
+ [gObjectWeakRefsMap setObject:set forKey:obj];
+ }
+ [set addObject:ref];
+#endif
+}
+
+static void RemoveWeakRefFromObject(id obj, GH_MAZeroingWeakRef *ref)
+{
+#if __APPLE__
+ CFMutableSetRef set = (void *)CFDictionaryGetValue(gObjectWeakRefsMap, obj);
+ CFSetRemoveValue(set, ref);
+#else
+ NSHashTable *set = [gObjectWeakRefsMap objectForKey:obj];
+ [set removeObject:ref];
+#endif
+}
+
+static void ClearWeakRefsForObject(id obj)
+{
+#if __APPLE__
+ CFMutableSetRef set = (void *)CFDictionaryGetValue(gObjectWeakRefsMap, obj);
+ if(set)
+ {
+ NSSet *setCopy = [[NSSet alloc] initWithSet: (NSSet *)set];
+ [setCopy makeObjectsPerformSelector: @selector(_zeroTarget)];
+ [setCopy makeObjectsPerformSelector: @selector(_executeCleanupBlockWithTarget:) withObject: obj];
+ [setCopy release];
+ CFDictionaryRemoveValue(gObjectWeakRefsMap, obj);
+ }
+#else
+ NSHashTable *set = [gObjectWeakRefsMap objectForKey:obj];
+ if (set)
+ {
+ NSArray *setContents = [set allObjects];
+ [setContents makeObjectsPerformSelector:@selector(_zeroTarget)];
+ [setContents makeObjectsPerformSelector:@selector(_executeCleanupBlockWithTarget:) withObject:obj];
+ [gObjectWeakRefsMap removeObjectForKey:obj];
+ }
+#endif
+}
+
+static Class GetCustomSubclass(id obj)
+{
+ Class class = object_getClass(obj);
+ while(class && ![gCustomSubclasses containsObject: class])
+ class = class_getSuperclass(class);
+ return class;
+}
+
+static Class GetRealSuperclass(id obj)
+{
+ Class class = GetCustomSubclass(obj);
+ NSCAssert1(class, @"Coudn't find ZeroingWeakRef subclass in hierarchy starting from %@, should never happen", object_getClass(obj));
+ return class_getSuperclass(class);
+}
+
+static void CustomSubclassRelease(id self, SEL _cmd)
+{
+ Class superclass = GetRealSuperclass(self);
+ IMP superRelease = class_getMethodImplementation(superclass, @selector(release));
+ WhileLocked({
+ ((void (*)(id, SEL))superRelease)(self, _cmd);
+ });
+}
+
+static void CustomSubclassDealloc(id self, SEL _cmd)
+{
+ ClearWeakRefsForObject(self);
+ Class superclass = GetRealSuperclass(self);
+ IMP superDealloc = class_getMethodImplementation(superclass, @selector(dealloc));
+ ((void (*)(id, SEL))superDealloc)(self, _cmd);
+}
+
+static Class CustomSubclassClassForCoder(id self, SEL _cmd)
+{
+ Class class = GetCustomSubclass(self);
+ Class superclass = class_getSuperclass(class);
+ IMP superClassForCoder = class_getMethodImplementation(superclass, @selector(classForCoder));
+ Class classForCoder = ((id (*)(id, SEL))superClassForCoder)(self, _cmd);
+ if(classForCoder == class)
+ classForCoder = superclass;
+ return classForCoder;
+}
+
+static void KVOSubclassRelease(id self, SEL _cmd)
+{
+ IMP originalRelease = class_getMethodImplementation(object_getClass(self), @selector(GH_MAZeroingWeakRef_KVO_original_release));
+ WhileLocked({
+ ((void (*)(id, SEL))originalRelease)(self, _cmd);
+ });
+}
+
+static void KVOSubclassDealloc(id self, SEL _cmd)
+{
+ ClearWeakRefsForObject(self);
+ IMP originalDealloc = class_getMethodImplementation(object_getClass(self), @selector(GH_MAZeroingWeakRef_KVO_original_dealloc));
+ ((void (*)(id, SEL))originalDealloc)(self, _cmd);
+}
+
+static void KVOSubclassRemoveObserverForKeyPath(id self, SEL _cmd, id observer, NSString *keyPath)
+{
+ WhileLocked({
+ IMP originalIMP = class_getMethodImplementation(object_getClass(self), @selector(GH_MAZeroingWeakRef_KVO_original_removeObserver:forKeyPath:));
+ ((void (*)(id, SEL, id, NSString *))originalIMP)(self, _cmd, observer, keyPath);
+
+ EnsureCustomSubclass(self);
+ });
+}
+
+static void KVOSubclassRemoveObserverForKeyPathContext(id self, SEL _cmd, id observer, NSString *keyPath, void *context)
+{
+ WhileLocked({
+ IMP originalIMP = class_getMethodImplementation(object_getClass(self), @selector(GH_MAZeroingWeakRef_KVO_original_removeObserver:forKeyPath:context:));
+ ((void (*)(id, SEL, id, NSString *, void *))originalIMP)(self, _cmd, observer, keyPath, context);
+
+ EnsureCustomSubclass(self);
+ });
+}
+
+#if COREFOUNDATION_HACK_LEVEL >= 3
+
+static void CallCFReleaseLater(CFTypeRef cf)
+{
+ mach_port_t thread = mach_thread_self(); // must "release" this
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ SEL sel = @selector(releaseLater:fromThread:);
+ NSInvocation *inv = [NSInvocation invocationWithMethodSignature: [GH_MAZeroingWeakRef methodSignatureForSelector: sel]];
+ [inv setTarget: [GH_MAZeroingWeakRef class]];
+ [inv setSelector: sel];
+ [inv setArgument: &cf atIndex: 2];
+ [inv setArgument: &thread atIndex: 3];
+
+ NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithInvocation: inv];
+ [gCFDelayedDestructionQueue addOperation: op];
+ [op release];
+ [pool release];
+}
+
+static const void *kPCThreadExited = &kPCThreadExited;
+static const void *kPCError = NULL;
+
+static const void *GetPC(mach_port_t thread)
+{
+#if defined(__x86_64__)
+ x86_thread_state64_t state;
+ unsigned int count = x86_THREAD_STATE64_COUNT;
+ thread_state_flavor_t flavor = x86_THREAD_STATE64;
+#define PC_REGISTER __rip
+#elif defined(__i386__)
+ i386_thread_state_t state;
+ unsigned int count = i386_THREAD_STATE_COUNT;
+ thread_state_flavor_t flavor = i386_THREAD_STATE;
+#define PC_REGISTER __eip
+#elif defined(__arm__)
+ arm_thread_state_t state;
+ unsigned int count = ARM_THREAD_STATE_COUNT;
+ thread_state_flavor_t flavor = ARM_THREAD_STATE;
+#define PC_REGISTER __pc
+#elif defined(__ppc__)
+ ppc_thread_state_t state;
+ unsigned int count = PPC_THREAD_STATE_COUNT;
+ thread_state_flavor_t flavor = PPC_THREAD_STATE;
+#define PC_REGISTER __srr0
+#elif defined(__ppc64__)
+ ppc_thread_state64_t state;
+ unsigned int count = PPC_THREAD_STATE64_COUNT;
+ thread_state_flavor_t flavor = PPC_THREAD_STATE64;
+#define PC_REGISTER __srr0
+#else
+#error don't know how to get PC for the current architecture!
+#endif
+
+ kern_return_t ret = thread_get_state(thread, flavor, (thread_state_t)&state, &count);
+ if(ret == KERN_SUCCESS)
+ return (void *)state.PC_REGISTER;
+ else if(ret == KERN_INVALID_ARGUMENT)
+ return kPCThreadExited;
+ else
+ return kPCError;
+}
+
+static void CustomCFFinalize(CFTypeRef cf)
+{
+ WhileLocked({
+ if(CFSetContainsValue(gCFWeakTargets, cf))
+ {
+ if(CFGetRetainCount(cf) == 1)
+ {
+ ClearWeakRefsForObject((id)cf);
+ CFSetRemoveValue(gCFWeakTargets, cf);
+ CFRetain(cf);
+ CallCFReleaseLater(cf);
+ }
+ }
+ else
+ {
+ void (*fptr)(CFTypeRef) = gCFOriginalFinalizes[CFGetTypeID(cf)];
+ if(fptr)
+ fptr(cf);
+ }
+ });
+}
+
+#elif COREFOUNDATION_HACK_LEVEL >= 2
+
+static void CustomCFFinalize(CFTypeRef cf)
+{
+ WhileLocked({
+ if(CFGetRetainCount(cf) == 1)
+ {
+ ClearWeakRefsForObject((id)cf);
+ void (*fptr)(CFTypeRef) = gCFOriginalFinalizes[CFGetTypeID(cf)];
+ if(fptr)
+ fptr(cf);
+ }
+ });
+}
+#endif
+
+static BOOL IsTollFreeBridged(Class class, id obj)
+{
+#if COREFOUNDATION_HACK_LEVEL >= 1
+ CFTypeID typeID = CFGetTypeID(obj);
+ Class tfbClass = __CFRuntimeObjCClassTable[typeID];
+ return class == tfbClass;
+#else
+ NSString *className = NSStringFromClass(class);
+ return [className hasPrefix:@"NSCF"] || [className hasPrefix:@"__NSCF"];
+#endif
+}
+
+static BOOL IsConstantObject(id obj)
+{
+ unsigned int retainCount = [obj retainCount];
+ return retainCount == UINT_MAX || retainCount == INT_MAX;
+}
+
+#if COREFOUNDATION_HACK_LEVEL >= 3
+void _CFRelease(CFTypeRef cf);
+
++ (void)releaseLater: (CFTypeRef)cf fromThread: (mach_port_t)thread
+{
+ BOOL retry = YES;
+
+ while(retry)
+ {
+ BLOCK_QUALIFIER const void *pc;
+ // ensure that the PC is outside our inner code when fetching it,
+ // so we don't have to check for all the nested calls
+ WhileLocked({
+ pc = GetPC(thread);
+ });
+
+ if(pc != kPCError)
+ {
+ if(pc == kPCThreadExited || pc < (void *)CustomCFFinalize || pc > (void *)IsTollFreeBridged)
+ {
+ Dl_info info;
+ int success = dladdr(pc, &info);
+ if(success)
+ {
+ if(info.dli_saddr != _CFRelease)
+ {
+ retry = NO; // success!
+ CFRelease(cf);
+ mach_port_mod_refs(mach_task_self(), thread, MACH_PORT_RIGHT_SEND, -1 ); // "release"
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
+static BOOL IsKVOSubclass(id obj)
+{
+#if KVO_HACK_LEVEL >= 1
+ return [obj respondsToSelector: @selector(_isKVOA)] && [obj _isKVOA];
+#else
+ return [obj class] == class_getSuperclass(object_getClass(obj));
+#endif
+}
+
+// The native ZWR capability table is conceptually a set of SHA1 hashes.
+// Hashes are used instead of class names because the table is large and
+// contains a lot of private classes. Embedding private class names in
+// the binary is likely to cause problems with app review. Manually
+// removing all private classes from the table is a lot of work. Using
+// hashes allows for reasonably quick checks and no private API names.
+// It's implemented as a tree of tables, where each individual table
+// maps to a single byte. The top level of the tree is a 256-entry table.
+// Table entries are a NULL pointer for leading bytes which aren't present
+// at all. Other table entries can either contain a pointer to another
+// table (in which case the process continues recursively), or they can
+// contain a pointer to a single hash. In this second case, this indicates
+// that this hash is the only one present in the table with that prefix
+// and so a simple comparison can be used to check for membership at
+// that point.
+#if __APPLE__
+static BOOL HashPresentInTable(unsigned char *hash, int length, struct _NativeZWRTableEntry *table)
+{
+ while(length)
+ {
+ struct _NativeZWRTableEntry entry = table[hash[0]];
+ if(entry.ptr == NULL)
+ {
+ return NO;
+ }
+ else if(!entry.isTable)
+ {
+ return memcmp(entry.ptr, hash + 1, length - 1) == 0;
+ }
+ else
+ {
+ hash++;
+ length--;
+ table = entry.ptr;
+ }
+ }
+ return NO;
+}
+#endif
+
+static BOOL CanNativeZWRClass(Class c)
+{
+#if __APPLE__
+ if(!c)
+ return YES;
+
+ const char *name = class_getName(c);
+ unsigned char hash[CC_SHA1_DIGEST_LENGTH];
+ CC_SHA1(name, strlen(name), hash);
+
+ if(HashPresentInTable(hash, CC_SHA1_DIGEST_LENGTH, _GH_MAZeroingWeakRefClassNativeWeakReferenceNotAllowedTable))
+ return NO;
+ else
+ return CanNativeZWRClass(class_getSuperclass(c));
+#else
+ return NO;
+#endif
+}
+
+static BOOL CanNativeZWR(id obj)
+{
+ return CanNativeZWRClass(object_getClass(obj));
+}
+
+static Class CreatePlainCustomSubclass(Class class)
+{
+ NSString *newName = [NSString stringWithFormat: @"%s_GH_MAZeroingWeakRefSubclass", class_getName(class)];
+ const char *newNameC = [newName UTF8String];
+
+ Class subclass = objc_allocateClassPair(class, newNameC, 0);
+
+ Method release = class_getInstanceMethod(class, @selector(release));
+ Method dealloc = class_getInstanceMethod(class, @selector(dealloc));
+ Method classForCoder = class_getInstanceMethod(class, @selector(classForCoder));
+ class_addMethod(subclass, @selector(release), (IMP)CustomSubclassRelease, method_getTypeEncoding(release));
+ class_addMethod(subclass, @selector(dealloc), (IMP)CustomSubclassDealloc, method_getTypeEncoding(dealloc));
+ class_addMethod(subclass, @selector(classForCoder), (IMP)CustomSubclassClassForCoder, method_getTypeEncoding(classForCoder));
+
+ objc_registerClassPair(subclass);
+
+ return subclass;
+}
+
+static void PatchKVOSubclass(Class class)
+{
+// NSLog(@"Patching KVO class %s", class_getName(class));
+ Method removeObserverForKeyPath = class_getInstanceMethod(class, @selector(removeObserver:forKeyPath:));
+ Method release = class_getInstanceMethod(class, @selector(release));
+ Method dealloc = class_getInstanceMethod(class, @selector(dealloc));
+
+ class_addMethod(class,
+ @selector(GH_MAZeroingWeakRef_KVO_original_removeObserver:forKeyPath:),
+ method_getImplementation(removeObserverForKeyPath),
+ method_getTypeEncoding(removeObserverForKeyPath));
+ class_addMethod(class, @selector(GH_MAZeroingWeakRef_KVO_original_release), method_getImplementation(release), method_getTypeEncoding(release));
+ class_addMethod(class, @selector(GH_MAZeroingWeakRef_KVO_original_dealloc), method_getImplementation(dealloc), method_getTypeEncoding(dealloc));
+
+ class_replaceMethod(class,
+ @selector(removeObserver:forKeyPath:),
+ (IMP)KVOSubclassRemoveObserverForKeyPath,
+ method_getTypeEncoding(removeObserverForKeyPath));
+ class_replaceMethod(class, @selector(release), (IMP)KVOSubclassRelease, method_getTypeEncoding(release));
+ class_replaceMethod(class, @selector(dealloc), (IMP)KVOSubclassDealloc, method_getTypeEncoding(dealloc));
+
+ // The context variant is only available on 10.7/iOS5+, so only perform that override if the method actually exists.
+ Method removeObserverForKeyPathContext = class_getInstanceMethod(class, @selector(removeObserver:forKeyPath:context:));
+ if(removeObserverForKeyPathContext)
+ {
+ class_addMethod(class,
+ @selector(GH_MAZeroingWeakRef_KVO_original_removeObserver:forKeyPath:context:),
+ method_getImplementation(removeObserverForKeyPathContext),
+ method_getTypeEncoding(removeObserverForKeyPathContext));
+ class_replaceMethod(class,
+ @selector(removeObserver:forKeyPath:context:),
+ (IMP)KVOSubclassRemoveObserverForKeyPathContext,
+ method_getTypeEncoding(removeObserverForKeyPathContext));
+
+ }
+}
+
+static void RegisterCustomSubclass(Class subclass, Class superclass)
+{
+ [gCustomSubclassMap setObject: subclass forKey: superclass];
+ [gCustomSubclasses addObject: subclass];
+}
+
+static Class CreateCustomSubclass(Class class, id obj)
+{
+ if(IsTollFreeBridged(class, obj))
+ {
+#if COREFOUNDATION_HACK_LEVEL >= 2
+ CFTypeID typeID = CFGetTypeID(obj);
+ CFRuntimeClass *cfclass = _CFRuntimeGetClassWithTypeID(typeID);
+
+ if(typeID >= gCFOriginalFinalizesSize)
+ {
+ gCFOriginalFinalizesSize = typeID + 1;
+ gCFOriginalFinalizes = realloc(gCFOriginalFinalizes, gCFOriginalFinalizesSize * sizeof(*gCFOriginalFinalizes));
+ }
+
+ do {
+ gCFOriginalFinalizes[typeID] = cfclass->finalize;
+ } while(!OSAtomicCompareAndSwapPtrBarrier(gCFOriginalFinalizes[typeID], CustomCFFinalize, (void *)&cfclass->finalize));
+#else
+ NSCAssert2(0, @"Cannot create zeroing weak reference to object of type %@ with COREFOUNDATION_HACK_LEVEL set to %d", class, COREFOUNDATION_HACK_LEVEL);
+#endif
+ return class;
+ }
+ else if(IsKVOSubclass(obj))
+ {
+ PatchKVOSubclass(class);
+ return class;
+ }
+ else
+ {
+ return CreatePlainCustomSubclass(class);
+ }
+}
+
+static void EnsureCustomSubclass(id obj)
+{
+ if(!GetCustomSubclass(obj) && !IsConstantObject(obj))
+ {
+ Class class = object_getClass(obj);
+ Class subclass = [gCustomSubclassMap objectForKey: class];
+ if(!subclass)
+ {
+ subclass = CreateCustomSubclass(class, obj);
+ RegisterCustomSubclass(subclass, class);
+ }
+
+ // only set the class if the current one is its superclass
+ // otherwise it's possible that it returns something farther up in the hierarchy
+ // and so there's no need to set it then
+ if(class_getSuperclass(subclass) == class)
+ object_setClass(obj, subclass);
+ }
+}
+
+static void RegisterRef(GH_MAZeroingWeakRef *ref, id target)
+{
+ WhileLocked({
+ EnsureCustomSubclass(target);
+ AddWeakRefToObject(target, ref);
+#if COREFOUNDATION_HACK_LEVEL >= 3
+ if(IsTollFreeBridged(object_getClass(target), target))
+ CFSetAddValue(gCFWeakTargets, target);
+#endif
+ });
+}
+
+static void UnregisterRef(GH_MAZeroingWeakRef *ref)
+{
+ WhileLocked({
+ id target = ref->_target;
+
+ if(target)
+ RemoveWeakRefFromObject(target, ref);
+ });
+}
+
++ (BOOL)canRefCoreFoundationObjects
+{
+ return COREFOUNDATION_HACK_LEVEL >= 2 || objc_storeWeak_fptr;
+}
+
++ (id)refWithTarget: (id)target
+{
+ return [[[self alloc] initWithTarget: target] autorelease];
+}
+
+- (id)initWithTarget: (id)target
+{
+ if((self = [self init]))
+ {
+ if(objc_storeWeak_fptr && CanNativeZWR(target))
+ {
+ objc_storeWeak_fptr(&_target, target);
+ _nativeZWR = YES;
+ }
+ else
+ {
+ _target = target;
+ RegisterRef(self, target);
+ }
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ if(objc_storeWeak_fptr && _nativeZWR)
+ objc_storeWeak_fptr(&_target, nil);
+ else
+ UnregisterRef(self);
+
+#if NS_BLOCKS_AVAILABLE
+ [_cleanupBlock release];
+#endif
+ [super dealloc];
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat: @"<%@: %p -> %@>", [self class], self, [self target]];
+}
+
+#if NS_BLOCKS_AVAILABLE
+- (void)setCleanupBlock: (void (^)(id target))block
+{
+ block = [block copy];
+ [_cleanupBlock release];
+ _cleanupBlock = block;
+
+ if(objc_loadWeak_fptr && _nativeZWR)
+ {
+ // wrap a pool around this code, otherwise it artificially extends
+ // the lifetime of the target object
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ id target = [self target];
+ if(target != nil) @synchronized(target)
+ {
+ static void *associatedKey = &associatedKey;
+ NSMutableSet *cleanupHelpers = objc_getAssociatedObject(target, associatedKey);
+
+ if(cleanupHelpers == nil)
+ {
+ cleanupHelpers = [NSMutableSet set];
+ objc_setAssociatedObject(target, associatedKey, cleanupHelpers, OBJC_ASSOCIATION_RETAIN);
+ }
+
+ _GH_MAZeroingWeakRefCleanupHelper *helper = [[_GH_MAZeroingWeakRefCleanupHelper alloc] initWithRef: self target: target];
+ [cleanupHelpers addObject:helper];
+
+ [helper release];
+ }
+
+ [pool release];
+ }
+}
+#endif
+
+- (id)target
+{
+ if(objc_loadWeak_fptr && _nativeZWR)
+ {
+ return objc_loadWeak_fptr(&_target);
+ }
+ else
+ {
+ BLOCK_QUALIFIER id ret;
+ WhileLocked({
+ ret = [_target retain];
+ });
+ return [ret autorelease];
+ }
+}
+
+- (void)_zeroTarget
+{
+ _target = nil;
+}
+
+- (void)_executeCleanupBlockWithTarget: (id)target
+{
+#if NS_BLOCKS_AVAILABLE
+ if(_cleanupBlock)
+ {
+ _cleanupBlock(target);
+ [_cleanupBlock release];
+ _cleanupBlock = nil;
+ }
+#endif
+}
+
+@end
View
180 Classes/MAZeroingWeakRef/GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h
@@ -0,0 +1,180 @@
+static void *_GH_MAZeroingWeakRefClassPresentToken = &_GH_MAZeroingWeakRefClassPresentToken;
+struct _NativeZWRTableEntry { BOOL isTable; void *ptr; };
+static struct _NativeZWRTableEntry _GH_MAZeroingWeakRefClassNativeWeakReferenceNotAllowedTable[256] = {
+ [0x3] = { 0, (unsigned char[]){ 0x5b, 0x81, 0x42, 0xa2, 0xe, 0x20, 0xd7, 0x39, 0xf1, 0xa4, 0xa8, 0x21, 0x86, 0x1d, 0xdc, 0xa5, 0xef, 0x9, 0x34 } }, // NSTableCellView
+ [0x5] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0xa] = { 0, (unsigned char[]){ 0x5a, 0x2f, 0xc3, 0xa6, 0xd5, 0xfb, 0xcf, 0xcc, 0x85, 0xf2, 0x2f, 0xea, 0x16, 0xeb, 0xbf, 0xcf, 0x9e, 0x52 } }, // NSBlock
+ [0x83] = { 0, (unsigned char[]){ 0xae, 0xc5, 0x56, 0x5, 0xce, 0xb3, 0xd5, 0x18, 0xe9, 0x30, 0xb7, 0x70, 0xf4, 0x78, 0xc9, 0xaf, 0xdd, 0x54 } }, // NSISNonNegativeVariableToBeMinimized
+ }},
+ [0x7] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0xf] = { 0, (unsigned char[]){ 0x52, 0xec, 0xf7, 0xb1, 0xe5, 0x2a, 0x7c, 0x39, 0xd4, 0x61, 0x17, 0x76, 0x26, 0x8e, 0x7a, 0x5c, 0x8f, 0xb2 } }, // NSISObjectiveVariable
+ [0x40] = { 0, (unsigned char[]){ 0x46, 0xca, 0xad, 0x6d, 0xcc, 0x49, 0x26, 0x3c, 0x81, 0xb8, 0xb, 0xe7, 0x21, 0xcc, 0x28, 0xcf, 0xc3, 0x24 } }, // NSATSGlyphStorage
+ }},
+ [0x8] = { 0, (unsigned char[]){ 0x82, 0x50, 0x66, 0x55, 0x76, 0x98, 0xb5, 0xb8, 0x56, 0x20, 0xd6, 0x1c, 0x7, 0x55, 0x4e, 0x32, 0xe0, 0xb1, 0x33 } }, // NSViewHierarchyLock
+ [0x9] = { 0, (unsigned char[]){ 0x11, 0x7b, 0x21, 0x90, 0x28, 0xc0, 0x39, 0x90, 0x9b, 0xc5, 0xa9, 0xf, 0xaf, 0x8, 0x43, 0x9e, 0xb9, 0x9d, 0xc3 } }, // NSTableOptions
+ [0xf] = { 0, (unsigned char[]){ 0x7d, 0x56, 0x74, 0xad, 0x93, 0x48, 0xe2, 0xbd, 0x2b, 0x5c, 0xb4, 0xf6, 0xf8, 0xd2, 0xfc, 0x47, 0xc0, 0xf4, 0xb9 } }, // _NSQuickLookWrapperDocumentWindow
+ [0x11] = { 0, (unsigned char[]){ 0xa3, 0x61, 0xe2, 0x7d, 0xb1, 0x3e, 0xe4, 0xe1, 0xd1, 0x7a, 0xd, 0xc4, 0x74, 0x52, 0x76, 0xb0, 0xb5, 0x7e, 0xb3 } }, // _NSScalarObjectID
+ [0x1a] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x44] = { 0, (unsigned char[]){ 0x3b, 0x91, 0x94, 0xd2, 0x34, 0x5e, 0x4a, 0x18, 0xd9, 0x71, 0x17, 0x2c, 0xc4, 0xfa, 0x5a, 0x71, 0x4c, 0xb5 } }, // NSCorrectionSubPanel
+ [0xda] = { 0, (unsigned char[]){ 0x11, 0x4, 0xac, 0x59, 0xce, 0x58, 0x99, 0x8, 0x5, 0xae, 0xc7, 0x9f, 0x5f, 0x7c, 0x1e, 0xab, 0xf3, 0x12 } }, // NSISNonNegativeVariableWithDelegate
+ }},
+ [0x1c] = { 0, (unsigned char[]){ 0x90, 0xdf, 0xd3, 0x6e, 0xb0, 0x87, 0xd6, 0xc4, 0xa4, 0x33, 0xd9, 0x9f, 0xf9, 0xde, 0x69, 0xf4, 0x80, 0x7d, 0xf4 } }, // NSCorrectionPanel
+ [0x1d] = { 0, (unsigned char[]){ 0xfc, 0x3e, 0x70, 0x29, 0x9a, 0x6f, 0xbe, 0x9a, 0x3e, 0xe7, 0x56, 0x1e, 0x64, 0x13, 0xe9, 0x6a, 0xfd, 0xc9, 0xcd } }, // __NSSharedFontInstanceInfo
+ [0x1f] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x3a] = { 0, (unsigned char[]){ 0x80, 0xbb, 0xa7, 0xc1, 0x41, 0xc9, 0xa5, 0x87, 0x46, 0x6c, 0xe8, 0x53, 0xf, 0x31, 0x2c, 0xe4, 0x82, 0xed } }, // NSToolbarConfigPanel
+ [0xf5] = { 0, (unsigned char[]){ 0x26, 0xc2, 0x40, 0xf7, 0x91, 0x16, 0x9f, 0x23, 0x4e, 0x23, 0xa4, 0xfd, 0xcf, 0xe0, 0xb7, 0x12, 0xbe, 0x5 } }, // _NSBrowserTableColumnViewController
+ }},
+ [0x20] = { 0, (unsigned char[]){ 0x45, 0xd6, 0x66, 0x4e, 0xd3, 0x46, 0xa2, 0x31, 0xbc, 0xd4, 0x91, 0xbb, 0xc6, 0x7f, 0xaf, 0x9a, 0x16, 0xf3, 0x55 } }, // NSSpellingPanel
+ [0x24] = { 0, (unsigned char[]){ 0x97, 0x38, 0x41, 0x2b, 0xe7, 0x18, 0x67, 0x62, 0x5, 0xdd, 0xdf, 0xc1, 0x57, 0x59, 0x49, 0xc4, 0x16, 0x32, 0x94 } }, // NSISVariableWithDelegate
+ [0x2b] = { 0, (unsigned char[]){ 0x1, 0xdd, 0xee, 0xa6, 0x38, 0xdf, 0x45, 0x52, 0x1, 0xa3, 0x33, 0x18, 0x2a, 0x2e, 0x17, 0x5, 0x96, 0x81, 0x4a } }, // NSManagedObjectID
+ [0x2d] = { 0, (unsigned char[]){ 0xb6, 0x84, 0x6b, 0x6a, 0xe6, 0x48, 0x56, 0xb4, 0xb8, 0xae, 0x9, 0x8f, 0x88, 0xd4, 0x9f, 0x71, 0x8d, 0x2b, 0xf4 } }, // NSSecureTextView
+ [0x33] = { 0, (unsigned char[]){ 0x46, 0x16, 0x4e, 0xe1, 0x47, 0x1a, 0x32, 0x82, 0x6e, 0xae, 0x61, 0xed, 0xf8, 0xe, 0x27, 0xa8, 0x76, 0xda, 0x8 } }, // __NSFontTypefaceInfo
+ [0x35] = { 0, (unsigned char[]){ 0xc2, 0x5e, 0x22, 0xd0, 0x4b, 0x59, 0x4a, 0xfe, 0xc7, 0xb2, 0xc, 0xb5, 0x8d, 0x7, 0x4b, 0xee, 0x4a, 0x35, 0x52 } }, // _NSFullScreenUnbufferedWindow
+ [0x37] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x6f] = { 0, (unsigned char[]){ 0x70, 0x43, 0x47, 0x3f, 0x14, 0x9b, 0xf8, 0x1e, 0x57, 0xcb, 0x40, 0xd6, 0x54, 0xd4, 0xd1, 0x6f, 0xc6, 0x5e } }, // _NSSlideAndCrossFadeAnimationProjectionWindow
+ [0x72] = { 0, (unsigned char[]){ 0x9b, 0xcf, 0x5f, 0xcf, 0x88, 0x75, 0x72, 0x8e, 0xf1, 0x6c, 0xe5, 0xc8, 0x62, 0xc5, 0x5f, 0xe2, 0xcd, 0x5c } }, // NSNavNodeSharedServerController
+ }},
+ [0x38] = { 0, (unsigned char[]){ 0x60, 0x5c, 0x3f, 0xa3, 0xb, 0xc3, 0x8d, 0x3e, 0x7, 0x33, 0x1e, 0x54, 0xf3, 0xed, 0x88, 0x29, 0xe, 0xaf, 0xc3 } }, // NSNavFilepathInputController
+ [0x3a] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x19] = { 0, (unsigned char[]){ 0x21, 0x87, 0xa7, 0x0, 0x57, 0xb5, 0x54, 0xdf, 0x53, 0x50, 0x57, 0xe7, 0x88, 0xf6, 0x85, 0x3d, 0x5e, 0x73 } }, // _NSBrowserMatrixColumnViewController
+ [0x29] = { 0, (unsigned char[]){ 0x2f, 0x44, 0xd9, 0xeb, 0x81, 0x1e, 0x89, 0x21, 0x38, 0x1a, 0xd1, 0x36, 0xf5, 0x1b, 0xb1, 0xf, 0xe2, 0xa5 } }, // NSAttributeDictionary
+ }},
+ [0x3d] = { 0, (unsigned char[]){ 0x84, 0x79, 0x16, 0x14, 0xdb, 0x72, 0x27, 0x5, 0xb1, 0x2b, 0x8c, 0xed, 0xfb, 0x1f, 0xe6, 0x65, 0x9b, 0xa3, 0x32 } }, // NSISVariable
+ [0x42] = { 0, (unsigned char[]){ 0x6e, 0xba, 0xa0, 0x45, 0x15, 0x86, 0x37, 0x4b, 0x30, 0x48, 0xe, 0x7b, 0xaf, 0xa, 0xd2, 0x75, 0x43, 0x10, 0xfb } }, // NSTableOptionsPanel
+ [0x43] = { 0, (unsigned char[]){ 0xac, 0xfb, 0xb9, 0xaa, 0xde, 0xc7, 0xe3, 0xe0, 0x91, 0x32, 0x60, 0xad, 0xfe, 0xd2, 0x44, 0xfe, 0x75, 0xbc, 0x6b } }, // NSAccessoryWindow
+ [0x44] = { 0, (unsigned char[]){ 0xe4, 0x9e, 0x1b, 0x5, 0xa9, 0x34, 0xa9, 0xd9, 0xc5, 0xa7, 0x5, 0x16, 0x3d, 0x4f, 0x15, 0x41, 0xa8, 0x45, 0x24 } }, // __NSOperationInternal
+ [0x45] = { 0, (unsigned char[]){ 0xb8, 0xcb, 0x9f, 0xea, 0x3a, 0xf2, 0xe3, 0x30, 0x9d, 0x53, 0xc5, 0x36, 0x95, 0x4a, 0x69, 0x55, 0xea, 0x85, 0xee } }, // NSNavSharedServerController
+ [0x48] = { 0, (unsigned char[]){ 0x57, 0x8c, 0x37, 0xc5, 0x34, 0x5, 0x21, 0x89, 0x5c, 0x4b, 0x15, 0x7, 0x9c, 0xb8, 0xff, 0x7b, 0x6e, 0xf1, 0xae } }, // NSWindow
+ [0x4a] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0xc] = { 0, (unsigned char[]){ 0xcd, 0x9e, 0xea, 0x1e, 0x8a, 0xea, 0xf, 0x0, 0xf3, 0xe7, 0x33, 0xb1, 0x6f, 0x5b, 0x42, 0x55, 0x55, 0x45 } }, // NSStringDrawingTextStorage
+ [0x3e] = { 0, (unsigned char[]){ 0xc4, 0xeb, 0x56, 0x8b, 0x5, 0x8a, 0xbb, 0xbe, 0xa0, 0xdb, 0x58, 0xd2, 0x5b, 0x99, 0xef, 0xc, 0x36, 0xc0 } }, // NSDocumentRevisionsTimelineWindow
+ }},
+ [0x4c] = { 0, (unsigned char[]){ 0x96, 0x73, 0x2, 0xb9, 0x44, 0xe3, 0x1f, 0xb, 0xaf, 0xab, 0xba, 0xf0, 0x1c, 0x1c, 0x12, 0x0, 0xb7, 0x86, 0xbf } }, // NSLocalWindowWrappingRemoteWindow
+ [0x4d] = { 0, (unsigned char[]){ 0xb2, 0x61, 0xa9, 0x77, 0x21, 0xee, 0x44, 0x1c, 0x86, 0xdc, 0xcd, 0x68, 0x7c, 0x6f, 0x6d, 0xf2, 0x93, 0xed, 0x1e } }, // NSNavAdvancedSearchController
+ [0x4e] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0xaa] = { 0, (unsigned char[]){ 0x67, 0xf8, 0xa5, 0xc8, 0x3e, 0x19, 0x3f, 0xc0, 0x9, 0x59, 0x79, 0x51, 0xa0, 0x8e, 0xeb, 0xfb, 0x77, 0x26 } }, // _CTNativeGlyphStorage
+ [0xd7] = { 0, (unsigned char[]){ 0xfc, 0xdd, 0x19, 0x16, 0xed, 0x7e, 0x9e, 0x83, 0x8e, 0x25, 0x5c, 0xa6, 0xe6, 0xe, 0xe1, 0x36, 0xc3, 0xb1 } }, // NSTokenTextView
+ }},
+ [0x50] = { 0, (unsigned char[]){ 0xb2, 0x2e, 0x2a, 0x97, 0xb4, 0x8, 0x61, 0xa9, 0x51, 0x72, 0x20, 0x74, 0xbf, 0x85, 0xe4, 0x54, 0xb3, 0x1a, 0x24 } }, // _NSCoreManagedObjectID
+ [0x52] = { 0, (unsigned char[]){ 0xb4, 0xcf, 0x19, 0x47, 0xb8, 0xd5, 0x65, 0x56, 0x75, 0xc0, 0x46, 0xd4, 0x3c, 0x9a, 0xf2, 0x21, 0x2f, 0xc5, 0xca } }, // _PFManagedObjectReferenceQueue
+ [0x53] = { 0, (unsigned char[]){ 0x4d, 0xe5, 0x8d, 0xa1, 0x40, 0xcb, 0x7a, 0x1a, 0x27, 0xd3, 0x89, 0x24, 0x39, 0xda, 0xd1, 0x46, 0x1c, 0xf0, 0x84 } }, // NSProgressPanel
+ [0x54] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x77] = { 0, (unsigned char[]){ 0x65, 0xbb, 0x28, 0x9e, 0xbd, 0x9f, 0x5d, 0xc, 0x39, 0x70, 0x5b, 0xe7, 0x65, 0xcc, 0x3c, 0xcc, 0x4a, 0x6 } }, // NSMessagePort
+ [0xa4] = { 0, (unsigned char[]){ 0x4f, 0x92, 0x89, 0xe2, 0x3b, 0x49, 0x6e, 0x70, 0xe1, 0x75, 0x90, 0x79, 0xbb, 0x53, 0x5f, 0x4f, 0xcc, 0x3e } }, // NSColorPopoverController
+ }},
+ [0x59] = { 0, (unsigned char[]){ 0xed, 0xef, 0x25, 0x8c, 0xc5, 0x35, 0xe7, 0xa3, 0xa7, 0x5a, 0xcc, 0xd3, 0x75, 0x8, 0x43, 0xb2, 0xa, 0xee, 0xb2 } }, // NSPort
+ [0x5b] = { 0, (unsigned char[]){ 0x8a, 0x1d, 0xa9, 0x7e, 0x72, 0x5d, 0x70, 0x81, 0xcf, 0xc, 0xe0, 0xb8, 0x73, 0x8f, 0x5c, 0x85, 0xd6, 0xa1, 0xe1 } }, // _NSBrowserPreviewColumnViewController
+ [0x5f] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x22] = { 0, (unsigned char[]){ 0x72, 0x59, 0x13, 0xf8, 0x71, 0xdb, 0x3a, 0xbe, 0xa0, 0x1b, 0xaf, 0xed, 0x76, 0xb, 0x9a, 0xf3, 0x5e, 0xd8 } }, // NSBasicObjectID
+ [0xc0] = { 0, (unsigned char[]){ 0x5e, 0x88, 0x3a, 0xb1, 0x91, 0x9c, 0xf9, 0x9d, 0x19, 0xfe, 0x79, 0xa9, 0x8f, 0x7a, 0x42, 0x3, 0x7c, 0x72 } }, // _NSSavePanelTextView
+ }},
+ [0x67] = { 0, (unsigned char[]){ 0xae, 0xaf, 0x59, 0x8c, 0xa3, 0x4a, 0xf8, 0xe9, 0xa, 0xe8, 0x7c, 0x18, 0x48, 0x0, 0x34, 0xbc, 0x4a, 0x69, 0x40 } }, // NSRulerMarkerPanel
+ [0x68] = { 0, (unsigned char[]){ 0x3a, 0x65, 0xf1, 0xba, 0x6a, 0x7f, 0xa7, 0xfb, 0x12, 0xe4, 0x1f, 0x53, 0x25, 0xad, 0x74, 0x88, 0xd, 0x73, 0x30 } }, // NSStatusBarWindow
+ [0x69] = { 0, (unsigned char[]){ 0x20, 0xef, 0xa7, 0x58, 0xa2, 0x8c, 0xc3, 0x20, 0xa1, 0xb8, 0xcd, 0x75, 0x46, 0x40, 0xfc, 0x5, 0xae, 0x61, 0xa } }, // NSToolbarFullScreenWindow
+ [0x6a] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x16] = { 0, (unsigned char[]){ 0xaf, 0x44, 0x1, 0x18, 0x5e, 0x88, 0x4d, 0x10, 0x1c, 0x26, 0x2b, 0xf7, 0xca, 0xf4, 0x9, 0xb, 0x24, 0x8e } }, // NSCarbonWindow
+ [0x72] = { 0, (unsigned char[]){ 0x94, 0xde, 0xb9, 0xc4, 0x93, 0x86, 0xcc, 0x88, 0x1e, 0x3, 0x8b, 0x7f, 0x72, 0x7c, 0x51, 0x96, 0xfb, 0xba } }, // NSPrintPreviewController
+ }},
+ [0x6e] = { 0, (unsigned char[]){ 0x7, 0x4a, 0x8f, 0xd5, 0xad, 0xa6, 0xbf, 0x62, 0x15, 0x49, 0x9a, 0x98, 0xfb, 0x9e, 0x6c, 0x9a, 0x29, 0x5e, 0x45 } }, // NSTextView
+ [0x6f] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x34] = { 0, (unsigned char[]){ 0x15, 0x3d, 0x33, 0x27, 0xe2, 0x98, 0x15, 0x6b, 0xd, 0xc5, 0xb0, 0x9, 0x8e, 0x8b, 0x22, 0x40, 0x88, 0x9c } }, // __NSATSStringSegment
+ [0xc5] = { 0, (unsigned char[]){ 0x6c, 0x2c, 0x2c, 0x37, 0xe2, 0x89, 0x72, 0x56, 0xb3, 0x7d, 0xb6, 0x2d, 0x67, 0x4c, 0xd0, 0x5f, 0x55, 0xc1 } }, // NSSubTextStorage
+ }},
+ [0x72] = { 0, (unsigned char[]){ 0x8d, 0x27, 0x74, 0x97, 0x62, 0x6, 0x8b, 0x6b, 0xec, 0x92, 0x51, 0x4a, 0xbd, 0x43, 0xc8, 0xaa, 0x6c, 0x58, 0x9 } }, // NSTextViewCompletionWindow
+ [0x73] = { 0, (unsigned char[]){ 0xb1, 0xc6, 0x4b, 0x54, 0xb0, 0x56, 0x42, 0x26, 0xd0, 0xc, 0xf4, 0x28, 0x23, 0x12, 0x37, 0xad, 0xb4, 0x7d, 0xac } }, // _NSFullScreenTransitionOverlayWindow
+ [0x75] = { 0, (unsigned char[]){ 0x4b, 0xe3, 0x5c, 0xb0, 0x20, 0x14, 0xca, 0x8c, 0x61, 0x60, 0xdc, 0x7a, 0xee, 0xf, 0x88, 0x19, 0x9f, 0xa7, 0x68 } }, // _PFTask
+ [0x76] = { 0, (unsigned char[]){ 0xf5, 0x2d, 0xe3, 0x23, 0x10, 0x98, 0x61, 0xac, 0x59, 0x99, 0x59, 0xda, 0x3d, 0x8d, 0xa6, 0xa, 0x67, 0x37, 0xc0 } }, // NSParagraphStyle
+ [0x77] = { 0, (unsigned char[]){ 0xe0, 0xd5, 0x7, 0x83, 0xa7, 0x2e, 0x7e, 0xba, 0xac, 0x6a, 0xaa, 0x97, 0x47, 0x4f, 0xb4, 0x26, 0xe8, 0xd5, 0xca } }, // _NSOrderOutAnimationProxyWindow
+ [0x7c] = { 0, (unsigned char[]){ 0xdd, 0x75, 0x76, 0xb0, 0xb1, 0xfc, 0xcb, 0x3e, 0xd7, 0x51, 0xe3, 0xf4, 0x93, 0x78, 0xd5, 0x27, 0xc2, 0x4c, 0xc4 } }, // NSPrintPanelOldAccessoryController
+ [0x7d] = { 0, (unsigned char[]){ 0x76, 0x18, 0xf6, 0x67, 0x49, 0xf0, 0x27, 0xd0, 0x31, 0x14, 0xf3, 0xce, 0x4d, 0x6e, 0x95, 0x26, 0x95, 0xa1, 0xb9 } }, // NSNavProgressStatusViewController
+ [0x7f] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x18] = { 0, (unsigned char[]){ 0x3a, 0xe7, 0x3a, 0x47, 0xa1, 0x86, 0x5c, 0x8b, 0x3d, 0xad, 0x74, 0xe7, 0x7b, 0xa3, 0x71, 0xce, 0xb6, 0xed } }, // NSWindowController
+ [0xb5] = { 0, (unsigned char[]){ 0x68, 0x7e, 0xc6, 0xa1, 0xb8, 0x14, 0xb3, 0x1b, 0xd2, 0xec, 0xce, 0x99, 0x3e, 0x3, 0x72, 0x1d, 0x17, 0xce } }, // NSTextTab
+ }},
+ [0x83] = { 0, (unsigned char[]){ 0x11, 0x3f, 0x29, 0x8e, 0x75, 0xfa, 0x19, 0xca, 0x82, 0x5f, 0xc, 0xe6, 0x40, 0x60, 0x99, 0xa5, 0xcc, 0xb0, 0xd5 } }, // _NSFullScreenWindow
+ [0x84] = { 0, (unsigned char[]){ 0x5d, 0x46, 0x99, 0xf2, 0x6f, 0x3e, 0x70, 0xd0, 0x7, 0x4, 0x32, 0x68, 0x82, 0x5d, 0xad, 0xdb, 0x5d, 0x96, 0x89 } }, // NSISNonNegativeMarkerVariable
+ [0x89] = { 0, (unsigned char[]){ 0xe8, 0x30, 0xee, 0xf9, 0x87, 0x23, 0xd7, 0x55, 0x41, 0x71, 0xfe, 0xbd, 0x6a, 0x6a, 0x9, 0xf8, 0xa8, 0xa9, 0xb0 } }, // NSCarbonMenuWindow
+ [0x8e] = { 0, (unsigned char[]){ 0x3c, 0x39, 0xef, 0xfb, 0x5e, 0xbf, 0xfc, 0x69, 0x9f, 0xdb, 0xd7, 0x4c, 0x97, 0xaf, 0x9f, 0xc7, 0xbf, 0xe7, 0x5 } }, // __NSFinalizingBlock
+ [0x91] = { 0, (unsigned char[]){ 0x29, 0xe6, 0xff, 0x9c, 0xa8, 0x1b, 0x78, 0x33, 0x5e, 0xf5, 0xd6, 0xf6, 0xf3, 0x34, 0xa9, 0x27, 0x68, 0xdc, 0x48 } }, // NSISNonNegativeVariableWithDelegateToBeMinimized
+ [0x93] = { 0, (unsigned char[]){ 0x6b, 0x15, 0xf9, 0xf2, 0xb9, 0xfb, 0x86, 0x42, 0xb2, 0x9d, 0x76, 0xaa, 0x9a, 0x3e, 0xaf, 0x47, 0x3b, 0x4b, 0x97 } }, // _NSDuplicateDocumentAnimationProjectionWindow
+ [0x95] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x1f] = { 0, (unsigned char[]){ 0xc2, 0x2d, 0x6b, 0x81, 0x8b, 0xc6, 0x6d, 0x62, 0x89, 0x92, 0x68, 0x5f, 0x4b, 0x54, 0x74, 0xbc, 0x1b, 0x43 } }, // NSExceptionAlertController
+ [0xca] = { 0, (unsigned char[]){ 0x6b, 0x18, 0xe4, 0xc5, 0xf8, 0x35, 0xae, 0x2c, 0xc1, 0x2c, 0xdc, 0xcd, 0xec, 0x4e, 0xca, 0x76, 0x94, 0x6 } }, // NSColorSpace
+ }},
+ [0x96] = { 0, (unsigned char[]){ 0x9f, 0x99, 0xf9, 0x49, 0x2a, 0xc, 0xfe, 0x8, 0x4e, 0xed, 0xd4, 0x2b, 0x69, 0x39, 0xef, 0x12, 0xba, 0x18, 0x2 } }, // NSToolTipPanel
+ [0x97] = { 0, (unsigned char[]){ 0x20, 0x8, 0xb2, 0x87, 0x77, 0xe3, 0xa4, 0x7e, 0xbe, 0x34, 0x6f, 0x84, 0x29, 0xa6, 0x21, 0x2a, 0x7f, 0xcc, 0xe } }, // __NSAutoBlock
+ [0x98] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x4a] = { 0, (unsigned char[]){ 0xd, 0xf9, 0x7b, 0xf8, 0x20, 0x1c, 0xc6, 0x40, 0x43, 0x6, 0x7, 0x6c, 0x14, 0xd7, 0x25, 0x21, 0x25, 0xb7 } }, // NSSingleLineTypesetter
+ [0xb2] = { 0, (unsigned char[]){ 0xb6, 0xb4, 0x58, 0x5d, 0x2a, 0x3c, 0xc, 0xc8, 0x27, 0xe7, 0x6e, 0x63, 0x7, 0x7e, 0x53, 0xb2, 0x50, 0x59 } }, // NSCollectionViewItem
+ [0xdf] = { 0, (unsigned char[]){ 0xf3, 0x3a, 0x92, 0xb7, 0x1a, 0x77, 0x8f, 0xf7, 0x45, 0x92, 0xd0, 0x22, 0x18, 0xb0, 0xcc, 0xc5, 0x4f, 0x96 } }, // NSScalarObjectID64
+ }},
+ [0x9a] = { 0, (unsigned char[]){ 0x57, 0xa6, 0xe7, 0x54, 0xa2, 0xbc, 0xe6, 0x20, 0x28, 0x42, 0x60, 0x93, 0x3, 0x14, 0x9d, 0xdf, 0xdb, 0xda, 0x4f } }, // NSSidebarImage
+ [0x9d] = { 0, (unsigned char[]){ 0xb3, 0x81, 0xc4, 0xce, 0x4b, 0x48, 0x6d, 0x80, 0x6a, 0xf4, 0xe1, 0x31, 0xda, 0x8d, 0xc7, 0x83, 0xab, 0xc5, 0xa1 } }, // NSPanel
+ [0xa0] = { 0, (unsigned char[]){ 0x63, 0xb, 0xc2, 0xb6, 0xbe, 0xf6, 0xc3, 0x86, 0x47, 0x7, 0xe, 0xd8, 0xef, 0xff, 0x92, 0xe5, 0x31, 0xe9, 0x0 } }, // NSComboBoxWindow
+ [0xa2] = { 0, (unsigned char[]){ 0x83, 0x8d, 0xd0, 0xff, 0xa3, 0x36, 0x89, 0xef, 0x62, 0xbc, 0xb5, 0xd6, 0xbb, 0x7a, 0x4b, 0xf6, 0xf6, 0xb1, 0xfb } }, // NSViewController
+ [0xa6] = { 0, (unsigned char[]){ 0xe8, 0x41, 0xe7, 0xac, 0x58, 0xf6, 0x21, 0x64, 0x82, 0xad, 0xa8, 0x65, 0x1a, 0x54, 0x58, 0x8c, 0xd3, 0x54, 0xa0 } }, // _NSNonretainedFullScreenWindow
+ [0xa9] = { 0, (unsigned char[]){ 0x2f, 0xd9, 0xc0, 0xea, 0xae, 0x7d, 0x3, 0xd8, 0x5e, 0xbe, 0x67, 0xee, 0x5f, 0xb0, 0x60, 0xd0, 0x57, 0x7a, 0x5c } }, // _NSAutomaticFocusRingOverlayWindow
+ [0xaa] = { 0, (unsigned char[]){ 0x9b, 0x75, 0x33, 0xf, 0xa8, 0xfa, 0xda, 0x8d, 0x4a, 0xd6, 0x4c, 0x43, 0x12, 0x47, 0x4d, 0x10, 0xb2, 0xc0, 0xa0 } }, // NSNavProgressWindowController
+ [0xab] = { 0, (unsigned char[]){ 0xed, 0xd5, 0xe6, 0xe8, 0xac, 0x1, 0xd, 0x20, 0x57, 0x7f, 0x71, 0xfd, 0x18, 0xcc, 0x69, 0x72, 0xa, 0x1d, 0x42 } }, // _NSCachedAttributedString
+ [0xac] = { 0, (unsigned char[]){ 0x62, 0xbc, 0xb9, 0x26, 0xdd, 0x24, 0x3d, 0x3f, 0xc4, 0x26, 0x47, 0x50, 0xc6, 0xbb, 0x6b, 0x56, 0x93, 0x16, 0x2c } }, // NSLineFragmentRenderingContext
+ [0xad] = { 0, (unsigned char[]){ 0x75, 0xf9, 0xaa, 0x1b, 0xf9, 0x53, 0x93, 0x35, 0xe3, 0x16, 0x98, 0xfc, 0x7e, 0xe5, 0xec, 0x9b, 0xca, 0x64, 0xef } }, // NSFindPatternFieldEditor
+ [0xae] = { 0, (unsigned char[]){ 0xd, 0x3, 0x25, 0x76, 0x1f, 0x1f, 0x45, 0x58, 0x25, 0xb8, 0x8f, 0xa8, 0x37, 0x72, 0xfd, 0xf5, 0xb7, 0xf1, 0x85 } }, // PBOXMenuWindow
+ [0xb0] = { 0, (unsigned char[]){ 0x40, 0x9, 0xa1, 0xd9, 0xb4, 0xf, 0x4, 0xb6, 0x4, 0xd6, 0xd5, 0x7b, 0x9d, 0xdf, 0x9e, 0x8, 0xa2, 0xe4, 0xb7 } }, // NSMachPort
+ [0xb1] = { 0, (unsigned char[]){ 0x7e, 0x84, 0xd, 0x23, 0x8f, 0x79, 0x56, 0xff, 0x92, 0x40, 0x76, 0xb0, 0x6b, 0x81, 0x76, 0x96, 0xf, 0xc1, 0xa } }, // __NSAutoBlock__
+ [0xb4] = { 0, (unsigned char[]){ 0x69, 0x23, 0xfd, 0xe9, 0xf, 0x24, 0x19, 0xb7, 0xa7, 0x92, 0xe1, 0xed, 0x1b, 0xd1, 0xa0, 0xae, 0x64, 0x85, 0x87 } }, // NSExternalRefCountedData
+ [0xbc] = { 0, (unsigned char[]){ 0x7b, 0x3e, 0x3c, 0xe7, 0xe3, 0x14, 0x1b, 0x46, 0x77, 0x44, 0xdb, 0x43, 0xc3, 0xa4, 0xb9, 0x31, 0x66, 0x8, 0xc7 } }, // _NSFlippedImage
+ [0xbe] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x66] = { 0, (unsigned char[]){ 0x1a, 0x9f, 0x99, 0xf3, 0x4a, 0xb9, 0xa7, 0xb0, 0x6, 0xad, 0xc1, 0x81, 0xdf, 0xe2, 0x1e, 0x1, 0x8b, 0xf4 } }, // _NSBorderlessLayerTreeProjectionWindow
+ [0xab] = { 0, (unsigned char[]){ 0x49, 0x7d, 0x5f, 0x63, 0xfe, 0xdc, 0xa7, 0x43, 0x43, 0xad, 0x24, 0x80, 0x6c, 0xeb, 0x36, 0x4, 0xd2, 0x9b } }, // NSFontPanel
+ }},
+ [0xbf] = { 0, (unsigned char[]){ 0x83, 0x4b, 0x26, 0xf2, 0xc3, 0x24, 0xc5, 0x64, 0x5d, 0x4c, 0x96, 0x86, 0xed, 0x42, 0x1c, 0x83, 0x5, 0x34, 0x8c } }, // NSNavProgressErrorViewController
+ [0xc1] = { 0, (unsigned char[]){ 0x94, 0xb4, 0x7c, 0xba, 0xa4, 0xf5, 0x3a, 0x43, 0x6, 0xa3, 0x84, 0x64, 0xeb, 0xf7, 0xe0, 0xe0, 0xb6, 0x98, 0x55 } }, // NSText
+ [0xc3] = { 0, (unsigned char[]){ 0x2e, 0x12, 0x59, 0xba, 0x72, 0xd7, 0x51, 0x40, 0x73, 0xe3, 0xe1, 0xfb, 0x1e, 0x97, 0xb0, 0xc5, 0xc1, 0xe4, 0xeb } }, // _NSTextFinderOverlayWindow
+ [0xcd] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x1b] = { 0, (unsigned char[]){ 0x3b, 0x80, 0x3f, 0x14, 0x9c, 0xde, 0xad, 0x18, 0x4b, 0xe9, 0x44, 0xba, 0x1, 0x5f, 0x8, 0x98, 0xd6, 0x8c } }, // __NSStackBlock
+ [0x81] = { 0, (unsigned char[]){ 0xa9, 0x68, 0x44, 0x6c, 0xfc, 0x5b, 0x40, 0xfe, 0x10, 0xb4, 0xc3, 0x4e, 0x19, 0xfd, 0x57, 0x68, 0x6c, 0xcb } }, // NSFindPanel
+ }},
+ [0xd2] = { 0, (unsigned char[]){ 0x53, 0x40, 0xb2, 0xe9, 0xe7, 0xd8, 0xaa, 0xa9, 0x8c, 0x59, 0x99, 0x1, 0x9, 0x2b, 0xa9, 0x5a, 0x8c, 0x4, 0xa4 } }, // NSDocumentRevisionsWindow
+ [0xd9] = { 0, (unsigned char[]){ 0x9, 0x12, 0x39, 0x4d, 0xa4, 0x3, 0x8b, 0x2, 0x13, 0x4a, 0xc6, 0x58, 0xd5, 0x9e, 0x50, 0x4a, 0xf0, 0x2, 0x36 } }, // NSISNonNegativeVariable
+ [0xdb] = { 0, (unsigned char[]){ 0x1a, 0x27, 0xe4, 0x7, 0x22, 0xf5, 0x27, 0xc3, 0xcd, 0xc8, 0x2b, 0xb6, 0x2c, 0x25, 0x40, 0xf9, 0x46, 0xa4, 0x73 } }, // NSFont
+ [0xdc] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x6] = { 0, (unsigned char[]){ 0x59, 0x16, 0xd4, 0x5a, 0xea, 0x6f, 0x8e, 0x8, 0xac, 0x89, 0xac, 0xb, 0x73, 0x2c, 0x62, 0x67, 0xff, 0x0 } }, // __NSFinalizingBlock__
+ [0x10] = { 0, (unsigned char[]){ 0xab, 0x59, 0x12, 0x43, 0x64, 0x12, 0x79, 0xe0, 0x82, 0xb3, 0xf9, 0xcd, 0x3b, 0xf4, 0x4d, 0x7b, 0x94, 0x25 } }, // NSPersistentUIEncodedReference
+ }},
+ [0xdd] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x94] = { 0, (unsigned char[]){ 0x9b, 0xe, 0x2a, 0x0, 0x1b, 0x77, 0x4d, 0x1c, 0xe6, 0x22, 0x91, 0x1d, 0x0, 0xc4, 0xf2, 0x51, 0xaa, 0x77 } }, // NSFontManager
+ [0x97] = { 0, (unsigned char[]){ 0x91, 0x5, 0x67, 0xd4, 0xed, 0x70, 0xac, 0xca, 0x54, 0x91, 0x52, 0x9a, 0x83, 0x97, 0xd2, 0x27, 0x32, 0x45 } }, // NSDockMiniViewWindow
+ }},
+ [0xde] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x5d] = { 0, (unsigned char[]){ 0x3d, 0x4e, 0xd6, 0x7a, 0x5c, 0x6b, 0xe7, 0x4a, 0x4c, 0xa, 0xbf, 0xbe, 0x5f, 0xdf, 0x48, 0x34, 0x80, 0xe8 } }, // NSBrowserColumnViewController
+ [0x96] = { 0, (unsigned char[]){ 0xa9, 0x1e, 0x9e, 0x35, 0x8f, 0x86, 0x47, 0x74, 0xd3, 0x6b, 0x36, 0x41, 0x53, 0x70, 0x40, 0x52, 0xaf, 0xcb } }, // __NSStackBlock__
+ }},
+ [0xe1] = { 0, (unsigned char[]){ 0xbf, 0xae, 0xbb, 0x5e, 0xb3, 0x4f, 0xa1, 0xe6, 0x4e, 0xb0, 0xd7, 0x78, 0x96, 0xba, 0x99, 0x51, 0xc6, 0x14, 0xbe } }, // NSNavPreviewController
+ [0xe5] = { 0, (unsigned char[]){ 0xf0, 0x45, 0x53, 0x1a, 0xc8, 0x5d, 0x6b, 0xec, 0x33, 0x26, 0xf6, 0x40, 0xbe, 0x49, 0x18, 0xab, 0xd1, 0x1d, 0xa8 } }, // NSPersistentUIWindowInfo
+ [0xe6] = { 0, (unsigned char[]){ 0x4f, 0x4f, 0xa8, 0x1f, 0x86, 0x21, 0x2b, 0x2c, 0xea, 0xab, 0xc4, 0xd5, 0x21, 0x66, 0x4c, 0xd8, 0x5b, 0xa0, 0x93 } }, // NSTypeSelectPanel
+ [0xe8] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x58] = { 0, (unsigned char[]){ 0xc1, 0x9e, 0x22, 0x8f, 0x43, 0x27, 0xfc, 0xe4, 0x97, 0xfb, 0x26, 0xeb, 0x32, 0x7b, 0xaf, 0x83, 0xc1, 0x89 } }, // _NSMagnifierWindow
+ [0x8c] = { 0, (unsigned char[]){ 0x19, 0x95, 0x99, 0x16, 0xe0, 0x53, 0x7, 0xfd, 0xe0, 0xde, 0x1c, 0x45, 0x44, 0x2f, 0xa3, 0xaf, 0xee, 0x90 } }, // NSScalarObjectID48
+ }},
+ [0xe9] = { 0, (unsigned char[]){ 0xc6, 0x97, 0x40, 0x80, 0x2e, 0xc7, 0xd2, 0xbd, 0xc9, 0xd9, 0x7b, 0x21, 0x74, 0x23, 0x43, 0xf, 0xe1, 0x5a, 0x71 } }, // NSNavNodePreviewController
+ [0xea] = { 0, (unsigned char[]){ 0x2f, 0x9f, 0x2c, 0xbf, 0x6b, 0xa7, 0x23, 0x7e, 0x64, 0x70, 0xcc, 0x75, 0x9c, 0xa9, 0xbd, 0x70, 0x2c, 0xd1, 0x66 } }, // NSATSTypesetter
+ [0xec] = { 0, (unsigned char[]){ 0xd0, 0xc9, 0x57, 0xaf, 0xce, 0xfe, 0x15, 0xe7, 0xa3, 0xab, 0x2c, 0xda, 0x72, 0xae, 0xad, 0x17, 0x45, 0x86, 0xb1 } }, // _NSPopoverWindow
+ [0xf1] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0xa5] = { 0, (unsigned char[]){ 0x56, 0x9f, 0x8e, 0xfd, 0x1c, 0xc1, 0x5a, 0x15, 0xc5, 0x2, 0xd, 0x56, 0xb4, 0x1b, 0x70, 0x10, 0xdf, 0xa } }, // NSSavePanel
+ [0xf5] = { 0, (unsigned char[]){ 0xf3, 0x38, 0xe1, 0x77, 0x44, 0x43, 0x88, 0x4, 0x36, 0x2, 0x38, 0xfc, 0xfc, 0xfb, 0xa8, 0x17, 0x4c, 0xe } }, // _NSToolbarDefaultImageRepWindow
+ }},
+ [0xf2] = { 0, (unsigned char[]){ 0xce, 0x71, 0x3f, 0x21, 0x3, 0x1b, 0x57, 0x65, 0x33, 0xbf, 0xe7, 0x23, 0x4d, 0x99, 0x82, 0x1b, 0xb9, 0xf6, 0x34 } }, // NSISPureMarkerVariable
+ [0xf3] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0x66] = { 0, (unsigned char[]){ 0x95, 0xb6, 0xa7, 0x27, 0x66, 0x70, 0x2f, 0xc5, 0x4a, 0x38, 0xe6, 0x3b, 0x34, 0xd, 0x54, 0x21, 0x87, 0x8e } }, // NSTempAttributeDictionary
+ [0xb8] = { 0, (unsigned char[]){ 0x8a, 0xcf, 0x23, 0xe6, 0x69, 0xe8, 0x76, 0x42, 0x9d, 0xb1, 0x4a, 0x2, 0xb1, 0x9f, 0x84, 0xa4, 0x39, 0x3e } }, // NSISNonNegativeMarkerVariableToBeMinimized
+ [0xeb] = { 0, (unsigned char[]){ 0x5a, 0x8e, 0x70, 0xf6, 0xbf, 0x41, 0x37, 0x89, 0x2e, 0x94, 0x4b, 0x94, 0x23, 0x7d, 0x34, 0x6c, 0x46, 0xb4 } }, // NSOpenPanel
+ }},
+ [0xf7] = { 0, (unsigned char[]){ 0xcc, 0x3b, 0x53, 0x10, 0x6b, 0x29, 0xa6, 0x2c, 0xbd, 0xb4, 0x33, 0x8f, 0xa2, 0x46, 0x50, 0x9f, 0x97, 0xe6, 0x77 } }, // NSImage
+ [0xf9] = { 0, (unsigned char[]){ 0x89, 0x82, 0x91, 0xa7, 0xfc, 0x43, 0xee, 0x1b, 0x3, 0xef, 0xcc, 0x48, 0x8, 0x11, 0x51, 0x9b, 0x72, 0xe9, 0x14 } }, // NSNavNewFolderController
+ [0xfa] = { 0, (unsigned char[]){ 0x2c, 0xb3, 0xa5, 0x1a, 0xe1, 0xa0, 0x3, 0x94, 0x42, 0xe2, 0x6c, 0xaa, 0xa1, 0xf8, 0x23, 0xb2, 0x12, 0x8e, 0xfd } }, // NSMutableParagraphStyle
+ [0xfc] = { 1, (struct _NativeZWRTableEntry[256]) { // 1
+ [0xd4] = { 0, (unsigned char[]){ 0x7f, 0xea, 0x1b, 0x11, 0xbf, 0xeb, 0x92, 0x57, 0x23, 0x70, 0x9, 0x12, 0x89, 0xaf, 0x84, 0xa2, 0xdf, 0x31 } }, // NSNavProgressWindow
+ [0xd8] = { 0, (unsigned char[]){ 0x12, 0x31, 0x5f, 0x60, 0x61, 0x94, 0x7b, 0x74, 0xde, 0xd5, 0xf9, 0x34, 0x6a, 0x51, 0xff, 0x16, 0xef, 0x1e } }, // NSDrawerWindow
+ }},
+ [0xff] = { 0, (unsigned char[]){ 0xd7, 0x9a, 0x4b, 0x94, 0x11, 0xb7, 0xbb, 0xb8, 0x25, 0x4d, 0x34, 0x60, 0x80, 0x46, 0xdc, 0x3a, 0x95, 0xed, 0xe3 } }, // NSLazyBrowserCell
+};
View
50 GHKit.xcodeproj/project.pbxproj
@@ -22,6 +22,16 @@
006BD88A15AE2FF500D493AE /* ydefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 006BD88315AE2FF500D493AE /* ydefines.h */; };
006BD88B15AE2FF500D493AE /* ydefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 006BD88315AE2FF500D493AE /* ydefines.h */; };
007DA66A154E055C008574F9 /* GHKit-Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 007DA669154E055C008574F9 /* GHKit-Prefix.pch */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0084E6881601103D0036580E /* GH_MAZeroingWeakRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 0084E6851601103D0036580E /* GH_MAZeroingWeakRef.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0084E6891601103D0036580E /* GH_MAZeroingWeakRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 0084E6851601103D0036580E /* GH_MAZeroingWeakRef.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0084E68A1601103D0036580E /* GH_MAZeroingWeakRef.m in Sources */ = {isa = PBXBuildFile; fileRef = 0084E6861601103D0036580E /* GH_MAZeroingWeakRef.m */; };
+ 0084E68B1601103D0036580E /* GH_MAZeroingWeakRef.m in Sources */ = {isa = PBXBuildFile; fileRef = 0084E6861601103D0036580E /* GH_MAZeroingWeakRef.m */; };
+ 0084E68C1601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0084E6871601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0084E68D1601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0084E6871601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0084E6911601106E0036580E /* GH_MAZeroingWeakRefTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0084E6901601106E0036580E /* GH_MAZeroingWeakRefTest.m */; };
+ 0084E6921601106E0036580E /* GH_MAZeroingWeakRefTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0084E6901601106E0036580E /* GH_MAZeroingWeakRefTest.m */; };
+ 0084E693160111220036580E /* GH_MAZeroingWeakRef.m in Sources */ = {isa = PBXBuildFile; fileRef = 0084E6861601103D0036580E /* GH_MAZeroingWeakRef.m */; };
+ 0084E694160111220036580E /* GH_MAZeroingWeakRef.m in Sources */ = {isa = PBXBuildFile; fileRef = 0084E6861601103D0036580E /* GH_MAZeroingWeakRef.m */; };
00D022D8154DF1EB003BAAC3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D022D7154DF1EB003BAAC3 /* Foundation.framework */; };
00D022EA154DF226003BAAC3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D022E9154DF226003BAAC3 /* Cocoa.framework */; };
00D022FC154DF30E003BAAC3 /* GHCGUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 00D0227B154DF1C5003BAAC3 /* GHCGUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -314,6 +324,10 @@
006BD88215AE2FF400D493AE /* ybase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ybase64.h; sourceTree = "<group>"; };
006BD88315AE2FF500D493AE /* ydefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ydefines.h; sourceTree = "<group>"; };
007DA669154E055C008574F9 /* GHKit-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GHKit-Prefix.pch"; sourceTree = "<group>"; };
+ 0084E6851601103D0036580E /* GH_MAZeroingWeakRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GH_MAZeroingWeakRef.h; sourceTree = "<group>"; };
+ 0084E6861601103D0036580E /* GH_MAZeroingWeakRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GH_MAZeroingWeakRef.m; sourceTree = "<group>"; };
+ 0084E6871601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h; sourceTree = "<group>"; };
+ 0084E6901601106E0036580E /* GH_MAZeroingWeakRefTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GH_MAZeroingWeakRefTest.m; sourceTree = "<group>"; };
00D0227B154DF1C5003BAAC3 /* GHCGUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHCGUtils.h; sourceTree = "<group>"; };
00D0227C154DF1C5003BAAC3 /* GHCGUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHCGUtils.m; sourceTree = "<group>"; };
00D0227F154DF1C5003BAAC3 /* GHKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHKit.h; sourceTree = "<group>"; };
@@ -432,7 +446,7 @@
00D0240C154DFA87003BAAC3 /* GTMRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMRegex.h; sourceTree = "<group>"; };
00D0240D154DFA87003BAAC3 /* GTMRegex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMRegex.m; sourceTree = "<group>"; };
00D0240F154DFABF003BAAC3 /* test.file */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = test.file; sourceTree = "<group>"; };
- 00D02415154DFB0C003BAAC3 /* TestsFramework.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = TestsFramework.app; path = GHKitTestsFramework.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 00D02415154DFB0C003BAAC3 /* GHKitTestsFramework.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GHKitTestsFramework.app; sourceTree = BUILT_PRODUCTS_DIR; };
00D0241A154DFB0D003BAAC3 /* TestsFramework-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TestsFramework-Info.plist"; sourceTree = "<group>"; };
00D0241E154DFB0D003BAAC3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
00D02420154DFB0D003BAAC3 /* TestsFramework-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestsFramework-Prefix.pch"; sourceTree = "<group>"; };
@@ -488,6 +502,16 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 0084E6841601103D0036580E /* MAZeroingWeakRef */ = {
+ isa = PBXGroup;
+ children = (
+ 0084E6851601103D0036580E /* GH_MAZeroingWeakRef.h */,
+ 0084E6861601103D0036580E /* GH_MAZeroingWeakRef.m */,
+ 0084E6871601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h */,
+ );
+ path = MAZeroingWeakRef;
+ sourceTree = "<group>";
+ };
00D0226B154DF111003BAAC3 = {
isa = PBXGroup;
children = (
@@ -572,6 +596,7 @@
00D022CA154DF1C5003BAAC3 /* sha1.c */,
00D022CB154DF1C5003BAAC3 /* sha1.h */,
00D022CC154DF1C5003BAAC3 /* Swizzle */,
+ 0084E6841601103D0036580E /* MAZeroingWeakRef */,
007DA669154E055C008574F9 /* GHKit-Prefix.pch */,
);
path = Classes;
@@ -620,7 +645,7 @@
00D022D4154DF1EB003BAAC3 /* libGHKit.a */,
00D022E8154DF226003BAAC3 /* GHKit.framework */,
00D02394154DF67D003BAAC3 /* GHKitTests.app */,
- 00D02415154DFB0C003BAAC3 /* TestsFramework.app */,
+ 00D02415154DFB0C003BAAC3 /* GHKitTestsFramework.app */,
);
name = Products;
sourceTree = "<group>";
@@ -676,6 +701,7 @@
00D023AE154DF89A003BAAC3 /* GHNSStringXMLTest.m */,
00D023AF154DF89A003BAAC3 /* GHReversableDictionaryTest.m */,
00D023B0154DF89A003BAAC3 /* GHValidatorsTest.m */,
+ 0084E6901601106E0036580E /* GH_MAZeroingWeakRefTest.m */,
00D023B1154DF89A003BAAC3 /* iOS */,
00D0240F154DFABF003BAAC3 /* test.file */,
00D0239C154DF67E003BAAC3 /* Supporting Files */,
@@ -788,6 +814,8 @@
006BD87B15AE2FC900D493AE /* GHNSData+Base64.h in Headers */,
006BD88815AE2FF500D493AE /* ybase64.h in Headers */,
006BD88A15AE2FF500D493AE /* ydefines.h in Headers */,
+ 0084E6881601103D0036580E /* GH_MAZeroingWeakRef.h in Headers */,
+ 0084E68C1601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -836,6 +864,8 @@
006BD87C15AE2FC900D493AE /* GHNSData+Base64.h in Headers */,
006BD88915AE2FF500D493AE /* ybase64.h in Headers */,
006BD88B15AE2FF500D493AE /* ydefines.h in Headers */,
+ 0084E6891601103D0036580E /* GH_MAZeroingWeakRef.h in Headers */,
+ 0084E68D1601103D0036580E /* GH_MAZeroingWeakRefNativeZWRNotAllowedTable.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -909,7 +939,7 @@
);
name = GHKitTestsFramework;
productName = TestsFramework;
- productReference = 00D02415154DFB0C003BAAC3 /* TestsFramework.app */;
+ productReference = 00D02415154DFB0C003BAAC3 /* GHKitTestsFramework.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -919,7 +949,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = GH;
- LastUpgradeCheck = 0430;
+ LastUpgradeCheck = 0440;
ORGANIZATIONNAME = rel.me;
};
buildConfigurationList = 00D02270154DF111003BAAC3 /* Build configuration list for PBXProject "GHKit" */;
@@ -1007,6 +1037,7 @@
00D02385154DF45A003BAAC3 /* GHUIColor+Utils.m in Sources */,
006BD87D15AE2FC900D493AE /* GHNSData+Base64.m in Sources */,
006BD88415AE2FF500D493AE /* ybase64.c in Sources */,
+ 0084E68A1601103D0036580E /* GH_MAZeroingWeakRef.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1051,6 +1082,7 @@
00D0238F154DF479003BAAC3 /* GHViewAnimation.m in Sources */,
006BD87E15AE2FC900D493AE /* GHNSData+Base64.m in Sources */,
006BD88515AE2FF500D493AE /* ybase64.c in Sources */,
+ 0084E68B1601103D0036580E /* GH_MAZeroingWeakRef.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1116,6 +1148,8 @@
00D0240E154DFA87003BAAC3 /* GTMRegex.m in Sources */,
006BD87F15AE2FD700D493AE /* GHNSData+Base64.m in Sources */,
006BD88615AE2FF500D493AE /* ybase64.c in Sources */,
+ 0084E6911601106E0036580E /* GH_MAZeroingWeakRefTest.m in Sources */,
+ 0084E693160111220036580E /* GH_MAZeroingWeakRef.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1186,6 +1220,8 @@
00D02477154DFDF1003BAAC3 /* GTMRegex.m in Sources */,
006BD88015AE2FD800D493AE /* GHNSData+Base64.m in Sources */,
006BD88715AE2FF500D493AE /* ybase64.c in Sources */,
+ 0084E6921601106E0036580E /* GH_MAZeroingWeakRefTest.m in Sources */,
+ 0084E694160111220036580E /* GH_MAZeroingWeakRef.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1224,6 +1260,7 @@
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
@@ -1253,6 +1290,7 @@
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Classes/GHKit-Prefix.pch";
+ GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
@@ -1275,6 +1313,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@@ -1311,6 +1350,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1413,6 +1453,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -1449,6 +1490,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
View
25 Tests/GH_MAZeroingWeakRefTest.m
@@ -0,0 +1,25 @@
+//
+// GH_MAZeroingWeakRefTest.m
+// GHKit
+//
+// Created by Gabriel Handford on 9/12/12.
+// Copyright (c) 2012 rel.me. All rights reserved.
+//
+
+#import "GH_MAZeroingWeakRef.h"
+
+
+@interface GH_MAZeroingWeakRefTest : GHTestCase { }
+@end
+
+@implementation GH_MAZeroingWeakRefTest
+
+- (void)test {
+ NSObject *object = [[NSObject alloc] init];
+ GH_MAZeroingWeakRef *weakRef = [GH_MAZeroingWeakRef refWithTarget:object];
+ [object release];
+ [weakRef.target hash];
+}
+
+@end
+
Please sign in to comment.
Something went wrong with that request. Please try again.