Skip to content

Instantly share code, notes, and snippets.

@chrishulbert
Created June 1, 2011 03:46
Show Gist options
  • Select an option

  • Save chrishulbert/1001758 to your computer and use it in GitHub Desktop.

Select an option

Save chrishulbert/1001758 to your computer and use it in GitHub Desktop.
Simulating iOS memory warnings
#if TARGET_IPHONE_SIMULATOR
#import <objc/objc-class.h>
// http://cocoawithlove.com/2008/02/imp-of-current-method.html
IMP impOfCallingMethod(id lookupObject, SEL selector)
{
NSUInteger returnAddress = (NSUInteger)__builtin_return_address(0);
NSUInteger closest = 0;
// Iterate over the class and all superclasses
Class currentClass = object_getClass(lookupObject);
while (currentClass)
{
// Iterate over all instance methods for this class
unsigned int methodCount;
Method *methodList = class_copyMethodList(currentClass, &methodCount);
unsigned int i;
for (i = 0; i < methodCount; i++)
{
// Ignore methods with different selectors
if (method_getName(methodList[i]) != selector)
{
continue;
}
// If this address is closer, use it instead
NSUInteger address = (NSUInteger)method_getImplementation(methodList[i]);
if (address < returnAddress && address > closest)
{
closest = address;
}
}
free(methodList);
currentClass = class_getSuperclass(currentClass);
}
return (IMP)closest;
}
// http://cocoawithlove.com/2008/03/supersequent-implementation.html
#define invokeSupersequent(...) \
([self getImplementationOf:_cmd \
after:impOfCallingMethod(self, _cmd)]) \
(self, _cmd, ##__VA_ARGS__)
#define invokeSupersequentNoParameters() \
([self getImplementationOf:_cmd \
after:impOfCallingMethod(self, _cmd)]) \
(self, _cmd)
@interface NSObject (SupersequentImplementation)
- (IMP)getImplementationOf:(SEL)lookup after:(IMP)skip;
@end
@implementation NSObject (SupersequentImplementation)
// Lookup the next implementation of the given selector after the
// default one. Returns nil if no alternate implementation is found.
- (IMP)getImplementationOf:(SEL)lookup after:(IMP)skip
{
BOOL found = NO;
Class currentClass = object_getClass(self);
while (currentClass)
{
// Get the list of methods for this class
unsigned int methodCount;
Method *methodList = class_copyMethodList(currentClass, &methodCount);
// Iterate over all methods
unsigned int i;
for (i = 0; i < methodCount; i++)
{
// Look for the selector
if (method_getName(methodList[i]) != lookup)
{
continue;
}
IMP implementation = method_getImplementation(methodList[i]);
// Check if this is the "skip" implementation
if (implementation == skip)
{
found = YES;
}
else if (found)
{
// Return the match.
free(methodList);
return implementation;
}
}
// No match found. Traverse up through super class' methods.
free(methodList);
currentClass = class_getSuperclass(currentClass);
}
return nil;
}
@end
// http://idevrecipes.com/2011/05/04/debugging-magic-auto-simulate-memory-warnings/
@implementation UIViewController (MemoryWarningCategory)
- (void) viewDidAppear:(BOOL)animated {
IMP superSequentImp = (IMP)[self getImplementationOf:_cmd after:impOfCallingMethod(self, _cmd)];
((void(*)(id, SEL, BOOL))superSequentImp)(self, _cmd, animated);
// If we are running in the simulator then simulate a memory warning.
NSLog(@"Faking a memory warning");
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)@"UISimulatedMemoryWarningNotification", NULL, NULL, true);
}
@end
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment