-
-
Save maicoder/146fba1b966abf180bac21ce2325574c to your computer and use it in GitHub Desktop.
Revisions
-
steipete revised this gist
Jul 6, 2016 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,8 @@ // // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. // PLEASE DUPE rdar://27192338 (https://openradar.appspot.com/27192338) if you would like to see this in UIKit. #import <objc/runtime.h> #import <objc/message.h> -
steipete revised this gist
Jun 10, 2016 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -16,7 +16,11 @@ // http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { NSCParameterAssert(c); NSCParameterAssert(origSEL); NSCParameterAssert(newSEL); NSCParameterAssert(block); if ([c instancesRespondToSelector:newSEL]) return YES; // Selector already implemented, skip silently. Method origMethod = class_getInstanceMethod(c, origSEL); -
steipete revised this gist
Sep 16, 2014 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ // Taken from the commercial iOS PDF framework http://pspdfkit.com. // Copyright (c) 2014 Peter Steinberger, PSPDFKit GmbH. All rights reserved. // Licensed under MIT (http://opensource.org/licenses/MIT) // // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. -
steipete revised this gist
Sep 16, 2014 . 1 changed file with 38 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,6 +14,44 @@ #define PROPERTY(propName) @#propName #endif // http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { PSPDFAssert(c && origSEL && newSEL && block); if ([c instancesRespondToSelector:newSEL]) return YES; // Selector already implemented, skip silently. Method origMethod = class_getInstanceMethod(c, origSEL); // Add the new method. IMP impl = imp_implementationWithBlock(block); if (!class_addMethod(c, newSEL, impl, method_getTypeEncoding(origMethod))) { PSPDFLogError(@"Failed to add method: %@ on %@", NSStringFromSelector(newSEL), c); return NO; }else { Method newMethod = class_getInstanceMethod(c, newSEL); // If original doesn't implement the method we want to swizzle, create it. if (class_addMethod(c, origSEL, method_getImplementation(newMethod), method_getTypeEncoding(origMethod))) { class_replaceMethod(c, newSEL, method_getImplementation(origMethod), method_getTypeEncoding(newMethod)); }else { method_exchangeImplementations(origMethod, newMethod); } } return YES; } SEL _PSPDFPrefixedSelector(SEL selector) { return NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", NSStringFromSelector(selector)]); } #define PSPDFAssert(expression, ...) \ do { if(!(expression)) { \ NSLog(@"%@", [NSString stringWithFormat: @"Assertion failure: %s in %s on line %s:%d. %@", #expression, __PRETTY_FUNCTION__, __FILE__, __LINE__, [NSString stringWithFormat:@"" __VA_ARGS__]]); \ abort(); }} while(0) void PSPDFAssertIfNotMainThread(void) { PSPDFAssert(NSThread.isMainThread, @"\nERROR: All calls to UIKit need to happen on the main thread. You have a bug in your code. Use dispatch_async(dispatch_get_main_queue(), ^{ ... }); if you're unsure what thread you're in.\n\nBreak on PSPDFAssertIfNotMainThread to find out where.\n\nStacktrace: %@", NSThread.callStackSymbols); } __attribute__((constructor)) static void PSPDFUIKitMainThreadGuard(void) { @autoreleasepool { for (NSString *selStr in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) { -
steipete revised this gist
Sep 16, 2014 . 1 changed file with 26 additions and 51 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,70 +14,45 @@ #define PROPERTY(propName) @#propName #endif __attribute__((constructor)) static void PSPDFUIKitMainThreadGuard(void) { @autoreleasepool { for (NSString *selStr in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) { SEL selector = NSSelectorFromString(selStr); SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selStr]); if ([selStr hasSuffix:@":"]) { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self, CGRect r) { // Check for window, since *some* UIKit methods are indeed thread safe. // https://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html /* Drawing to a graphics context in UIKit is now thread-safe. Specifically: The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads. String and image drawing is now thread-safe. Using color and font objects in multiple threads is now safe to do. */ if (_self.window) PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r); }); }else { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self) { if (_self.window) { if (!NSThread.isMainThread) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" dispatch_queue_t queue = dispatch_get_current_queue(); #pragma clang diagnostic pop // iOS 8 layouts the MFMailComposeController in a background thread on an UIKit queue. // https://github.com/PSPDFKit/PSPDFKit/issues/1423 if (!queue || !strstr(dispatch_queue_get_label(queue), "UIKit")) { PSPDFAssertIfNotMainThread(); } } } ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); }); } } } } -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,6 @@ #import <objc/runtime.h> #import <objc/message.h> // Compile-time selector checks. #if DEBUG -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,6 +8,7 @@ #import <objc/message.h> #import <QuartzCore/QuartzCore.h> // Compile-time selector checks. #if DEBUG #define PROPERTY(propName) NSStringFromSelector(@selector(propName)) #else -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -24,6 +24,9 @@ NSLog(@"%@", [NSString stringWithFormat: @"Assertion failure: %s in %s on line %s:%d. %@", #expression, __PRETTY_FUNCTION__, __FILE__, __LINE__, [NSString stringWithFormat:@"" __VA_ARGS__]]); \ abort(); }} while(0) /////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - Helper for Swizzling BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { PSPDFAssert(c && origSEL && newSEL && block); Method origMethod = class_getInstanceMethod(c, origSEL); -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ // Taken from the commercial iOS PDF framework http://pspdfkit.com. // Copyright (c) 2013 Peter Steinberger. All rights reserved. // Licensed under MIT (http://opensource.org/licenses/MIT) // // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -25,7 +25,7 @@ abort(); }} while(0) BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { PSPDFAssert(c && origSEL && newSEL && block); Method origMethod = class_getInstanceMethod(c, origSEL); const char *encoding = method_getTypeEncoding(origMethod); @@ -37,7 +37,7 @@ BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { }else { // Ensure the new selector has the same parameters as the existing selector. Method newMethod = class_getInstanceMethod(c, newSEL); PSPDFAssert(strcmp(method_getTypeEncoding(origMethod), method_getTypeEncoding(newMethod)) == 0, @"Encoding must be the same."); // If original doesn't implement the method we want to swizzle, create it. if (class_addMethod(c, origSEL, method_getImplementation(newMethod), encoding)) { -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 7 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,12 +1,18 @@ // Taken from the commercial iOS PDF framework http://pspdfkit.com. // Copyright (c) 2013 Peter Steinberger. All rights reserved. // Licensed under MIT. // // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. #import <objc/runtime.h> #import <objc/message.h> #import <QuartzCore/QuartzCore.h> #if DEBUG #define PROPERTY(propName) NSStringFromSelector(@selector(propName)) #else #define PROPERTY(propName) @#propName #endif // A better assert. NSAssert is too runtime dependant, and assert() doesn't log. // http://www.mikeash.com/pyblog/friday-qa-2013-05-03-proper-use-of-asserts.html @@ -18,9 +24,6 @@ NSLog(@"%@", [NSString stringWithFormat: @"Assertion failure: %s in %s on line %s:%d. %@", #expression, __PRETTY_FUNCTION__, __FILE__, __LINE__, [NSString stringWithFormat:@"" __VA_ARGS__]]); \ abort(); }} while(0) BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { NSCParameterAssert(c && origSEL && newSEL && block); Method origMethod = class_getInstanceMethod(c, origSEL); @@ -74,6 +77,4 @@ static void PSPDFAssertIfNotMainThread(void) { } } } } -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,7 @@ // Taken from the commercial iOS PDF framework http://pspdfkit.com. // Copyright (c) 2013 Peter Steinberger. All rights reserved. // Licensed under MIT. #import <objc/runtime.h> #import <objc/message.h> #import <QuartzCore/QuartzCore.h> -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -58,12 +58,12 @@ static void PSPDFAssertIfNotMainThread(void) { SEL selector = NSSelectorFromString(selStr); SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selStr]); if ([selStr hasSuffix:@":"]) { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self, CGRect r) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r); }); }else { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); }); -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 29 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,21 +17,29 @@ // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. #ifdef DEBUG BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { NSCParameterAssert(c && origSEL && newSEL && block); Method origMethod = class_getInstanceMethod(c, origSEL); const char *encoding = method_getTypeEncoding(origMethod); // Add the new method. IMP impl = imp_implementationWithBlock(block); if (!class_addMethod(c, newSEL, impl, encoding)) { NSLog(@"Failed to add method: %@ on %@", NSStringFromSelector(newSEL), c); return NO; }else { // Ensure the new selector has the same parameters as the existing selector. Method newMethod = class_getInstanceMethod(c, newSEL); NSCAssert(strcmp(method_getTypeEncoding(origMethod), method_getTypeEncoding(newMethod)) == 0, @"Encoding must be the same."); // If original doesn't implement the method we want to swizzle, create it. if (class_addMethod(c, origSEL, method_getImplementation(newMethod), encoding)) { class_replaceMethod(c, newSEL, method_getImplementation(origMethod), encoding); }else { method_exchangeImplementations(origMethod, newMethod); } } return YES; } /////////////////////////////////////////////////////////////////////////////////////////// @@ -46,18 +54,19 @@ static void PSPDFAssertIfNotMainThread(void) { // @note No private API is used here. __attribute__((constructor)) static void PSPDFUIKitMainThreadGuard(void) { @autoreleasepool { for (NSString *selStr in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) { SEL selector = NSSelectorFromString(selStr); SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selStr]); if ([selStr hasSuffix:@":"]) { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(UIView *_self, CGRect r) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r); }); }else { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(UIView *_self) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); }); } } } -
steipete revised this gist
Jun 2, 2013 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -30,15 +30,15 @@ static void PSPDFSwizzleMethod(Class c, SEL orig, SEL new) { void PSPDFReplaceMethod(Class c, SEL orig, SEL newSel, IMP impl) { Method method = class_getInstanceMethod(c, orig); if (!class_addMethod(c, newSel, impl, method_getTypeEncoding(method))) { NSLog(@"Failed to add method: %@ on %@", NSStringFromSelector(newSel), c); }else PSPDFSwizzleMethod(c, orig, newSel); } /////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - Tracks down calls to UIKit from a Thread other than Main static void PSPDFAssertIfNotMainThread(void) { PSPDFAssert(NSThread.isMainThread, @"\nERROR: All calls to UIKit need to happen on the main thread. You have a bug in your code. Use dispatch_async(dispatch_get_main_queue(), ^{ ... }); if you're unsure what thread you're in.\n\nBreak on PSPDFAssertIfNotMainThread to find out where.\n\nStacktrace: %@", [NSThread callStackSymbols]); } // This installs a small guard that checks for the most common threading-errors in UIKit. -
steipete revised this gist
May 28, 2013 . 1 changed file with 10 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -48,18 +48,16 @@ static void PSPDFAssertIfNotMainThread(void) { @autoreleasepool { for (NSString *selector in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) { SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selector]); if ([selector hasSuffix:@":"]) { PSPDFReplaceMethod(UIView.class, NSSelectorFromString(selector), newSelector, imp_implementationWithBlock(^(UIView *_self, CGRect r) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r); })); }else { PSPDFReplaceMethod(UIView.class, NSSelectorFromString(selector), newSelector, imp_implementationWithBlock(^(UIView *_self) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); })); } } } -
steipete revised this gist
May 28, 2013 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,16 @@ #define PROPERTY(propName) NSStringFromSelector(@selector(propName)) // A better assert. NSAssert is too runtime dependant, and assert() doesn't log. // http://www.mikeash.com/pyblog/friday-qa-2013-05-03-proper-use-of-asserts.html // Accepts both: // - PSPDFAssert(x > 0); // - PSPDFAssert(y > 3, @"Bad value for y"); #define PSPDFAssert(expression, ...) \ do { if(!(expression)) { \ NSLog(@"%@", [NSString stringWithFormat: @"Assertion failure: %s in %s on line %s:%d. %@", #expression, __PRETTY_FUNCTION__, __FILE__, __LINE__, [NSString stringWithFormat:@"" __VA_ARGS__]]); \ abort(); }} while(0) // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. #ifdef DEBUG -
steipete revised this gist
May 28, 2013 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,8 @@ #import <objc/message.h> #import <QuartzCore/QuartzCore.h> #define PROPERTY(propName) NSStringFromSelector(@selector(propName)) // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. #ifdef DEBUG -
steipete revised this gist
May 28, 2013 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -52,4 +52,5 @@ static void PSPDFAssertIfNotMainThread(void) { } } } #endif -
steipete revised this gist
May 28, 2013 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,9 @@ #import <objc/message.h> #import <QuartzCore/QuartzCore.h> // You should only use this in debug builds. It doesn't use private API, but I wouldn't ship it. #ifdef DEBUG static void PSPDFSwizzleMethod(Class c, SEL orig, SEL new) { Method origMethod = class_getInstanceMethod(c, orig); Method newMethod = class_getInstanceMethod(c, new); @@ -48,4 +51,5 @@ static void PSPDFAssertIfNotMainThread(void) { } } } } #endif -
steipete created this gist
May 28, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,51 @@ #import <objc/runtime.h> #import <objc/message.h> #import <QuartzCore/QuartzCore.h> static void PSPDFSwizzleMethod(Class c, SEL orig, SEL new) { 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); } } void PSPDFReplaceMethod(Class c, SEL orig, SEL newSel, IMP impl) { Method method = class_getInstanceMethod(c, orig); if (!class_addMethod(c, newSel, impl, method_getTypeEncoding(method))) { PSPDFLogError(@"Failed to add method: %@ on %@", NSStringFromSelector(newSel), c); }else PSPDFSwizzleMethod(c, orig, newSel); } /////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - Tracks down calls to UIKit from a Thread other than Main static void PSPDFAssertIfNotMainThread(void) { PSPDFAssert([NSThread isMainThread], @"\nERROR: All calls to UIKit need to happen on the main thread. You have a bug in your code. Use dispatch_async(dispatch_get_main_queue(), ^{ ... }); if you're unsure what thread you're in.\n\nBreak on PSPDFAssertIfNotMainThread to find out where.\n\nStacktrace: %@", [NSThread callStackSymbols]); } // This installs a small guard that checks for the most common threading-errors in UIKit. // This won't really slow down performance but still only is compiled in DEBUG versions of PSPDFKit. // @note No private API is used here. __attribute__((constructor)) static void PSPDFUIKitMainThreadGuard(void) { @autoreleasepool { for (NSString *selector in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) { SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selector]); for (Class theClass in @[UIView.class, CALayer.class]) { if ([selector hasSuffix:@":"]) { PSPDFReplaceMethod(theClass, NSSelectorFromString(selector), newSelector, imp_implementationWithBlock(^(UIView *_self, CGRect r) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r); })); }else { PSPDFReplaceMethod(theClass, NSSelectorFromString(selector), newSelector, imp_implementationWithBlock(^(UIView *_self) { PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); })); } } } } }