// // NSObject_DTRuntime.h // DTFoundation // // Created by Oliver Drobnik on 4/25/12. // Copyright (c) 2012 Cocoanetics. All rights reserved. // #import <objc/runtime.h> #import "DTObjectBlockExecutor.h" @implementation NSObject (DTRuntime) static char DTRuntimeDeallocBlocks; #pragma mark - Blocks - (void)addDeallocBlock:(void (^)())block { // don't accept NULL block NSParameterAssert(block); NSMutableArray *deallocBlocks = objc_getAssociatedObject(self, &DTRuntimeDeallocBlocks); // add array of dealloc blocks if not existing yet if (!deallocBlocks) { deallocBlocks = [[NSMutableArray alloc] init]; objc_setAssociatedObject(self, &DTRuntimeDeallocBlocks, deallocBlocks, OBJC_ASSOCIATION_RETAIN); } DTObjectBlockExecutor *executor = [DTObjectBlockExecutor blockExecutorWithDeallocBlock:block]; [deallocBlocks addObject:executor]; } + (BOOL)addInstanceMethodWithSelectorName:(NSString *)selectorName block:(void (^)(id))block { // don't accept nil name NSParameterAssert(selectorName); // don't accept NULL block NSParameterAssert(block); // See http://stackoverflow.com/questions/6357663/casting-a-block-to-a-void-for-dynamic-class-method-resolution #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_7 void *impBlockForIMP = (void *)objc_unretainedPointer(block); #else id impBlockForIMP = block; #endif IMP myIMP = imp_implementationWithBlock(impBlockForIMP); SEL selector = NSSelectorFromString(selectorName); return class_addMethod(self, selector, myIMP, "v@:"); } #pragma mark - Method Swizzling + (void)swizzleMethod:(SEL)selector withMethod:(SEL)otherSelector { // my own class is being targetted Class c = [self class]; // get the methods from the selectors Method originalMethod = class_getInstanceMethod(c, selector); Method otherMethod = class_getInstanceMethod(c, otherSelector); if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod))) { class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, otherMethod); } } + (void)swizzleClassMethod:(SEL)selector withMethod:(SEL)otherSelector { // my own class is being targetted Class c = [self class]; // get the methods from the selectors Method originalMethod = class_getClassMethod(c, selector); Method otherMethod = class_getClassMethod(c, otherSelector); // if (class_addMethod(c, selector, method_getImplementation(otherMethod), method_getTypeEncoding(otherMethod))) // { // class_replaceMethod(c, otherSelector, method_getImplementation(originalMethod), // method_getTypeEncoding(originalMethod)); // } // else // { method_exchangeImplementations(originalMethod, otherMethod); // } } @end