NSObject+DTRuntime.m 2.76 KiB
//
//  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 {
71727374757677787980818283848586878889909192939495
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