├── .gitignore ├── .swift-version ├── .travis.yml ├── Example ├── Podfile ├── Podfile.lock ├── Pods │ ├── JRSwizzle │ │ ├── JRSwizzle.h │ │ ├── JRSwizzle.m │ │ └── README.markdown │ ├── Local Podspecs │ │ └── WTSafeGuard.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── JRSwizzle │ │ ├── Info.plist │ │ ├── JRSwizzle-dummy.m │ │ ├── JRSwizzle-prefix.pch │ │ ├── JRSwizzle-umbrella.h │ │ ├── JRSwizzle.modulemap │ │ └── JRSwizzle.xcconfig │ │ ├── Pods-WTSafeGuard_Example │ │ ├── Info.plist │ │ ├── Pods-WTSafeGuard_Example-acknowledgements.markdown │ │ ├── Pods-WTSafeGuard_Example-acknowledgements.plist │ │ ├── Pods-WTSafeGuard_Example-dummy.m │ │ ├── Pods-WTSafeGuard_Example-frameworks.sh │ │ ├── Pods-WTSafeGuard_Example-resources.sh │ │ ├── Pods-WTSafeGuard_Example-umbrella.h │ │ ├── Pods-WTSafeGuard_Example.debug.xcconfig │ │ ├── Pods-WTSafeGuard_Example.modulemap │ │ └── Pods-WTSafeGuard_Example.release.xcconfig │ │ ├── Pods-WTSafeGuard_Tests │ │ ├── Info.plist │ │ ├── Pods-WTSafeGuard_Tests-acknowledgements.markdown │ │ ├── Pods-WTSafeGuard_Tests-acknowledgements.plist │ │ ├── Pods-WTSafeGuard_Tests-dummy.m │ │ ├── Pods-WTSafeGuard_Tests-frameworks.sh │ │ ├── Pods-WTSafeGuard_Tests-resources.sh │ │ ├── Pods-WTSafeGuard_Tests-umbrella.h │ │ ├── Pods-WTSafeGuard_Tests.debug.xcconfig │ │ ├── Pods-WTSafeGuard_Tests.modulemap │ │ └── Pods-WTSafeGuard_Tests.release.xcconfig │ │ └── WTSafeGuard │ │ ├── Info.plist │ │ ├── WTSafeGuard-dummy.m │ │ ├── WTSafeGuard-prefix.pch │ │ ├── WTSafeGuard-umbrella.h │ │ ├── WTSafeGuard.modulemap │ │ └── WTSafeGuard.xcconfig ├── Tests │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj │ │ └── InfoPlist.strings ├── WTSafeGuard.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── WTSafeGuard-Example.xcscheme ├── WTSafeGuard.xcworkspace │ └── contents.xcworkspacedata └── WTSafeGuard │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── WTAppDelegate.h │ ├── WTAppDelegate.m │ ├── WTSafeGuard-Info.plist │ ├── WTSafeGuard-Prefix.pch │ ├── WTViewController.h │ ├── WTViewController.m │ ├── en.lproj │ └── InfoPlist.strings │ └── main.m ├── README.md ├── WTSafeGuard.podspec ├── WTSafeGuard ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── Container │ ├── NSAttributedString+WTSafe.h │ ├── NSAttributedString+WTSafe.m │ ├── NSDictionary+WTSafe.h │ ├── NSDictionary+WTSafe.m │ ├── NSFileManager+WTSafe.h │ ├── NSFileManager+WTSafe.m │ ├── NSIndexPath+WTSafe.h │ ├── NSIndexPath+WTSafe.m │ ├── NSJSONSerialization+WTSafe.h │ ├── NSJSONSerialization+WTSafe.m │ ├── NSMutableDictionary+WTSafe.h │ ├── NSMutableDictionary+WTSafe.m │ ├── NSMutableSet+WTSafe.h │ ├── NSMutableSet+WTSafe.m │ ├── NSMutableString+WTSafe.h │ ├── NSMutableString+WTSafe.m │ ├── NSSet+WTSafe.h │ ├── NSSet+WTSafe.m │ ├── NSString+WTSafe.h │ ├── NSString+WTSafe.m │ ├── NSURL+WTSafe.h │ └── NSURL+WTSafe.m │ ├── KVO │ ├── WTKVOMapManager.h │ ├── WTKVOMapManager.m │ ├── WTKVOResource.h │ └── WTKVOResource.m │ ├── NSObject+WTSafe.h │ ├── NSObject+WTSafe.m │ ├── Target │ ├── WTFakeForwardTargetObject.h │ └── WTFakeForwardTargetObject.m │ ├── Timer │ ├── NSTimer+WTSafe.h │ ├── NSTimer+WTSafe.m │ ├── WTWeakTimerTarget.h │ └── WTWeakTimerTarget.m │ ├── UI │ ├── UIPasteboard+WTSafe.h │ ├── UIPasteboard+WTSafe.m │ ├── UIView+WTSafe.h │ └── UIView+WTSafe.m │ ├── WTSafeGuard.h │ └── WTSafeGuard.m └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Note: if you ignore the Pods directory, make sure to uncomment 31 | # `pod install` in .travis.yml 32 | # 33 | # Pods/ 34 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 2.3 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -workspace Example/WTSafeGuard.xcworkspace -scheme WTSafeGuard-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'WTSafeGuard_Example' do 4 | pod 'WTSafeGuard', :path => '../' 5 | 6 | target 'WTSafeGuard_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - JRSwizzle (1.0) 3 | - WTSafeGuard (1.3.0): 4 | - JRSwizzle 5 | 6 | DEPENDENCIES: 7 | - WTSafeGuard (from `../`) 8 | 9 | EXTERNAL SOURCES: 10 | WTSafeGuard: 11 | :path: ../ 12 | 13 | SPEC CHECKSUMS: 14 | JRSwizzle: dd5ead5d913a0f29e7f558200165849f006bb1e3 15 | WTSafeGuard: b2f60762704cd279abaab22a6caef5c3f131265c 16 | 17 | PODFILE CHECKSUM: f38df40f5d74089817f4f9d44c4669ee3c39834a 18 | 19 | COCOAPODS: 1.4.0.beta.1 20 | -------------------------------------------------------------------------------- /Example/Pods/JRSwizzle/JRSwizzle.h: -------------------------------------------------------------------------------- 1 | // JRSwizzle.h semver:1.0 2 | // Copyright (c) 2007-2011 Jonathan 'Wolf' Rentzsch: http://rentzsch.com 3 | // Some rights reserved: http://opensource.org/licenses/MIT 4 | // https://github.com/rentzsch/jrswizzle 5 | 6 | #import 7 | 8 | @interface NSObject (JRSwizzle) 9 | 10 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_; 11 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/Pods/JRSwizzle/JRSwizzle.m: -------------------------------------------------------------------------------- 1 | // JRSwizzle.m semver:1.0 2 | // Copyright (c) 2007-2011 Jonathan 'Wolf' Rentzsch: http://rentzsch.com 3 | // Some rights reserved: http://opensource.org/licenses/MIT 4 | // https://github.com/rentzsch/jrswizzle 5 | 6 | #import "JRSwizzle.h" 7 | 8 | #if TARGET_OS_IPHONE 9 | #import 10 | #import 11 | #else 12 | #import 13 | #endif 14 | 15 | #define SetNSErrorFor(FUNC, ERROR_VAR, FORMAT,...) \ 16 | if (ERROR_VAR) { \ 17 | NSString *errStr = [NSString stringWithFormat:@"%s: " FORMAT,FUNC,##__VA_ARGS__]; \ 18 | *ERROR_VAR = [NSError errorWithDomain:@"NSCocoaErrorDomain" \ 19 | code:-1 \ 20 | userInfo:[NSDictionary dictionaryWithObject:errStr forKey:NSLocalizedDescriptionKey]]; \ 21 | } 22 | #define SetNSError(ERROR_VAR, FORMAT,...) SetNSErrorFor(__func__, ERROR_VAR, FORMAT, ##__VA_ARGS__) 23 | 24 | #if OBJC_API_VERSION >= 2 25 | #define GetClass(obj) object_getClass(obj) 26 | #else 27 | #define GetClass(obj) (obj ? obj->isa : Nil) 28 | #endif 29 | 30 | @implementation NSObject (JRSwizzle) 31 | 32 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ { 33 | #if OBJC_API_VERSION >= 2 34 | Method origMethod = class_getInstanceMethod(self, origSel_); 35 | if (!origMethod) { 36 | #if TARGET_OS_IPHONE 37 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self class]); 38 | #else 39 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); 40 | #endif 41 | return NO; 42 | } 43 | 44 | Method altMethod = class_getInstanceMethod(self, altSel_); 45 | if (!altMethod) { 46 | #if TARGET_OS_IPHONE 47 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self class]); 48 | #else 49 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); 50 | #endif 51 | return NO; 52 | } 53 | 54 | class_addMethod(self, 55 | origSel_, 56 | class_getMethodImplementation(self, origSel_), 57 | method_getTypeEncoding(origMethod)); 58 | class_addMethod(self, 59 | altSel_, 60 | class_getMethodImplementation(self, altSel_), 61 | method_getTypeEncoding(altMethod)); 62 | 63 | method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_)); 64 | return YES; 65 | #else 66 | // Scan for non-inherited methods. 67 | Method directOriginalMethod = NULL, directAlternateMethod = NULL; 68 | 69 | void *iterator = NULL; 70 | struct objc_method_list *mlist = class_nextMethodList(self, &iterator); 71 | while (mlist) { 72 | int method_index = 0; 73 | for (; method_index < mlist->method_count; method_index++) { 74 | if (mlist->method_list[method_index].method_name == origSel_) { 75 | assert(!directOriginalMethod); 76 | directOriginalMethod = &mlist->method_list[method_index]; 77 | } 78 | if (mlist->method_list[method_index].method_name == altSel_) { 79 | assert(!directAlternateMethod); 80 | directAlternateMethod = &mlist->method_list[method_index]; 81 | } 82 | } 83 | mlist = class_nextMethodList(self, &iterator); 84 | } 85 | 86 | // If either method is inherited, copy it up to the target class to make it non-inherited. 87 | if (!directOriginalMethod || !directAlternateMethod) { 88 | Method inheritedOriginalMethod = NULL, inheritedAlternateMethod = NULL; 89 | if (!directOriginalMethod) { 90 | inheritedOriginalMethod = class_getInstanceMethod(self, origSel_); 91 | if (!inheritedOriginalMethod) { 92 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); 93 | return NO; 94 | } 95 | } 96 | if (!directAlternateMethod) { 97 | inheritedAlternateMethod = class_getInstanceMethod(self, altSel_); 98 | if (!inheritedAlternateMethod) { 99 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); 100 | return NO; 101 | } 102 | } 103 | 104 | int hoisted_method_count = !directOriginalMethod && !directAlternateMethod ? 2 : 1; 105 | struct objc_method_list *hoisted_method_list = malloc(sizeof(struct objc_method_list) + (sizeof(struct objc_method)*(hoisted_method_count-1))); 106 | hoisted_method_list->obsolete = NULL; // soothe valgrind - apparently ObjC runtime accesses this value and it shows as uninitialized in valgrind 107 | hoisted_method_list->method_count = hoisted_method_count; 108 | Method hoisted_method = hoisted_method_list->method_list; 109 | 110 | if (!directOriginalMethod) { 111 | bcopy(inheritedOriginalMethod, hoisted_method, sizeof(struct objc_method)); 112 | directOriginalMethod = hoisted_method++; 113 | } 114 | if (!directAlternateMethod) { 115 | bcopy(inheritedAlternateMethod, hoisted_method, sizeof(struct objc_method)); 116 | directAlternateMethod = hoisted_method; 117 | } 118 | class_addMethods(self, hoisted_method_list); 119 | } 120 | 121 | // Swizzle. 122 | IMP temp = directOriginalMethod->method_imp; 123 | directOriginalMethod->method_imp = directAlternateMethod->method_imp; 124 | directAlternateMethod->method_imp = temp; 125 | 126 | return YES; 127 | #endif 128 | } 129 | 130 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ { 131 | return [GetClass((id)self) jr_swizzleMethod:origSel_ withMethod:altSel_ error:error_]; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /Example/Pods/JRSwizzle/README.markdown: -------------------------------------------------------------------------------- 1 | # JRSwizzle 2 | 3 | ## Description 4 | 5 | JRSwizzle is source code package that offers a single, easy, correct+consistent interface for exchanging Objective-C method implementations ("method swizzling") across many versions of Mac OS X, iOS, Objective-C and runtime architectures. 6 | 7 | More succinctly: *JRSwizzle wants to be your one-stop-shop for all your method swizzling needs.* 8 | 9 | ## Download 10 | 11 | $ cd /path/to/top/of/your/project 12 | $ git submodule add git://github.com/rentzsch/jrswizzle.git JRSwizzle 13 | $ git submodule init && git submodule update 14 | 15 | # OPTIONAL: Execute the following commands if you want to explicitly peg 16 | # to a certain version. Otherwise `git submodule update` will keep you 17 | # current with HEAD. 18 | 19 | $ cd JRSwizzle 20 | $ git checkout v1.0 21 | 22 | ## Reasons for Existence 23 | 24 | * **Easy:** Just do this: `[SomeClass jr_swizzle:@selector(foo) withMethod:@selector(my_foo) error:&error];` Voila. 25 | * **Correct:** There's a subtle interaction between method swizzling and method inheritance. Following in Kevin Ballard's footsteps, this package Does The Right Thing. 26 | * **Compatible:** JRSwizzle should Just Work on any version of Mac OS X and iOS you care about. Here's the exhaustive compatibility list: 27 | * Mac OS X v10.3/ppc (Ballard implementation) 28 | * Mac OS X v10.4/ppc (Ballard implementation) 29 | * Mac OS X v10.4/i386 (Ballard implementation) 30 | * Mac OS X v10.5/ppc (method_exchangeImplementations+Ballard implementation) 31 | * Mac OS X v10.5/i386 (method_exchangeImplementations+Ballard implementation) 32 | * Mac OS X v10.5/ppc64 (method_exchangeImplementations+Ballard implementation) 33 | * Mac OS X v10.5/x86_64 (method_exchangeImplementations+Ballard implementation) 34 | * iOS 2.0+ (method_exchangeImplementations+Ballard implementation) 35 | * **Robust:** All parameters are checked and JRSwizzle returns an optional `NSError` with high-quality diagnostics. 36 | 37 | ## Support 38 | 39 | Please use [JRSwizzle's GitHub Issues tab](https://github.com/rentzsch/jrswizzle/issues) to [file bugs or feature requests](https://github.com/rentzsch/jrswizzle/issues/new). 40 | 41 | To contribute, please fork this project, make+commit your changes and then send me a pull request. 42 | 43 | ## Comparison 44 | 45 | There's at least four swizzling implementations floating around. Here's a comparison chart to help you make sense of how they relate to each other and why JRSwizzle exists. 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
ScenarioSwizzle TechnologyMethod ImplementationCorrect Behavior10.464-bit
1ClassicDirectYESYESNO
2ClassicInheritedNOYESNO
3BallardDirectYESYESNO
4BallardInheritedYESYESNO
5AppleDirectYESNOYES
6AppleInheritedNONOYES
7JRSwizzleDirectYESYESYES
8JRSwizzleInheritedYESYESYES
121 | 122 | * *Classic* is the canonical `MethodSwizzle()` implementation as described in [CocoaDev's MethodSwizzling page](http://www.cocoadev.com/index.pl?MethodSwizzling). 123 | * *Ballard* is [Kevin Ballard's improved implementation](http://kevin.sb.org/2006/12/30/method-swizzling-reimplemented/) which solves the inherited method problem. 124 | * *Apple* is 10.5's new `method_exchangeImplementations` API. 125 | * *JRSwizzle* is this package. 126 | 127 | ## License 128 | 129 | The source code is distributed under the nonviral [MIT License](http://opensource.org/licenses/mit-license.php). It's the simplest most permissive license available. 130 | 131 | ## Version History 132 | 133 | * **v1.0:** Mar 2 2012 134 | 135 | * [NEW] iOS Support. ([Anton Serebryakov](https://github.com/rentzsch/jrswizzle/commit/60ccb350a3577e55d00d3fdfee8b3c0390b8e852])) 136 | 137 | * [NEW] Class method swizzling. ([outis](https://github.com/rentzsch/jrswizzle/pull/1)) 138 | 139 | * **v1.0d1:** May 31 2009 140 | 141 | * [FIX] Soothe valgrind by nulling out `hoisted_method_list->obsolete`, which it apparently reads. ([Daniel Jalkut](http://github.com/rentzsch/jrswizzle/commit/2f677d063202b443ca7a1c46e8b67d67ea6fc88e)) 142 | 143 | * [FIX] Xcode 3.2 apparently now needs `ARCHS` set explicitly for 10.3 targets. ([rentzsch](http://github.com/rentzsch/jrswizzle/commit/4478faa40e4fdb322201da20f24d3996193ea48b)) 144 | 145 | * **v1.0d0:** Apr 09 2009 146 | 147 | * Moved to github. 148 | 149 | * **v1.0d0:** Dec 28 2007 150 | 151 | * Under development. -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/WTSafeGuard.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WTSafeGuard", 3 | "version": "1.3.0", 4 | "summary": "A short description of WTSafeGuard.", 5 | "description": "防止crash", 6 | "homepage": "https://github.com/hongruqi/SafeGuard", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "lbrsilva-allin": "hongru.qi@quvideo.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/hongruqi/SafeGuard.git", 16 | "tag": "1.3.0" 17 | }, 18 | "platforms": { 19 | "ios": "8.0" 20 | }, 21 | "source_files": [ 22 | "WTSafeGuard/Classes/**/*", 23 | "WTSafeGuard/Classes/KVO/*", 24 | "WTSafeGuard/Classes/UI/*", 25 | "WTSafeGuard/Classes/Container/*", 26 | "WTSafeGuard/Classes/Target/*", 27 | "WTSafeGuard/Classes/Timer/*" 28 | ], 29 | "dependencies": { 30 | "JRSwizzle": [ 31 | 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - JRSwizzle (1.0) 3 | - WTSafeGuard (1.3.0): 4 | - JRSwizzle 5 | 6 | DEPENDENCIES: 7 | - WTSafeGuard (from `../`) 8 | 9 | EXTERNAL SOURCES: 10 | WTSafeGuard: 11 | :path: ../ 12 | 13 | SPEC CHECKSUMS: 14 | JRSwizzle: dd5ead5d913a0f29e7f558200165849f006bb1e3 15 | WTSafeGuard: b2f60762704cd279abaab22a6caef5c3f131265c 16 | 17 | PODFILE CHECKSUM: f38df40f5d74089817f4f9d44c4669ee3c39834a 18 | 19 | COCOAPODS: 1.4.0.beta.1 20 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JRSwizzle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JRSwizzle/JRSwizzle-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_JRSwizzle : NSObject 3 | @end 4 | @implementation PodsDummy_JRSwizzle 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JRSwizzle/JRSwizzle-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JRSwizzle/JRSwizzle-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "JRSwizzle.h" 14 | 15 | FOUNDATION_EXPORT double JRSwizzleVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char JRSwizzleVersionString[]; 17 | 18 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JRSwizzle/JRSwizzle.modulemap: -------------------------------------------------------------------------------- 1 | framework module JRSwizzle { 2 | umbrella header "JRSwizzle-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JRSwizzle/JRSwizzle.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_LDFLAGS = -framework "Foundation" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/JRSwizzle 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_WTSafeGuard_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_WTSafeGuard_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 12 | 13 | install_framework() 14 | { 15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 16 | local source="${BUILT_PRODUCTS_DIR}/$1" 17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 19 | elif [ -r "$1" ]; then 20 | local source="$1" 21 | fi 22 | 23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | 25 | if [ -L "${source}" ]; then 26 | echo "Symlinked..." 27 | source="$(readlink "${source}")" 28 | fi 29 | 30 | # Use filter instead of exclude so missing patterns don't throw errors. 31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 33 | 34 | local basename 35 | basename="$(basename -s .framework "$1")" 36 | binary="${destination}/${basename}.framework/${basename}" 37 | if ! [ -r "$binary" ]; then 38 | binary="${destination}/${basename}" 39 | fi 40 | 41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 43 | strip_invalid_archs "$binary" 44 | fi 45 | 46 | # Resign the code if required by the build settings to avoid unstable apps 47 | code_sign_if_enabled "${destination}/$(basename "$1")" 48 | 49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 51 | local swift_runtime_libs 52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 53 | for lib in $swift_runtime_libs; do 54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 56 | code_sign_if_enabled "${destination}/${lib}" 57 | done 58 | fi 59 | } 60 | 61 | # Copies the dSYM of a vendored framework 62 | install_dsym() { 63 | local source="$1" 64 | if [ -r "$source" ]; then 65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" 66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" 67 | fi 68 | } 69 | 70 | # Signs a framework with the provided identity 71 | code_sign_if_enabled() { 72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 73 | # Use the current code_sign_identitiy 74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 76 | 77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 78 | code_sign_cmd="$code_sign_cmd &" 79 | fi 80 | echo "$code_sign_cmd" 81 | eval "$code_sign_cmd" 82 | fi 83 | } 84 | 85 | # Strip invalid architectures 86 | strip_invalid_archs() { 87 | binary="$1" 88 | # Get architectures for current file 89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 90 | stripped="" 91 | for arch in $archs; do 92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 93 | # Strip non-valid architectures in-place 94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 95 | stripped="$stripped $arch" 96 | fi 97 | done 98 | if [[ "$stripped" ]]; then 99 | echo "Stripped $binary of architectures:$stripped" 100 | fi 101 | } 102 | 103 | 104 | if [[ "$CONFIGURATION" == "Debug" ]]; then 105 | install_framework "${BUILT_PRODUCTS_DIR}/JRSwizzle/JRSwizzle.framework" 106 | install_framework "${BUILT_PRODUCTS_DIR}/WTSafeGuard/WTSafeGuard.framework" 107 | fi 108 | if [[ "$CONFIGURATION" == "Release" ]]; then 109 | install_framework "${BUILT_PRODUCTS_DIR}/JRSwizzle/JRSwizzle.framework" 110 | install_framework "${BUILT_PRODUCTS_DIR}/WTSafeGuard/WTSafeGuard.framework" 111 | fi 112 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 113 | wait 114 | fi 115 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_WTSafeGuard_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_WTSafeGuard_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle" "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle/JRSwizzle.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard/WTSafeGuard.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "JRSwizzle" -framework "WTSafeGuard" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_WTSafeGuard_Example { 2 | umbrella header "Pods-WTSafeGuard_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle" "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle/JRSwizzle.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard/WTSafeGuard.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "JRSwizzle" -framework "WTSafeGuard" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_WTSafeGuard_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_WTSafeGuard_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 12 | 13 | install_framework() 14 | { 15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 16 | local source="${BUILT_PRODUCTS_DIR}/$1" 17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 19 | elif [ -r "$1" ]; then 20 | local source="$1" 21 | fi 22 | 23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | 25 | if [ -L "${source}" ]; then 26 | echo "Symlinked..." 27 | source="$(readlink "${source}")" 28 | fi 29 | 30 | # Use filter instead of exclude so missing patterns don't throw errors. 31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 33 | 34 | local basename 35 | basename="$(basename -s .framework "$1")" 36 | binary="${destination}/${basename}.framework/${basename}" 37 | if ! [ -r "$binary" ]; then 38 | binary="${destination}/${basename}" 39 | fi 40 | 41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 43 | strip_invalid_archs "$binary" 44 | fi 45 | 46 | # Resign the code if required by the build settings to avoid unstable apps 47 | code_sign_if_enabled "${destination}/$(basename "$1")" 48 | 49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 51 | local swift_runtime_libs 52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 53 | for lib in $swift_runtime_libs; do 54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 56 | code_sign_if_enabled "${destination}/${lib}" 57 | done 58 | fi 59 | } 60 | 61 | # Copies the dSYM of a vendored framework 62 | install_dsym() { 63 | local source="$1" 64 | if [ -r "$source" ]; then 65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" 66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" 67 | fi 68 | } 69 | 70 | # Signs a framework with the provided identity 71 | code_sign_if_enabled() { 72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 73 | # Use the current code_sign_identitiy 74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 76 | 77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 78 | code_sign_cmd="$code_sign_cmd &" 79 | fi 80 | echo "$code_sign_cmd" 81 | eval "$code_sign_cmd" 82 | fi 83 | } 84 | 85 | # Strip invalid architectures 86 | strip_invalid_archs() { 87 | binary="$1" 88 | # Get architectures for current file 89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 90 | stripped="" 91 | for arch in $archs; do 92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 93 | # Strip non-valid architectures in-place 94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 95 | stripped="$stripped $arch" 96 | fi 97 | done 98 | if [[ "$stripped" ]]; then 99 | echo "Stripped $binary of architectures:$stripped" 100 | fi 101 | } 102 | 103 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 104 | wait 105 | fi 106 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_WTSafeGuard_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_WTSafeGuard_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle" "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle/JRSwizzle.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard/WTSafeGuard.framework/Headers" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_WTSafeGuard_Tests { 2 | umbrella header "Pods-WTSafeGuard_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle" "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle/JRSwizzle.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard/WTSafeGuard.framework/Headers" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WTSafeGuard/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.3.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WTSafeGuard/WTSafeGuard-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_WTSafeGuard : NSObject 3 | @end 4 | @implementation PodsDummy_WTSafeGuard 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WTSafeGuard/WTSafeGuard-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WTSafeGuard/WTSafeGuard-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "NSAttributedString+WTSafe.h" 14 | #import "NSDictionary+WTSafe.h" 15 | #import "NSFileManager+WTSafe.h" 16 | #import "NSIndexPath+WTSafe.h" 17 | #import "NSJSONSerialization+WTSafe.h" 18 | #import "NSMutableDictionary+WTSafe.h" 19 | #import "NSMutableSet+WTSafe.h" 20 | #import "NSMutableString+WTSafe.h" 21 | #import "NSSet+WTSafe.h" 22 | #import "NSString+WTSafe.h" 23 | #import "NSURL+WTSafe.h" 24 | #import "WTKVOMapManager.h" 25 | #import "WTKVOResource.h" 26 | #import "NSObject+WTSafe.h" 27 | #import "WTFakeForwardTargetObject.h" 28 | #import "NSTimer+WTSafe.h" 29 | #import "WTWeakTimerTarget.h" 30 | #import "UIPasteboard+WTSafe.h" 31 | #import "UIView+WTSafe.h" 32 | #import "WTSafeGuard.h" 33 | 34 | FOUNDATION_EXPORT double WTSafeGuardVersionNumber; 35 | FOUNDATION_EXPORT const unsigned char WTSafeGuardVersionString[]; 36 | 37 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WTSafeGuard/WTSafeGuard.modulemap: -------------------------------------------------------------------------------- 1 | framework module WTSafeGuard { 2 | umbrella header "WTSafeGuard-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WTSafeGuard/WTSafeGuard.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WTSafeGuard 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JRSwizzle" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTSafeGuardTests.m 3 | // WTSafeGuardTests 4 | // 5 | // Created by lbrsilva-allin on 07/11/2017. 6 | // Copyright (c) 2017 lbrsilva-allin. All rights reserved. 7 | // 8 | 9 | @import XCTest; 10 | 11 | @interface Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Tests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/WTSafeGuard.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 11 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 12 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 13 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 14 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 15 | 6003F59E195388D20070C39A /* WTAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* WTAppDelegate.m */; }; 16 | 6003F5A7195388D20070C39A /* WTViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* WTViewController.m */; }; 17 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 18 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 19 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 20 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 21 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 22 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 23 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; 24 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; }; 25 | C151A6B2610256115A34C3B5 /* Pods_WTSafeGuard_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 579056D8F420226D5D86956D /* Pods_WTSafeGuard_Example.framework */; }; 26 | CB61350157311CB544CC2240 /* Pods_WTSafeGuard_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4FF251FA1D34EE7F48992FC /* Pods_WTSafeGuard_Tests.framework */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 6003F582195388D10070C39A /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 6003F589195388D20070C39A; 35 | remoteInfo = WTSafeGuard; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 030185EA5146DDFD46A8437A /* Pods-WTSafeGuard_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WTSafeGuard_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example.release.xcconfig"; sourceTree = ""; }; 41 | 1C754D5CF019D2654D1B6309 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 42 | 1F490A36CC5B8072AE9BD97F /* Pods-WTSafeGuard_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WTSafeGuard_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests.release.xcconfig"; sourceTree = ""; }; 43 | 3BF4D35587D6EA2A888972D7 /* WTSafeGuard.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = WTSafeGuard.podspec; path = ../WTSafeGuard.podspec; sourceTree = ""; }; 44 | 579056D8F420226D5D86956D /* Pods_WTSafeGuard_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WTSafeGuard_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 6003F58A195388D20070C39A /* WTSafeGuard_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WTSafeGuard_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 47 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 48 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 49 | 6003F595195388D20070C39A /* WTSafeGuard-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "WTSafeGuard-Info.plist"; sourceTree = ""; }; 50 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 51 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | 6003F59B195388D20070C39A /* WTSafeGuard-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WTSafeGuard-Prefix.pch"; sourceTree = ""; }; 53 | 6003F59C195388D20070C39A /* WTAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WTAppDelegate.h; sourceTree = ""; }; 54 | 6003F59D195388D20070C39A /* WTAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WTAppDelegate.m; sourceTree = ""; }; 55 | 6003F5A5195388D20070C39A /* WTViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WTViewController.h; sourceTree = ""; }; 56 | 6003F5A6195388D20070C39A /* WTViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WTViewController.m; sourceTree = ""; }; 57 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 58 | 6003F5AE195388D20070C39A /* WTSafeGuard_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WTSafeGuard_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 60 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 61 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 62 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 63 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 64 | 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 65 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 66 | 8FC73BADD260407735D9435C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 67 | 9717A6EC96721A160802E892 /* Pods-WTSafeGuard_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WTSafeGuard_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example.debug.xcconfig"; sourceTree = ""; }; 68 | A4FF251FA1D34EE7F48992FC /* Pods_WTSafeGuard_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WTSafeGuard_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | DB8C097249951956B3C3656E /* Pods-WTSafeGuard_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WTSafeGuard_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests.debug.xcconfig"; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 6003F587195388D20070C39A /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 78 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 79 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, 80 | C151A6B2610256115A34C3B5 /* Pods_WTSafeGuard_Example.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | 6003F5AB195388D20070C39A /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 89 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 90 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 91 | CB61350157311CB544CC2240 /* Pods_WTSafeGuard_Tests.framework in Frameworks */, 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | /* End PBXFrameworksBuildPhase section */ 96 | 97 | /* Begin PBXGroup section */ 98 | 6003F581195388D10070C39A = { 99 | isa = PBXGroup; 100 | children = ( 101 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 102 | 6003F593195388D20070C39A /* Example for WTSafeGuard */, 103 | 6003F5B5195388D20070C39A /* Tests */, 104 | 6003F58C195388D20070C39A /* Frameworks */, 105 | 6003F58B195388D20070C39A /* Products */, 106 | 6CE9F9A09E439F80C82604A6 /* Pods */, 107 | ); 108 | sourceTree = ""; 109 | }; 110 | 6003F58B195388D20070C39A /* Products */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 6003F58A195388D20070C39A /* WTSafeGuard_Example.app */, 114 | 6003F5AE195388D20070C39A /* WTSafeGuard_Tests.xctest */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 6003F58C195388D20070C39A /* Frameworks */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 6003F58D195388D20070C39A /* Foundation.framework */, 123 | 6003F58F195388D20070C39A /* CoreGraphics.framework */, 124 | 6003F591195388D20070C39A /* UIKit.framework */, 125 | 6003F5AF195388D20070C39A /* XCTest.framework */, 126 | 579056D8F420226D5D86956D /* Pods_WTSafeGuard_Example.framework */, 127 | A4FF251FA1D34EE7F48992FC /* Pods_WTSafeGuard_Tests.framework */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | 6003F593195388D20070C39A /* Example for WTSafeGuard */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 6003F59C195388D20070C39A /* WTAppDelegate.h */, 136 | 6003F59D195388D20070C39A /* WTAppDelegate.m */, 137 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */, 138 | 6003F5A5195388D20070C39A /* WTViewController.h */, 139 | 6003F5A6195388D20070C39A /* WTViewController.m */, 140 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */, 141 | 6003F5A8195388D20070C39A /* Images.xcassets */, 142 | 6003F594195388D20070C39A /* Supporting Files */, 143 | ); 144 | name = "Example for WTSafeGuard"; 145 | path = WTSafeGuard; 146 | sourceTree = ""; 147 | }; 148 | 6003F594195388D20070C39A /* Supporting Files */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 6003F595195388D20070C39A /* WTSafeGuard-Info.plist */, 152 | 6003F596195388D20070C39A /* InfoPlist.strings */, 153 | 6003F599195388D20070C39A /* main.m */, 154 | 6003F59B195388D20070C39A /* WTSafeGuard-Prefix.pch */, 155 | ); 156 | name = "Supporting Files"; 157 | sourceTree = ""; 158 | }; 159 | 6003F5B5195388D20070C39A /* Tests */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 6003F5BB195388D20070C39A /* Tests.m */, 163 | 6003F5B6195388D20070C39A /* Supporting Files */, 164 | ); 165 | path = Tests; 166 | sourceTree = ""; 167 | }; 168 | 6003F5B6195388D20070C39A /* Supporting Files */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 6003F5B7195388D20070C39A /* Tests-Info.plist */, 172 | 6003F5B8195388D20070C39A /* InfoPlist.strings */, 173 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, 174 | ); 175 | name = "Supporting Files"; 176 | sourceTree = ""; 177 | }; 178 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | 3BF4D35587D6EA2A888972D7 /* WTSafeGuard.podspec */, 182 | 1C754D5CF019D2654D1B6309 /* README.md */, 183 | 8FC73BADD260407735D9435C /* LICENSE */, 184 | ); 185 | name = "Podspec Metadata"; 186 | sourceTree = ""; 187 | }; 188 | 6CE9F9A09E439F80C82604A6 /* Pods */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | 9717A6EC96721A160802E892 /* Pods-WTSafeGuard_Example.debug.xcconfig */, 192 | 030185EA5146DDFD46A8437A /* Pods-WTSafeGuard_Example.release.xcconfig */, 193 | DB8C097249951956B3C3656E /* Pods-WTSafeGuard_Tests.debug.xcconfig */, 194 | 1F490A36CC5B8072AE9BD97F /* Pods-WTSafeGuard_Tests.release.xcconfig */, 195 | ); 196 | name = Pods; 197 | sourceTree = ""; 198 | }; 199 | /* End PBXGroup section */ 200 | 201 | /* Begin PBXNativeTarget section */ 202 | 6003F589195388D20070C39A /* WTSafeGuard_Example */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "WTSafeGuard_Example" */; 205 | buildPhases = ( 206 | 758F9AFACD2C4B592B70EA8F /* [CP] Check Pods Manifest.lock */, 207 | 6003F586195388D20070C39A /* Sources */, 208 | 6003F587195388D20070C39A /* Frameworks */, 209 | 6003F588195388D20070C39A /* Resources */, 210 | A8CE4351E548C6653D1417D7 /* [CP] Embed Pods Frameworks */, 211 | ADC18C9A82AE13CFDBA3ED69 /* [CP] Copy Pods Resources */, 212 | ); 213 | buildRules = ( 214 | ); 215 | dependencies = ( 216 | ); 217 | name = WTSafeGuard_Example; 218 | productName = WTSafeGuard; 219 | productReference = 6003F58A195388D20070C39A /* WTSafeGuard_Example.app */; 220 | productType = "com.apple.product-type.application"; 221 | }; 222 | 6003F5AD195388D20070C39A /* WTSafeGuard_Tests */ = { 223 | isa = PBXNativeTarget; 224 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "WTSafeGuard_Tests" */; 225 | buildPhases = ( 226 | 260E457562CD5DD81ED577C5 /* [CP] Check Pods Manifest.lock */, 227 | 6003F5AA195388D20070C39A /* Sources */, 228 | 6003F5AB195388D20070C39A /* Frameworks */, 229 | 6003F5AC195388D20070C39A /* Resources */, 230 | 66A50245170A1C10A856D8AC /* [CP] Embed Pods Frameworks */, 231 | C2589F706584C2E2FCCF1715 /* [CP] Copy Pods Resources */, 232 | ); 233 | buildRules = ( 234 | ); 235 | dependencies = ( 236 | 6003F5B4195388D20070C39A /* PBXTargetDependency */, 237 | ); 238 | name = WTSafeGuard_Tests; 239 | productName = WTSafeGuardTests; 240 | productReference = 6003F5AE195388D20070C39A /* WTSafeGuard_Tests.xctest */; 241 | productType = "com.apple.product-type.bundle.unit-test"; 242 | }; 243 | /* End PBXNativeTarget section */ 244 | 245 | /* Begin PBXProject section */ 246 | 6003F582195388D10070C39A /* Project object */ = { 247 | isa = PBXProject; 248 | attributes = { 249 | CLASSPREFIX = WT; 250 | LastUpgradeCheck = 0720; 251 | ORGANIZATIONNAME = "lbrsilva-allin"; 252 | TargetAttributes = { 253 | 6003F5AD195388D20070C39A = { 254 | TestTargetID = 6003F589195388D20070C39A; 255 | }; 256 | }; 257 | }; 258 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "WTSafeGuard" */; 259 | compatibilityVersion = "Xcode 3.2"; 260 | developmentRegion = English; 261 | hasScannedForEncodings = 0; 262 | knownRegions = ( 263 | en, 264 | Base, 265 | ); 266 | mainGroup = 6003F581195388D10070C39A; 267 | productRefGroup = 6003F58B195388D20070C39A /* Products */; 268 | projectDirPath = ""; 269 | projectRoot = ""; 270 | targets = ( 271 | 6003F589195388D20070C39A /* WTSafeGuard_Example */, 272 | 6003F5AD195388D20070C39A /* WTSafeGuard_Tests */, 273 | ); 274 | }; 275 | /* End PBXProject section */ 276 | 277 | /* Begin PBXResourcesBuildPhase section */ 278 | 6003F588195388D20070C39A /* Resources */ = { 279 | isa = PBXResourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */, 283 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */, 284 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 285 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | 6003F5AC195388D20070C39A /* Resources */ = { 290 | isa = PBXResourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, 294 | ); 295 | runOnlyForDeploymentPostprocessing = 0; 296 | }; 297 | /* End PBXResourcesBuildPhase section */ 298 | 299 | /* Begin PBXShellScriptBuildPhase section */ 300 | 260E457562CD5DD81ED577C5 /* [CP] Check Pods Manifest.lock */ = { 301 | isa = PBXShellScriptBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | ); 305 | inputPaths = ( 306 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 307 | "${PODS_ROOT}/Manifest.lock", 308 | ); 309 | name = "[CP] Check Pods Manifest.lock"; 310 | outputPaths = ( 311 | "$(DERIVED_FILE_DIR)/Pods-WTSafeGuard_Tests-checkManifestLockResult.txt", 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | shellPath = /bin/sh; 315 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 316 | showEnvVarsInLog = 0; 317 | }; 318 | 66A50245170A1C10A856D8AC /* [CP] Embed Pods Frameworks */ = { 319 | isa = PBXShellScriptBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | ); 323 | inputPaths = ( 324 | ); 325 | name = "[CP] Embed Pods Frameworks"; 326 | outputPaths = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-frameworks.sh\"\n"; 331 | showEnvVarsInLog = 0; 332 | }; 333 | 758F9AFACD2C4B592B70EA8F /* [CP] Check Pods Manifest.lock */ = { 334 | isa = PBXShellScriptBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | inputPaths = ( 339 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 340 | "${PODS_ROOT}/Manifest.lock", 341 | ); 342 | name = "[CP] Check Pods Manifest.lock"; 343 | outputPaths = ( 344 | "$(DERIVED_FILE_DIR)/Pods-WTSafeGuard_Example-checkManifestLockResult.txt", 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | shellPath = /bin/sh; 348 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 349 | showEnvVarsInLog = 0; 350 | }; 351 | A8CE4351E548C6653D1417D7 /* [CP] Embed Pods Frameworks */ = { 352 | isa = PBXShellScriptBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | ); 356 | inputPaths = ( 357 | "${SRCROOT}/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-frameworks.sh", 358 | "${BUILT_PRODUCTS_DIR}/JRSwizzle/JRSwizzle.framework", 359 | "${BUILT_PRODUCTS_DIR}/WTSafeGuard/WTSafeGuard.framework", 360 | ); 361 | name = "[CP] Embed Pods Frameworks"; 362 | outputPaths = ( 363 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JRSwizzle.framework", 364 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WTSafeGuard.framework", 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | shellPath = /bin/sh; 368 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-frameworks.sh\"\n"; 369 | showEnvVarsInLog = 0; 370 | }; 371 | ADC18C9A82AE13CFDBA3ED69 /* [CP] Copy Pods Resources */ = { 372 | isa = PBXShellScriptBuildPhase; 373 | buildActionMask = 2147483647; 374 | files = ( 375 | ); 376 | inputPaths = ( 377 | ); 378 | name = "[CP] Copy Pods Resources"; 379 | outputPaths = ( 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | shellPath = /bin/sh; 383 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WTSafeGuard_Example/Pods-WTSafeGuard_Example-resources.sh\"\n"; 384 | showEnvVarsInLog = 0; 385 | }; 386 | C2589F706584C2E2FCCF1715 /* [CP] Copy Pods Resources */ = { 387 | isa = PBXShellScriptBuildPhase; 388 | buildActionMask = 2147483647; 389 | files = ( 390 | ); 391 | inputPaths = ( 392 | ); 393 | name = "[CP] Copy Pods Resources"; 394 | outputPaths = ( 395 | ); 396 | runOnlyForDeploymentPostprocessing = 0; 397 | shellPath = /bin/sh; 398 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WTSafeGuard_Tests/Pods-WTSafeGuard_Tests-resources.sh\"\n"; 399 | showEnvVarsInLog = 0; 400 | }; 401 | /* End PBXShellScriptBuildPhase section */ 402 | 403 | /* Begin PBXSourcesBuildPhase section */ 404 | 6003F586195388D20070C39A /* Sources */ = { 405 | isa = PBXSourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | 6003F59E195388D20070C39A /* WTAppDelegate.m in Sources */, 409 | 6003F5A7195388D20070C39A /* WTViewController.m in Sources */, 410 | 6003F59A195388D20070C39A /* main.m in Sources */, 411 | ); 412 | runOnlyForDeploymentPostprocessing = 0; 413 | }; 414 | 6003F5AA195388D20070C39A /* Sources */ = { 415 | isa = PBXSourcesBuildPhase; 416 | buildActionMask = 2147483647; 417 | files = ( 418 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 419 | ); 420 | runOnlyForDeploymentPostprocessing = 0; 421 | }; 422 | /* End PBXSourcesBuildPhase section */ 423 | 424 | /* Begin PBXTargetDependency section */ 425 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 426 | isa = PBXTargetDependency; 427 | target = 6003F589195388D20070C39A /* WTSafeGuard_Example */; 428 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 429 | }; 430 | /* End PBXTargetDependency section */ 431 | 432 | /* Begin PBXVariantGroup section */ 433 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 434 | isa = PBXVariantGroup; 435 | children = ( 436 | 6003F597195388D20070C39A /* en */, 437 | ); 438 | name = InfoPlist.strings; 439 | sourceTree = ""; 440 | }; 441 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 442 | isa = PBXVariantGroup; 443 | children = ( 444 | 6003F5B9195388D20070C39A /* en */, 445 | ); 446 | name = InfoPlist.strings; 447 | sourceTree = ""; 448 | }; 449 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = { 450 | isa = PBXVariantGroup; 451 | children = ( 452 | 71719F9E1E33DC2100824A3D /* Base */, 453 | ); 454 | name = LaunchScreen.storyboard; 455 | sourceTree = ""; 456 | }; 457 | /* End PBXVariantGroup section */ 458 | 459 | /* Begin XCBuildConfiguration section */ 460 | 6003F5BD195388D20070C39A /* Debug */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | ALWAYS_SEARCH_USER_PATHS = NO; 464 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 465 | CLANG_CXX_LIBRARY = "libc++"; 466 | CLANG_ENABLE_MODULES = YES; 467 | CLANG_ENABLE_OBJC_ARC = YES; 468 | CLANG_WARN_BOOL_CONVERSION = YES; 469 | CLANG_WARN_CONSTANT_CONVERSION = YES; 470 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 471 | CLANG_WARN_EMPTY_BODY = YES; 472 | CLANG_WARN_ENUM_CONVERSION = YES; 473 | CLANG_WARN_INT_CONVERSION = YES; 474 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 475 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 476 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 477 | COPY_PHASE_STRIP = NO; 478 | ENABLE_TESTABILITY = YES; 479 | GCC_C_LANGUAGE_STANDARD = gnu99; 480 | GCC_DYNAMIC_NO_PIC = NO; 481 | GCC_OPTIMIZATION_LEVEL = 0; 482 | GCC_PREPROCESSOR_DEFINITIONS = ( 483 | "DEBUG=1", 484 | "$(inherited)", 485 | ); 486 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 487 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 488 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 489 | GCC_WARN_UNDECLARED_SELECTOR = YES; 490 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 491 | GCC_WARN_UNUSED_FUNCTION = YES; 492 | GCC_WARN_UNUSED_VARIABLE = YES; 493 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 494 | ONLY_ACTIVE_ARCH = YES; 495 | SDKROOT = iphoneos; 496 | TARGETED_DEVICE_FAMILY = "1,2"; 497 | }; 498 | name = Debug; 499 | }; 500 | 6003F5BE195388D20070C39A /* Release */ = { 501 | isa = XCBuildConfiguration; 502 | buildSettings = { 503 | ALWAYS_SEARCH_USER_PATHS = NO; 504 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 505 | CLANG_CXX_LIBRARY = "libc++"; 506 | CLANG_ENABLE_MODULES = YES; 507 | CLANG_ENABLE_OBJC_ARC = YES; 508 | CLANG_WARN_BOOL_CONVERSION = YES; 509 | CLANG_WARN_CONSTANT_CONVERSION = YES; 510 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 511 | CLANG_WARN_EMPTY_BODY = YES; 512 | CLANG_WARN_ENUM_CONVERSION = YES; 513 | CLANG_WARN_INT_CONVERSION = YES; 514 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 515 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 516 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 517 | COPY_PHASE_STRIP = YES; 518 | ENABLE_NS_ASSERTIONS = NO; 519 | GCC_C_LANGUAGE_STANDARD = gnu99; 520 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 521 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 522 | GCC_WARN_UNDECLARED_SELECTOR = YES; 523 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 524 | GCC_WARN_UNUSED_FUNCTION = YES; 525 | GCC_WARN_UNUSED_VARIABLE = YES; 526 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 527 | SDKROOT = iphoneos; 528 | TARGETED_DEVICE_FAMILY = "1,2"; 529 | VALIDATE_PRODUCT = YES; 530 | }; 531 | name = Release; 532 | }; 533 | 6003F5C0195388D20070C39A /* Debug */ = { 534 | isa = XCBuildConfiguration; 535 | baseConfigurationReference = 9717A6EC96721A160802E892 /* Pods-WTSafeGuard_Example.debug.xcconfig */; 536 | buildSettings = { 537 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 538 | DEVELOPMENT_TEAM = ""; 539 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 540 | GCC_PREFIX_HEADER = "WTSafeGuard/WTSafeGuard-Prefix.pch"; 541 | INFOPLIST_FILE = "WTSafeGuard/WTSafeGuard-Info.plist"; 542 | MODULE_NAME = ExampleApp; 543 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 544 | PRODUCT_NAME = "$(TARGET_NAME)"; 545 | WRAPPER_EXTENSION = app; 546 | }; 547 | name = Debug; 548 | }; 549 | 6003F5C1195388D20070C39A /* Release */ = { 550 | isa = XCBuildConfiguration; 551 | baseConfigurationReference = 030185EA5146DDFD46A8437A /* Pods-WTSafeGuard_Example.release.xcconfig */; 552 | buildSettings = { 553 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 554 | DEVELOPMENT_TEAM = ""; 555 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 556 | GCC_PREFIX_HEADER = "WTSafeGuard/WTSafeGuard-Prefix.pch"; 557 | INFOPLIST_FILE = "WTSafeGuard/WTSafeGuard-Info.plist"; 558 | MODULE_NAME = ExampleApp; 559 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 560 | PRODUCT_NAME = "$(TARGET_NAME)"; 561 | WRAPPER_EXTENSION = app; 562 | }; 563 | name = Release; 564 | }; 565 | 6003F5C3195388D20070C39A /* Debug */ = { 566 | isa = XCBuildConfiguration; 567 | baseConfigurationReference = DB8C097249951956B3C3656E /* Pods-WTSafeGuard_Tests.debug.xcconfig */; 568 | buildSettings = { 569 | BUNDLE_LOADER = "$(TEST_HOST)"; 570 | FRAMEWORK_SEARCH_PATHS = ( 571 | "$(SDKROOT)/Developer/Library/Frameworks", 572 | "$(inherited)", 573 | "$(DEVELOPER_FRAMEWORKS_DIR)", 574 | ); 575 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 576 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 577 | GCC_PREPROCESSOR_DEFINITIONS = ( 578 | "DEBUG=1", 579 | "$(inherited)", 580 | ); 581 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 582 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 583 | PRODUCT_NAME = "$(TARGET_NAME)"; 584 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WTSafeGuard_Example.app/WTSafeGuard_Example"; 585 | WRAPPER_EXTENSION = xctest; 586 | }; 587 | name = Debug; 588 | }; 589 | 6003F5C4195388D20070C39A /* Release */ = { 590 | isa = XCBuildConfiguration; 591 | baseConfigurationReference = 1F490A36CC5B8072AE9BD97F /* Pods-WTSafeGuard_Tests.release.xcconfig */; 592 | buildSettings = { 593 | BUNDLE_LOADER = "$(TEST_HOST)"; 594 | FRAMEWORK_SEARCH_PATHS = ( 595 | "$(SDKROOT)/Developer/Library/Frameworks", 596 | "$(inherited)", 597 | "$(DEVELOPER_FRAMEWORKS_DIR)", 598 | ); 599 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 600 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 601 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 602 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 603 | PRODUCT_NAME = "$(TARGET_NAME)"; 604 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WTSafeGuard_Example.app/WTSafeGuard_Example"; 605 | WRAPPER_EXTENSION = xctest; 606 | }; 607 | name = Release; 608 | }; 609 | /* End XCBuildConfiguration section */ 610 | 611 | /* Begin XCConfigurationList section */ 612 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "WTSafeGuard" */ = { 613 | isa = XCConfigurationList; 614 | buildConfigurations = ( 615 | 6003F5BD195388D20070C39A /* Debug */, 616 | 6003F5BE195388D20070C39A /* Release */, 617 | ); 618 | defaultConfigurationIsVisible = 0; 619 | defaultConfigurationName = Release; 620 | }; 621 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "WTSafeGuard_Example" */ = { 622 | isa = XCConfigurationList; 623 | buildConfigurations = ( 624 | 6003F5C0195388D20070C39A /* Debug */, 625 | 6003F5C1195388D20070C39A /* Release */, 626 | ); 627 | defaultConfigurationIsVisible = 0; 628 | defaultConfigurationName = Release; 629 | }; 630 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "WTSafeGuard_Tests" */ = { 631 | isa = XCConfigurationList; 632 | buildConfigurations = ( 633 | 6003F5C3195388D20070C39A /* Debug */, 634 | 6003F5C4195388D20070C39A /* Release */, 635 | ); 636 | defaultConfigurationIsVisible = 0; 637 | defaultConfigurationName = Release; 638 | }; 639 | /* End XCConfigurationList section */ 640 | }; 641 | rootObject = 6003F582195388D10070C39A /* Project object */; 642 | } 643 | -------------------------------------------------------------------------------- /Example/WTSafeGuard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/WTSafeGuard.xcodeproj/xcshareddata/xcschemes/WTSafeGuard-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Example/WTSafeGuard.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/WTAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTAppDelegate.h 3 | // WTSafeGuard 4 | // 5 | // Created by lbrsilva-allin on 07/11/2017. 6 | // Copyright (c) 2017 lbrsilva-allin. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface WTAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/WTAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTAppDelegate.m 3 | // WTSafeGuard 4 | // 5 | // Created by lbrsilva-allin on 07/11/2017. 6 | // Copyright (c) 2017 lbrsilva-allin. All rights reserved. 7 | // 8 | 9 | #import "WTAppDelegate.h" 10 | #import "WTSafeGuard.h" 11 | @interface WTAppDelegate() 12 | @end 13 | @implementation WTAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | // Override point for customization after application launch. 18 | [WTSafeGuard startSafeGuardWithType:WTSafeGuardType_NilTarget| WTSafeGuardType_Foundation]; 19 | [WTSafeGuard shareInstance].delegate = self; 20 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 21 | [dic setObject:nil forKey:nil]; 22 | return YES; 23 | } 24 | 25 | - (void)applicationWillResignActive:(UIApplication *)application 26 | { 27 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 28 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 29 | } 30 | 31 | - (void)applicationDidEnterBackground:(UIApplication *)application 32 | { 33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | - (void)applicationWillEnterForeground:(UIApplication *)application 38 | { 39 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | - (void)applicationDidBecomeActive:(UIApplication *)application 43 | { 44 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 45 | } 46 | 47 | - (void)applicationWillTerminate:(UIApplication *)application 48 | { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | - (void)safeGuardCrashMessage:(NSString *)className selector:(NSString *)selector stack:(NSArray *)stack 53 | { 54 | 55 | } 56 | @end 57 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/WTSafeGuard-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/WTSafeGuard-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/WTViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTViewController.h 3 | // WTSafeGuard 4 | // 5 | // Created by lbrsilva-allin on 07/11/2017. 6 | // Copyright (c) 2017 lbrsilva-allin. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface WTViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/WTViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTViewController.m 3 | // WTSafeGuard 4 | // 5 | // Created by lbrsilva-allin on 07/11/2017. 6 | // Copyright (c) 2017 lbrsilva-allin. All rights reserved. 7 | // 8 | 9 | #import "WTViewController.h" 10 | 11 | @interface WTViewController () 12 | 13 | @end 14 | 15 | @implementation WTViewController 16 | 17 | - (void)viewDidLoad 18 | { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view, typically from a nib. 21 | } 22 | 23 | - (void)didReceiveMemoryWarning 24 | { 25 | [super didReceiveMemoryWarning]; 26 | // Dispose of any resources that can be recreated. 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/WTSafeGuard/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WTSafeGuard 4 | // 5 | // Created by lbrsilva-allin on 07/11/2017. 6 | // Copyright (c) 2017 lbrsilva-allin. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "WTAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([WTAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WTSafeGuard can effectively prevent the IOS system application crash 2 | ### Features 3 | - Avoid NSTimer crash 4 | - Avoid UIKit Called on Non-Main Thread crash 5 | - Avoid KVO crash 6 | - Avoid unrecognized selector crash 7 | - Avoid Container NSArray, NSMutableArray, NSDictionary, NSMutableDictionary, NSSet, NSMutableSet crash 8 | - Avoid NSString, NSMutableString,NSAttributedString crash 9 | - Avoid NSURL, NSFileManager, NSIndexPath, NSJSONSerialization 10 | 11 | ### Requirements 12 | - IOS 8 or later , XCode 7 or later 13 | 14 | ### How To Use 15 | ```Objc 16 | #import "WTSafeGuard.h" 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | [WTSafeGuard startSafeGuard]; 20 | } 21 | ``` 22 | ### Installation 23 | - pod 'WTSafeGuard' 24 | 25 | 26 | -------------------------------------------------------------------------------- /WTSafeGuard.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint WTSafeGuard.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'WTSafeGuard' 11 | s.version = '1.3.1' 12 | s.summary = 'A short description of WTSafeGuard.' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | 防止crash 22 | DESC 23 | 24 | s.homepage = 'https://github.com/hongruqi/SafeGuard' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'lbrsilva-allin' => 'hongru.qi@quvideo.com' } 28 | s.source = { :git => 'https://github.com/hongruqi/SafeGuard.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '8.0' 32 | 33 | s.source_files = 'WTSafeGuard/Classes/**/*','WTSafeGuard/Classes/KVO/*','WTSafeGuard/Classes/UI/*', 34 | 'WTSafeGuard/Classes/Container/*','WTSafeGuard/Classes/Target/*','WTSafeGuard/Classes/Timer/*' 35 | # s.resource_bundles = { 36 | # 'WTSafeGuard' => ['WTSafeGuard/Assets/*.png'] 37 | # } 38 | 39 | # s.public_header_files = 'Pod/Classes/**/*.h' 40 | s.dependency 'JRSwizzle' 41 | end 42 | -------------------------------------------------------------------------------- /WTSafeGuard/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongruqi/SafeGuard/96f15d7123e0352429c8282c5e23bc9a086c3160/WTSafeGuard/Assets/.gitkeep -------------------------------------------------------------------------------- /WTSafeGuard/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hongruqi/SafeGuard/96f15d7123e0352429c8282c5e23bc9a086c3160/WTSafeGuard/Classes/.gitkeep -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSAttributedString+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/21. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSAttributedString (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSAttributedString+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/21. 6 | // 7 | // 8 | 9 | #import "NSAttributedString+WTSafe.h" 10 | #import 11 | #import "JRSwizzle.h" 12 | #import "WTSafeGuard.h" 13 | 14 | @implementation NSAttributedString (WTSafe) 15 | 16 | #pragma mark - Class Public Function 17 | 18 | + (void)runSafeGuard 19 | { 20 | NSError *error = nil; 21 | 22 | [objc_getClass("NSConcreteAttributedString") jr_swizzleMethod:@selector(attributedSubstringFromRange:) withMethod:@selector(WT_safeAttributedSubstringFromRange:) error:&error]; 23 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 24 | 25 | [objc_getClass("NSConcreteMutableAttributedString") jr_swizzleMethod:@selector(attributedSubstringFromRange:) withMethod:@selector(WT_safeAttributedSubstringFromRange:) error:&error]; 26 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 27 | } 28 | 29 | #pragma mark - Object Private Function 30 | 31 | - (NSAttributedString *)WT_safeAttributedSubstringFromRange:(NSRange)range 32 | { 33 | if (range.location > self.length || range.location + range.length > self.length) { 34 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 35 | return nil; 36 | } 37 | 38 | return [self WT_safeAttributedSubstringFromRange:range]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSDictionary+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/21. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSDictionary+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/21. 6 | // 7 | // 8 | 9 | #import "NSDictionary+WTSafe.h" 10 | #import "JRSwizzle.h" 11 | #import 12 | #import "WTSafeGuard.h" 13 | 14 | @implementation NSDictionary (WTSafe) 15 | 16 | + (void)runSafeGuard 17 | { 18 | NSError *error = nil; 19 | [NSDictionary jr_swizzleClassMethod:@selector(sharedKeySetForKeys:) withClassMethod:@selector(WT_safeSharedKeySetForKeys:) error:&error]; 20 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 21 | 22 | [NSDictionary jr_swizzleMethod:@selector(initWithObjects:forKeys:) withMethod:@selector(WT_safeInitWithObjects:forKeys:) error:&error]; 23 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 24 | 25 | [objc_getClass("__NSPlaceholderDictionary") jr_swizzleMethod:@selector(initWithObjects:forKeys:count:) withMethod:@selector(WT_safeInitWithObjects:forKeys:count:) error:&error]; 26 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 27 | } 28 | 29 | #pragma mark - Class Private Function 30 | 31 | + (id)WT_safeSharedKeySetForKeys:(NSArray *)keys 32 | { 33 | if (!keys || ![keys isKindOfClass:[NSArray class]]) { 34 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 35 | return nil; 36 | } 37 | 38 | return [NSDictionary WT_safeSharedKeySetForKeys:keys]; 39 | } 40 | 41 | - (instancetype)WT_safeInitWithObjects:(NSArray *)objects forKeys:(NSArray *)keys 42 | { 43 | if(![objects isKindOfClass:[NSArray class]] || 44 | ![keys isKindOfClass:[NSArray class]] || 45 | objects.count != keys.count) { 46 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 47 | return nil; 48 | } 49 | 50 | return [self WT_safeInitWithObjects:objects forKeys:keys]; 51 | } 52 | 53 | - (instancetype)WT_safeInitWithObjects:(const id [])objects 54 | forKeys:(const id [])keys 55 | count:(NSUInteger)cnt 56 | { 57 | for (int i = 0; i < cnt; ++i) { 58 | if(!keys[i] || !objects[i]) { 59 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 60 | return nil; 61 | } 62 | } 63 | 64 | return [self WT_safeInitWithObjects:objects forKeys:keys count:cnt]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSFileManager+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSFileManager (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSFileManager+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "NSFileManager+WTSafe.h" 10 | #import "WTSafeGuard.h" 11 | #import 12 | #import "JRSwizzle.h" 13 | 14 | @implementation NSFileManager (WTSafe) 15 | #pragma mark - Class Public Function 16 | 17 | + (void)runSafeGuard 18 | { 19 | NSError *error = nil; 20 | [NSFileManager jr_swizzleMethod:@selector(enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:) withMethod:@selector(WT_safeEnumeratorAtURL:includingPropertiesForKeys:options:errorHandler:) error:&error]; 21 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 22 | 23 | } 24 | 25 | #pragma mark - Object Private Function 26 | 27 | - (NSDirectoryEnumerator *)WT_safeEnumeratorAtURL:(NSURL *)url includingPropertiesForKeys:(NSArray *)keys options:(NSDirectoryEnumerationOptions)mask errorHandler:(BOOL (^)(NSURL *, NSError *))handler 28 | { 29 | if(!url) { 30 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 31 | return nil; 32 | } 33 | 34 | return [self WT_safeEnumeratorAtURL:url includingPropertiesForKeys:keys options:mask errorHandler:handler]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSIndexPath+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSIndexPath+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/21. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSIndexPath (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSIndexPath+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSIndexPath+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/21. 6 | // 7 | // 8 | 9 | #import "NSIndexPath+WTSafe.h" 10 | #import "JRSwizzle.h" 11 | #import 12 | #import "WTSafeGuard.h" 13 | 14 | @implementation NSIndexPath (WTSafe) 15 | 16 | + (void)runSafeGuard 17 | { 18 | NSError *error = nil; 19 | 20 | [NSIndexPath jr_swizzleMethod:@selector(getIndexes:range:) withMethod:@selector(WT_safeGetIndexes:range:) error:&error]; 21 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 22 | } 23 | 24 | - (void)WT_safeGetIndexes:(NSUInteger *)indexes range:(NSRange)positionRange 25 | { 26 | if (positionRange.location + positionRange.length > self.length) { 27 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 28 | return; 29 | } 30 | 31 | return [self WT_safeGetIndexes:indexes range:positionRange]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSJSONSerialization+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSJSONSerialization+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSJSONSerialization (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSJSONSerialization+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSJSONSerialization+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "NSJSONSerialization+WTSafe.h" 10 | #import 11 | #import "WTSafeGuard.h" 12 | #import "JRSwizzle.h" 13 | 14 | @implementation NSJSONSerialization (WTSafe) 15 | #pragma mark - Class Public Function 16 | 17 | + (void)runSafeGuard 18 | { 19 | NSError *error = nil; 20 | [NSJSONSerialization jr_swizzleClassMethod:@selector(dataWithJSONObject:options:error:) withClassMethod:@selector(WT_safeDataWithJSONObject:options:error:) error:&error]; 21 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 22 | } 23 | 24 | #pragma mark - Class Private Function 25 | 26 | + (NSData *)WT_safeDataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error 27 | { 28 | if (!obj) { 29 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 30 | return nil; 31 | } 32 | 33 | return [self WT_safeDataWithJSONObject:obj options:opt error:error]; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSMutableDictionary+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+WTSafe.h 3 | // WTSafetyGuard 4 | // 5 | // Created by hongru qi on 2017/6/10. 6 | // 7 | 8 | #import 9 | 10 | @interface NSMutableDictionary (WTSafe) 11 | 12 | + (void)runSafeGuard; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSMutableDictionary+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+WTSafe.m 3 | // WTSafetyGuard 4 | // 5 | // Created by hongru qi on 2017/6/10. 6 | // 7 | 8 | #import "NSMutableDictionary+WTSafe.h" 9 | #import 10 | #import "WTSafeGuard.h" 11 | #import "JRSwizzle.h" 12 | 13 | @implementation NSMutableDictionary (WTSafe) 14 | 15 | + (void)runSafeGuard 16 | { 17 | NSError *error = nil; 18 | 19 | [NSMutableDictionary jr_swizzleClassMethod:@selector(dictionaryWithSharedKeySet:) withClassMethod:@selector(WT_safeDictionaryWithSharedKeySet:) error:&error]; 20 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 21 | 22 | [objc_getClass("__NSDictionaryM") jr_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(WT_safeSetObject:forKey:) error:&error]; 23 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 24 | 25 | [objc_getClass("__NSCFDictionary") jr_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(WT_safeSetObject:forKey:) error:&error]; 26 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 27 | 28 | [objc_getClass("__NSDictionaryM") jr_swizzleMethod:@selector(removeObjectForKey:) withMethod:@selector(WT_safeRemoveObjectForKey:) error:&error]; 29 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 30 | [objc_getClass("__NSDictionaryM") jr_swizzleMethod:@selector(setValue:forKey:) withMethod:@selector(WT_safeSetValue:forKey:) error:&error]; 31 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 32 | } 33 | 34 | #pragma mark - Class Private Function 35 | 36 | + (NSMutableDictionary *)WT_safeDictionaryWithSharedKeySet:(id)keyset 37 | { 38 | if (!keyset) { 39 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 40 | return nil; 41 | } 42 | 43 | return [NSMutableDictionary WT_safeDictionaryWithSharedKeySet:keyset]; 44 | } 45 | 46 | #pragma mark - Object Private Function 47 | 48 | - (void)WT_safeSetObject:(id)anObject forKey:(id)aKey 49 | { 50 | if(!anObject || !aKey) { 51 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 52 | return; 53 | } 54 | 55 | [self WT_safeSetObject:anObject forKey:aKey]; 56 | } 57 | 58 | - (void)WT_safeRemoveObjectForKey:(id)aKey 59 | { 60 | if(!aKey) { 61 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 62 | return; 63 | } 64 | 65 | [self WT_safeRemoveObjectForKey:aKey]; 66 | } 67 | 68 | - (void)WT_safeSetValue:(id)anObject forKey:(id)aKey 69 | { 70 | if(!aKey) { 71 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 72 | return; 73 | } 74 | 75 | [self WT_safeSetValue:anObject forKey:aKey]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSMutableSet+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableSet+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableSet (WTSafe) 12 | 13 | + (void)runSafeGuard; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSMutableSet+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableSet+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "NSMutableSet+WTSafe.h" 10 | #import "WTSafeGuard.h" 11 | #import 12 | #import "JRSwizzle.h" 13 | 14 | @implementation NSMutableSet (WTSafe) 15 | 16 | #pragma mark - Class Public Function 17 | 18 | + (void)runSafeGuard 19 | { 20 | NSError *error = nil; 21 | [objc_getClass("__NSSetM") jr_swizzleMethod:@selector(addObject:) withMethod:@selector(WT_safeAddObject:) error:&error]; 22 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 23 | } 24 | 25 | #pragma mark - Object Private Function 26 | 27 | - (void)WT_safeAddObject:(id)anObject 28 | { 29 | if(!anObject) { 30 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 31 | return; 32 | } 33 | 34 | [self WT_safeAddObject:anObject]; 35 | } 36 | @end 37 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSMutableString+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableString (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSMutableString+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "NSMutableString+WTSafe.h" 10 | #import "WTSafeGuard.h" 11 | #import 12 | #import "JRSwizzle.h" 13 | 14 | @implementation NSMutableString (WTSafe) 15 | #pragma mark - Class Public Function 16 | 17 | + (void)runSafeGuard 18 | { 19 | NSError *error = nil; 20 | 21 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(setString:) withMethod:@selector(WT_safeSetString:) error:&error]; 22 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 23 | 24 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(appendString:) withMethod:@selector(WT_safeAppendString:) error:&error]; 25 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 26 | 27 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(deleteCharactersInRange:) withMethod:@selector(WT_safeDeleteCharactersInRange:) error:&error]; 28 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 29 | 30 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(insertString:atIndex:) withMethod:@selector(WT_safeInsertString:atIndex:) error:&error]; 31 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 32 | 33 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(replaceCharactersInRange:withString:) withMethod:@selector(WT_safeReplaceCharactersInRange:withString:) error:&error]; 34 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 35 | 36 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(replaceOccurrencesOfString:withString:options:range:) withMethod:@selector(WT_safeReplaceOccurrencesOfString:withString:options:range:) error:&error]; 37 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 38 | } 39 | 40 | #pragma mark - Object Private Function 41 | 42 | - (void)WT_safeSetString:(NSString *)aString 43 | { 44 | if (!aString || ![aString isKindOfClass:[NSString class]]) { 45 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 46 | return; 47 | } 48 | 49 | return [self WT_safeSetString:aString]; 50 | } 51 | 52 | - (void)WT_safeAppendString:(NSString *)aString 53 | { 54 | if (!aString || ![aString isKindOfClass:[NSString class]]) { 55 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 56 | return; 57 | } 58 | 59 | return [self WT_safeAppendString:aString]; 60 | } 61 | 62 | - (void)WT_safeDeleteCharactersInRange:(NSRange)range 63 | { 64 | if (range.location > self.length || range.location + range.length > self.length) { 65 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 66 | return; 67 | } 68 | 69 | [self WT_safeDeleteCharactersInRange:range]; 70 | } 71 | 72 | - (void)WT_safeInsertString:(NSString *)aString atIndex:(NSUInteger)loc 73 | { 74 | if (!aString || ![aString isKindOfClass:[NSString class]]) { 75 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 76 | return; 77 | } 78 | 79 | if (loc > self.length) { 80 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 81 | return; 82 | } 83 | 84 | [self WT_safeInsertString:aString atIndex:loc]; 85 | } 86 | 87 | - (void)WT_safeReplaceCharactersInRange:(NSRange)range withString:(NSString *)aString 88 | { 89 | if (range.location > self.length || range.location + range.length > self.length) { 90 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 91 | return; 92 | } 93 | 94 | if (!aString || ![aString isKindOfClass:[NSString class]]) { 95 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 96 | return; 97 | } 98 | 99 | [self WT_safeReplaceCharactersInRange:range withString:aString]; 100 | } 101 | 102 | - (NSUInteger)WT_safeReplaceOccurrencesOfString:(NSString *)target 103 | withString:(NSString *)replacement 104 | options:(NSStringCompareOptions)options 105 | range:(NSRange)searchRange 106 | { 107 | if (!target || ![target isKindOfClass:[NSString class]]) { 108 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 109 | return 0; 110 | } 111 | 112 | if (!replacement || ![replacement isKindOfClass:[NSString class]]) { 113 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 114 | return 0; 115 | } 116 | 117 | if (searchRange.location > self.length || searchRange.location + searchRange.length > self.length) { 118 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 119 | return 0; 120 | } 121 | 122 | return [self WT_safeReplaceOccurrencesOfString:target 123 | withString:replacement 124 | options:options 125 | range:searchRange]; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSSet+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSSet+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSSet (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSSet+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSSet+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "NSSet+WTSafe.h" 10 | #import 11 | #import "JRSwizzle.h" 12 | #import "WTSafeGuard.h" 13 | 14 | @implementation NSSet (WTSafe) 15 | 16 | #pragma mark - Class Public Function 17 | 18 | + (void)runSafeGuard 19 | { 20 | NSError *error = nil; 21 | [objc_getClass("__NSPlaceholderSet") jr_swizzleMethod:@selector(initWithObjects:count:) withMethod:@selector(WT_initWithObjects: count:) error:&error]; 22 | 23 | [objc_getClass("__NSSetI") jr_swizzleMethod:@selector(makeObjectsPerformSelector:) withMethod:@selector(WT_safeMakeObjectsPerformSelector:) error:&error]; 24 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 25 | 26 | [objc_getClass("__NSSetI") jr_swizzleMethod:@selector(makeObjectsPerformSelector:withObject:) withMethod:@selector(WT_safeMakeObjectsPerformSelector:withObject:) error:&error]; 27 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 28 | 29 | [objc_getClass("__NSSetM") jr_swizzleMethod:@selector(makeObjectsPerformSelector:) withMethod:@selector(WT_safeMakeObjectsPerformSelector:) error:&error]; 30 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 31 | 32 | [objc_getClass("__NSSetM") jr_swizzleMethod:@selector(addObject:) withMethod:@selector(WT_addObject:) error:&error]; 33 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 34 | 35 | [objc_getClass("__NSSetM") jr_swizzleMethod:@selector(makeObjectsPerformSelector:withObject:) withMethod:@selector(WT_safeMakeObjectsPerformSelector:withObject:) error:&error]; 36 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 37 | } 38 | 39 | #pragma mark - Class Private Function 40 | - (instancetype)WT_initWithObjects:(const id [])objects count:(NSUInteger)cnt 41 | { 42 | for (int i = 0; i < cnt; ++i) { 43 | if(objects && objects[i] == nil) { 44 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 45 | return nil; 46 | } 47 | } 48 | return [self WT_initWithObjects:objects count:cnt]; 49 | } 50 | 51 | - (void)WT_addObject:(id)object; 52 | { 53 | if (!object) { 54 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 55 | return; 56 | } 57 | 58 | return [self WT_addObject:object]; 59 | } 60 | 61 | 62 | 63 | - (void)WT_safeMakeObjectsPerformSelector:(SEL)aSelector 64 | { 65 | if (!aSelector) { 66 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 67 | return; 68 | } 69 | 70 | return [self WT_safeMakeObjectsPerformSelector:aSelector]; 71 | } 72 | 73 | - (void)WT_safeMakeObjectsPerformSelector:(SEL)aSelector 74 | withObject:(id)argument 75 | { 76 | if (!aSelector) { 77 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 78 | return; 79 | } 80 | 81 | return [self WT_safeMakeObjectsPerformSelector:aSelector withObject:argument]; 82 | } 83 | 84 | @end 85 | 86 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSString+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSString+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "NSString+WTSafe.h" 10 | #import "JRSwizzle.h" 11 | #import 12 | #import "WTSafeGuard.h" 13 | 14 | @implementation NSString (WTSafe) 15 | 16 | + (void)runSafeGuard 17 | { 18 | NSError *error = nil; 19 | 20 | [NSString jr_swizzleClassMethod:@selector(stringWithUTF8String:) withClassMethod:@selector(WT_safeStringWithUTF8String:) error:&error]; 21 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 22 | 23 | [NSString jr_swizzleMethod:@selector(stringByAppendingString:) withMethod:@selector(WT_safeStringByAppendingString:) error:&error]; 24 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 25 | 26 | [objc_getClass("NSPlaceholderString") jr_swizzleMethod:@selector(initWithString:) withMethod:@selector(WT_safeInitWithString:) error:&error]; 27 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 28 | 29 | [objc_getClass("NSPlaceholderMutableString") jr_swizzleMethod:@selector(initWithString:) withMethod:@selector(WT_safeInitWithString:) error:&error]; 30 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 31 | 32 | [objc_getClass("NSPlaceholderString") jr_swizzleMethod:@selector(initWithUTF8String:) withMethod:@selector(WT_safeInitWithUTF8String:) error:&error]; 33 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 34 | 35 | [objc_getClass("NSPlaceholderMutableString") jr_swizzleMethod:@selector(initWithUTF8String:) withMethod:@selector(WT_safeInitWithUTF8String:) error:&error]; 36 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 37 | 38 | [objc_getClass("NSPlaceholderString") jr_swizzleMethod:@selector(initWithFormat:locale:arguments:) withMethod:@selector(WT_safeInitWithFormat:locale:arguments:) error:&error]; 39 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 40 | 41 | [objc_getClass("NSPlaceholderMutableString") jr_swizzleMethod:@selector(initWithFormat:locale:arguments:) withMethod:@selector(WT_safeInitWithFormat:locale:arguments:) error:&error]; 42 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 43 | 44 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(characterAtIndex:) withMethod:@selector(WT_safeCharacterAtIndex:) error:&error]; 45 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 46 | 47 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(characterAtIndex:) withMethod:@selector(WT_safeCharacterAtIndex:) error:&error]; 48 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 49 | 50 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(getCharacters:range:) withMethod:@selector(WT_safeGetCharacters:range:) error:&error]; 51 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 52 | 53 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(getCharacters:range:) withMethod:@selector(WT_safeGetCharacters:range:) error:&error]; 54 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 55 | 56 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(rangeOfCharacterFromSet:options:range:) withMethod:@selector(WT_safeRangeOfCharacterFromSet:options:range:) error:&error]; 57 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 58 | 59 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(rangeOfCharacterFromSet:options:range:) withMethod:@selector(WT_safeRangeOfCharacterFromSet:options:range:) error:&error]; 60 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 61 | 62 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(rangeOfString:options:range:locale:) withMethod:@selector(WT_safeRangeOfString:options:range:locale:) error:&error]; 63 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 64 | 65 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(rangeOfString:options:range:locale:) withMethod:@selector(WT_safeRangeOfString:options:range:locale:) error:&error]; 66 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 67 | 68 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(substringFromIndex:) withMethod:@selector(WT_safeSubstringFromIndex:) error:&error]; 69 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 70 | 71 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(substringFromIndex:) withMethod:@selector(WT_safeSubstringFromIndex:) error:&error]; 72 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 73 | 74 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(substringWithRange:) withMethod:@selector(WT_safeSubstringWithRange:) error:&error]; 75 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 76 | 77 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(substringWithRange:) withMethod:@selector(WT_safeSubstringWithRange:) error:&error]; 78 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 79 | 80 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(substringToIndex:) withMethod:@selector(WT_safeSubstringToIndex:) error:&error]; 81 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 82 | 83 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(substringToIndex:) withMethod:@selector(WT_safeSubstringToIndex:) error:&error]; 84 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 85 | 86 | [objc_getClass("__NSCFConstantString") jr_swizzleMethod:@selector(getLineStart:end:contentsEnd:forRange:) withMethod:@selector(WT_safeGetLineStart:end:contentsEnd:forRange:) error:&error]; 87 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 88 | 89 | [objc_getClass("__NSCFString") jr_swizzleMethod:@selector(getLineStart:end:contentsEnd:forRange:) withMethod:@selector(WT_safeGetLineStart:end:contentsEnd:forRange:) error:&error]; 90 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 91 | } 92 | 93 | #pragma mark - Class Private Function 94 | 95 | + (instancetype)WT_safeStringWithUTF8String:(const char *)bytes 96 | { 97 | if (!bytes) { 98 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 99 | return nil; 100 | } 101 | 102 | return [self WT_safeStringWithUTF8String:bytes]; 103 | } 104 | 105 | #pragma mark - Object Private Function 106 | 107 | - (instancetype)WT_safeInitWithString:(NSString *)aString 108 | { 109 | if (!aString || ![aString isKindOfClass:[NSString class]]) { 110 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 111 | return nil; 112 | } 113 | 114 | return [self WT_safeInitWithString:aString]; 115 | } 116 | 117 | - (instancetype)WT_safeInitWithUTF8String:(const char *)nullTerminatedCString 118 | { 119 | if (!nullTerminatedCString) { 120 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 121 | return nil; 122 | } 123 | 124 | return [self WT_safeInitWithUTF8String:nullTerminatedCString]; 125 | } 126 | 127 | - (instancetype)WT_safeInitWithFormat:(NSString *)format locale:(id)locale arguments:(va_list)argList 128 | { 129 | if (!format || ![format isKindOfClass:[NSString class]]) { 130 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 131 | return nil; 132 | } 133 | 134 | return [self WT_safeInitWithFormat:format locale:locale arguments:argList]; 135 | } 136 | 137 | - (NSString *)WT_safeStringByAppendingString:(NSString *)aString 138 | { 139 | if (!aString || ![aString isKindOfClass:[NSString class]]) { 140 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 141 | return nil; 142 | } 143 | 144 | return [self WT_safeStringByAppendingString:aString]; 145 | } 146 | 147 | - (unichar)WT_safeCharacterAtIndex:(NSUInteger)index 148 | { 149 | if (index > self.length) { 150 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 151 | return USHRT_MAX; 152 | } 153 | 154 | return [self WT_safeCharacterAtIndex:index]; 155 | } 156 | 157 | - (void)WT_safeGetCharacters:(unichar *)buffer range:(NSRange)range 158 | { 159 | if (!buffer) { 160 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 161 | return; 162 | } 163 | 164 | if (range.location > self.length || range.location + range.length > self.length) { 165 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 166 | return; 167 | } 168 | 169 | return [self WT_safeGetCharacters:buffer range:range]; 170 | } 171 | 172 | - (NSRange)WT_safeRangeOfCharacterFromSet:(NSCharacterSet *)searchSet 173 | options:(NSStringCompareOptions)mask 174 | range:(NSRange)searchRange 175 | { 176 | if (!searchSet || ![searchSet isKindOfClass:[NSCharacterSet class]]) { 177 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 178 | return NSMakeRange(NSNotFound, 0); 179 | } 180 | 181 | if (searchRange.location > self.length || searchRange.location + searchRange.length > self.length) { 182 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 183 | return NSMakeRange(NSNotFound, 0); 184 | } 185 | 186 | return [self WT_safeRangeOfCharacterFromSet:searchSet options:mask range:searchRange]; 187 | } 188 | 189 | - (NSRange)WT_safeRangeOfString:(NSString *)searchString 190 | options:(NSStringCompareOptions)mask 191 | range:(NSRange)searchRange 192 | locale:(NSLocale *)locale 193 | { 194 | if (!searchString || ![searchString isKindOfClass:[NSString class]]) { 195 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 196 | return NSMakeRange(NSNotFound, 0); 197 | } 198 | 199 | if (searchRange.location > self.length || searchRange.location + searchRange.length > self.length) { 200 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 201 | return NSMakeRange(NSNotFound, 0); 202 | } 203 | 204 | return [self WT_safeRangeOfString:searchString options:mask range:searchRange locale:locale]; 205 | } 206 | 207 | - (NSString *)WT_safeSubstringFromIndex:(NSUInteger)from 208 | { 209 | if (from > self.length) { 210 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 211 | return nil; 212 | } 213 | 214 | return [self WT_safeSubstringFromIndex:from]; 215 | } 216 | 217 | - (NSString *)WT_safeSubstringWithRange:(NSRange)range 218 | { 219 | if (range.location > self.length || range.location + range.length > self.length) { 220 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 221 | return nil; 222 | } 223 | 224 | return [self WT_safeSubstringWithRange:range]; 225 | } 226 | 227 | - (NSString *)WT_safeSubstringToIndex:(NSUInteger)to 228 | { 229 | if (to > self.length) { 230 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 231 | return nil; 232 | } 233 | 234 | return [self WT_safeSubstringToIndex:to]; 235 | } 236 | 237 | - (void)WT_safeGetLineStart:(NSUInteger *)startPtr 238 | end:(NSUInteger *)lineEndPtr 239 | contentsEnd:(NSUInteger *)contentsEndPtr 240 | forRange:(NSRange)range 241 | { 242 | if (range.location > self.length || range.location + range.length > self.length) { 243 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 244 | return; 245 | } 246 | 247 | return [self WT_safeGetLineStart:startPtr 248 | end:lineEndPtr 249 | contentsEnd:contentsEndPtr 250 | forRange:range]; 251 | } 252 | @end 253 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSURL+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSURL (WTSafe) 12 | + (void)runSafeGuard; 13 | @end 14 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Container/NSURL+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | #import "JRSwizzle.h" 11 | #import "NSURL+WTSafe.h" 12 | #import "WTSafeGuard.h" 13 | 14 | @interface NSURL (WTSafeMethodPrivate) 15 | 16 | + (NSURL *)WT_safeFileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir; 17 | 18 | + (NSURL *)WT_safeFileURLWithPathComponents:(NSArray *)components; 19 | 20 | + (NSURL *)WT_safeFileURLWithPath:(NSString *)path isDirectory:(BOOL) isDir relativeToURL:(NSURL *)baseURL; 21 | 22 | - (instancetype)WT_safeInitWithString:(NSString *)URLString relativeToURL:(NSURL *)baseURL; 23 | 24 | - (instancetype)WT_safeInitFileURLWithPath:(NSString *)path; 25 | 26 | - (instancetype)WT_safeInitFileURLWithPath:(NSString *)path 27 | relativeToURL:(NSURL *)baseURL; 28 | 29 | - (instancetype)WT_safeInitFileURLWithPath:(NSString *)path 30 | isDirectory:(BOOL)isDir 31 | relativeToURL:(NSURL *)baseURL; 32 | 33 | @end 34 | 35 | @implementation NSURL (WTSafe) 36 | 37 | #pragma mark - Class Public Function 38 | 39 | + (void)runSafeGuard 40 | { 41 | CGFloat fVersion = [UIDevice currentDevice].systemVersion.floatValue; 42 | NSError *error = nil; 43 | 44 | [NSURL jr_swizzleClassMethod:@selector(fileURLWithPath:isDirectory:) withClassMethod:@selector(WT_safeFileURLWithPath:isDirectory:) error:&error]; 45 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 46 | 47 | [NSURL jr_swizzleClassMethod:@selector(fileURLWithPathComponents:) withClassMethod:@selector(WT_safeFileURLWithPathComponents:) error:&error]; 48 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 49 | 50 | [NSURL jr_swizzleMethod:@selector(initWithString:relativeToURL:) withMethod:@selector(WT_safeInitWithString:relativeToURL:) error:&error]; 51 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 52 | 53 | [NSURL jr_swizzleClassMethod:@selector(fileURLWithPath:) withClassMethod:@selector(WT_safeFileURLWithPath:) error:&error]; 54 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 55 | 56 | [NSURL jr_swizzleMethod:@selector(initFileURLWithPath:) withMethod:@selector(WT_safeInitFileURLWithPath:) error:&error]; 57 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 58 | 59 | if (fVersion >= 9.0f) { 60 | [NSURL jr_swizzleClassMethod:@selector(fileURLWithPath:isDirectory:relativeToURL:) withClassMethod:@selector(WT_safeFileURLWithPath:isDirectory:relativeToURL:) error:&error]; 61 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 62 | 63 | [NSURL jr_swizzleMethod:@selector(initFileURLWithPath:isDirectory:relativeToURL:) withMethod:@selector(WT_safeInitFileURLWithPath:isDirectory:relativeToURL:) error:&error]; 64 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 65 | 66 | [NSURL jr_swizzleMethod:@selector(initFileURLWithPath:relativeToURL:) withMethod:@selector(WT_safeInitFileURLWithPath:relativeToURL:) error:&error]; 67 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 68 | } 69 | } 70 | 71 | #pragma mark - Class Private Function 72 | 73 | + (NSURL *)WT_safeFileURLWithPath:(NSString *)path 74 | { 75 | if(!path) { 76 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 77 | return nil; 78 | } 79 | 80 | return [self WT_safeFileURLWithPath:path]; 81 | } 82 | 83 | + (NSURL *)WT_safeFileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir 84 | { 85 | if(!path) { 86 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 87 | return nil; 88 | } 89 | 90 | return [self WT_safeFileURLWithPath:path isDirectory:isDir]; 91 | } 92 | 93 | + (NSURL *)WT_safeFileURLWithPathComponents:(NSArray *)components 94 | { 95 | if(!components) { 96 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 97 | return nil; 98 | } 99 | 100 | return [self WT_safeFileURLWithPathComponents:components]; 101 | } 102 | 103 | + (NSURL *)WT_safeFileURLWithPath:(NSString *)path 104 | isDirectory:(BOOL)isDir 105 | relativeToURL:(NSURL *)baseURL 106 | { 107 | if (!path || ![path isKindOfClass:[NSString class]]) { 108 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 109 | return nil; 110 | } 111 | 112 | return [self WT_safeFileURLWithPath:path isDirectory:isDir relativeToURL:baseURL]; 113 | } 114 | 115 | #pragma mark - Object Private Function 116 | 117 | - (instancetype)WT_safeInitWithString:(NSString *)URLString relativeToURL:(NSURL *)baseURL 118 | { 119 | if (!URLString || ![URLString isKindOfClass:[NSString class]]) { 120 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 121 | return nil; 122 | } 123 | 124 | return [self WT_safeInitWithString:URLString relativeToURL:baseURL]; 125 | } 126 | 127 | - (instancetype)WT_safeInitFileURLWithPath:(NSString *)path 128 | { 129 | if (!path || ![path isKindOfClass:[NSString class]]) { 130 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 131 | return nil; 132 | } 133 | 134 | return [self WT_safeInitFileURLWithPath:path]; 135 | } 136 | 137 | - (instancetype)WT_safeInitFileURLWithPath:(NSString *)path 138 | relativeToURL:(NSURL *)baseURL 139 | { 140 | if (!path || ![path isKindOfClass:[NSString class]]) { 141 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 142 | return nil; 143 | } 144 | 145 | return [self WT_safeInitFileURLWithPath:path relativeToURL:baseURL]; 146 | } 147 | 148 | - (instancetype)WT_safeInitFileURLWithPath:(NSString *)path 149 | isDirectory:(BOOL)isDir 150 | relativeToURL:(NSURL *)baseURL 151 | { 152 | if (!path || ![path isKindOfClass:[NSString class]]) { 153 | [WTSafeGuard updateGuardCrashClassName:NSStringFromClass(self.class) selector:NSStringFromSelector(_cmd)]; 154 | return nil; 155 | } 156 | 157 | return [self WT_safeInitFileURLWithPath:path isDirectory:isDir relativeToURL:baseURL]; 158 | } 159 | 160 | @end 161 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/KVO/WTKVOMapManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTKVOMapManager.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/26. 6 | // 7 | // 8 | 9 | #import 10 | #import "WTKVOResource.h" 11 | 12 | @interface WTKVOMapManager : NSObject 13 | 14 | + (WTKVOMapManager *)shareInstance; 15 | 16 | - (BOOL)isMapObserver:(id)observer inkeySource:(id)keySource keyPath:(NSString*)path; 17 | 18 | - (BOOL)observerRemove:(id)observer inkeySource:(id)keySource keyPath:(NSString*)path; 19 | 20 | - (void)addObserver:(id)observer source:(WTKVOResource *)source; 21 | 22 | - (BOOL)observeValueForKeyPath:(id)observer inkeySource:(id)keySource keyPath:(NSString*)path; 23 | 24 | - (void)removeAllObserver:(id)source; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/KVO/WTKVOMapManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTKVOMapManager.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/26. 6 | // 7 | // 8 | 9 | #import "WTKVOMapManager.h" 10 | 11 | @interface WTKVOMapManager () 12 | 13 | @property (nonatomic, strong) NSMutableDictionary *kvoMap; 14 | @property (nonatomic, strong) NSLock *kvoMapLock; 15 | 16 | @end 17 | 18 | @implementation WTKVOMapManager 19 | 20 | + (WTKVOMapManager *)shareInstance 21 | { 22 | static dispatch_once_t onceToken; 23 | static WTKVOMapManager *shareInstance; 24 | 25 | dispatch_once(&onceToken, ^{ 26 | shareInstance = [[WTKVOMapManager alloc] init]; 27 | }); 28 | 29 | return shareInstance; 30 | } 31 | 32 | - (instancetype)init 33 | { 34 | if (self = [super init]) { 35 | _kvoMap = [NSMutableDictionary dictionary]; 36 | _kvoMapLock = [[NSLock alloc] init]; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (BOOL)isMapObserver:(id)observer inkeySource:(id)keySource keyPath:(NSString*)path 43 | { 44 | NSString *key = [NSString stringWithFormat:@"%@_%p",NSStringFromClass([observer class]),observer]; 45 | [self.kvoMapLock lock]; 46 | id obj = [self.kvoMap objectForKey:key]; 47 | if ([obj isKindOfClass:[NSMutableArray class]]) { 48 | for (id source in obj) { 49 | if ([source isKindOfClass:[WTKVOResource class]]) { 50 | if ([(WTKVOResource*)source resource] == keySource && [(WTKVOResource*)source key] == path) { 51 | [self.kvoMapLock unlock]; 52 | return YES; 53 | } 54 | } 55 | } 56 | } 57 | [self.kvoMapLock unlock]; 58 | return NO; 59 | } 60 | 61 | - (BOOL)observerRemove:(id)observer inkeySource:(id)keySource keyPath:(NSString*)path 62 | { 63 | NSString *key = [NSString stringWithFormat:@"%@_%p",NSStringFromClass([observer class]),observer]; 64 | [self.kvoMapLock lock]; 65 | id obj = [self.kvoMap objectForKey:key]; 66 | if ([obj isKindOfClass:[NSMutableArray class]]) { 67 | for (id source in obj) { 68 | if ([source isKindOfClass:[WTKVOResource class]]) { 69 | if ([(WTKVOResource*)source resource] == keySource && [(WTKVOResource*)source key] == path) { 70 | [obj removeObject:source]; 71 | [self.kvoMapLock unlock]; 72 | return YES; 73 | } 74 | } 75 | } 76 | } 77 | [self.kvoMapLock unlock]; 78 | return NO; 79 | } 80 | 81 | - (void)removeAllObserver:(id)source 82 | { 83 | [self.kvoMapLock lock]; 84 | [self.kvoMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, NSMutableArray *obj, BOOL * _Nonnull stop) { 85 | for (id resource in obj) { 86 | if ([resource isKindOfClass:[WTKVOResource class]]) { 87 | NSLog(@"%@", [(WTKVOResource*)resource observer]); 88 | NSLog(@"%@", source); 89 | if ([(WTKVOResource*)resource observer] == source || [(WTKVOResource*)resource observer] == NULL) { 90 | [[(WTKVOResource*)resource resource] removeObserver:source forKeyPath:[(WTKVOResource*)resource key]]; 91 | *stop = YES; 92 | } 93 | } 94 | } 95 | }]; 96 | [self.kvoMapLock unlock]; 97 | } 98 | 99 | - (BOOL)observeValueForKeyPath:(id)observer inkeySource:(id)keySource keyPath:(NSString*)path 100 | { 101 | NSString *key = [NSString stringWithFormat:@"%@_%p",NSStringFromClass([observer class]),observer]; 102 | [self.kvoMapLock lock]; 103 | id obj = [self.kvoMap objectForKey:key]; 104 | if ([obj isKindOfClass:[NSMutableArray class]]) { 105 | for (id source in obj) { 106 | if ([source isKindOfClass:[WTKVOResource class]]) { 107 | if ([(WTKVOResource*)source resource] == nil && [(WTKVOResource*)source key] == path) { 108 | [obj removeObject:source]; 109 | [self.kvoMapLock unlock]; 110 | return YES; 111 | } 112 | } 113 | } 114 | } 115 | [self.kvoMapLock unlock]; 116 | return NO; 117 | } 118 | 119 | - (void)addObserver:(id)observer source:(WTKVOResource *)source 120 | { 121 | if (nil == observer || nil == source) { 122 | return; 123 | } 124 | 125 | NSString *key = [NSString stringWithFormat:@"%@_%p",NSStringFromClass([observer class]),observer]; 126 | [self.kvoMapLock lock]; 127 | if ([self.kvoMap objectForKey:key]) { 128 | id obj = [self.kvoMap objectForKey:key]; 129 | if ([obj isKindOfClass:[NSArray class]]) { 130 | NSMutableArray *array = [NSMutableArray arrayWithArray:obj]; 131 | if (![array containsObject:source]) { 132 | [array addObject:source]; 133 | [self.kvoMap setObject:array forKey:key]; 134 | } 135 | } 136 | }else{ 137 | NSMutableArray *array = [NSMutableArray array]; 138 | [array addObject:source]; 139 | [self.kvoMap setObject:array forKey:key]; 140 | } 141 | [self.kvoMapLock unlock]; 142 | } 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/KVO/WTKVOResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTKVOResource.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface WTKVOResource : NSObject 12 | 13 | @property (nonatomic, strong)id resource; 14 | @property (nonatomic, strong)NSString *key; 15 | @property (nonatomic, weak) id observer; 16 | 17 | - (id)initWithResource:(id)resource observer:(id)observer key:(NSString *)key; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/KVO/WTKVOResource.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTKVOResource.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/23. 6 | // 7 | // 8 | 9 | #import "WTKVOResource.h" 10 | 11 | @implementation WTKVOResource 12 | 13 | - (id)initWithResource:(id)resource observer:(id)observer key:(NSString *)key 14 | { 15 | self = [super init]; 16 | if (self) { 17 | self.resource = resource; 18 | self.key = key; 19 | self.observer = observer; 20 | } 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/NSObject+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (WTSafe) 12 | 13 | + (void)runSafeGuard; 14 | + (void)runSafeGuardKVO; 15 | @end 16 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/NSObject+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/12. 6 | // 7 | // 8 | 9 | #import "NSObject+WTSafe.h" 10 | #import "WTSafeGuard.h" 11 | #import "JRSwizzle.h" 12 | #import "WTKVOResource.h" 13 | #import "WTKVOMapManager.h" 14 | 15 | @implementation NSObject (WTSafe) 16 | 17 | + (void)runSafeGuard 18 | { 19 | NSError *error = nil; 20 | [NSObject jr_swizzleMethod:@selector(forwardingTargetForSelector:) withMethod:@selector(WT_safeForwardingTargetForSelector:) error:&error]; 21 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 22 | } 23 | 24 | + (void)runSafeGuardKVO 25 | { 26 | NSError *error = nil; 27 | //KVO 28 | [NSObject jr_swizzleMethod:@selector(addObserver:forKeyPath:options:context:) withMethod:@selector(WT_addObserver:forKeyPath:options:context:) error:&error]; 29 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 30 | [NSObject jr_swizzleMethod:@selector(removeObserver:forKeyPath:) withMethod:@selector(WT_removeObserver:forKeyPath:) error:&error]; 31 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 32 | [NSObject jr_swizzleMethod:@selector(observeValueForKeyPath:ofObject:change:context:) withMethod:@selector(WT_observeValueForKeyPath:ofObject:change:context:) error:&error]; 33 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 34 | [NSObject jr_swizzleMethod:@selector(removeObserver:forKeyPath:context:) withMethod:@selector(WT_removeObserver:forKeyPath:context:) error:&error]; 35 | } 36 | 37 | #pragma mark - Object Private Function 38 | 39 | - (id)WT_safeForwardingTargetForSelector:(SEL)aSelector 40 | { 41 | NSMethodSignature *signature = [self methodSignatureForSelector:aSelector]; 42 | if ([self respondsToSelector:aSelector] || signature) { 43 | return [self WT_safeForwardingTargetForSelector:aSelector]; 44 | } 45 | 46 | return [WTSafeGuard createFakeForwardTargetObject:self selector:aSelector]; 47 | } 48 | 49 | - (void)WT_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context 50 | { 51 | if (![[WTKVOMapManager shareInstance] isMapObserver:observer inkeySource:self keyPath:keyPath]) { 52 | WTKVOResource *resource = [[WTKVOResource alloc] initWithResource:self observer:observer key:keyPath]; 53 | [[WTKVOMapManager shareInstance] addObserver:observer source:resource]; 54 | [self WT_addObserver:observer forKeyPath:keyPath options:options context:context]; 55 | } 56 | } 57 | 58 | - (void)WT_kvoDealloc 59 | { 60 | [[WTKVOMapManager shareInstance] removeAllObserver:self]; 61 | [self WT_kvoDealloc]; 62 | } 63 | 64 | - (void)WT_removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath 65 | { 66 | if ([[WTKVOMapManager shareInstance] observerRemove:observer inkeySource:self keyPath:keyPath]) { 67 | [self WT_removeObserver:observer forKeyPath:keyPath]; 68 | } 69 | } 70 | 71 | - (void)WT_removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context 72 | { 73 | if ([[WTKVOMapManager shareInstance] observerRemove:observer inkeySource:self keyPath:keyPath]) { 74 | [self WT_removeObserver:observer forKeyPath:keyPath context:context]; 75 | } 76 | } 77 | 78 | - (void)WT_observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 79 | { 80 | if (![[WTKVOMapManager shareInstance] observeValueForKeyPath:object inkeySource:self keyPath:keyPath]) { 81 | [self WT_observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 82 | } 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Target/WTFakeForwardTargetObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTFakeForwardTargetObject.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface WTFakeForwardTargetObject : NSObject 12 | 13 | - (instancetype)initWithSelector:(SEL)aSelector; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Target/WTFakeForwardTargetObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTFakeForwardTargetObject.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/12. 6 | // 7 | // 8 | 9 | #import "WTFakeForwardTargetObject.h" 10 | #import 11 | 12 | id fakeIMP(id sender,SEL sel,...){ 13 | return nil; 14 | } 15 | 16 | @implementation WTFakeForwardTargetObject 17 | 18 | - (instancetype)initWithSelector:(SEL)aSelector 19 | { 20 | if (self = [super init]) { 21 | if(class_addMethod([self class], aSelector, (IMP)fakeIMP, NULL)) { 22 | #ifdef DEBUG 23 | NSLog(@"add Fake Selector:[instance %@]", NSStringFromSelector(aSelector)); 24 | #endif 25 | } 26 | } 27 | 28 | return self; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Timer/NSTimer+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+WTSafe.h 3 | // Pods 4 | // 5 | // Created by walter on 30/07/2017. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSTimer (WTSafe) 12 | 13 | + (void)runSafeGuard; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Timer/NSTimer+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimer+WTSafe.m 3 | // Pods 4 | // 5 | // Created by walter on 30/07/2017. 6 | // 7 | // 8 | 9 | #import "NSTimer+WTSafe.h" 10 | #import "WTSafeGuard.h" 11 | #import "JRSwizzle.h" 12 | #import "WTWeakTimerTarget.h" 13 | 14 | @implementation NSTimer (WTSafe) 15 | 16 | + (void)runSafeGuard 17 | { 18 | NSError *error = nil; 19 | [NSTimer jr_swizzleMethod:@selector(scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:) withMethod:@selector(WT_safeScheduledTimerWithTimeInterval:target:selector:userInfo:repeats:) error:&error]; 20 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 21 | 22 | } 23 | 24 | + (NSTimer *)WT_safeScheduledTimerWithTimeInterval:(NSTimeInterval)ti 25 | target:(id)aTarget 26 | selector:(SEL)aSelector 27 | userInfo:(nullable id)userInfo 28 | repeats:(BOOL)yesOrNo 29 | { 30 | WTWeakTimerTarget *weakTarget = [[WTWeakTimerTarget alloc] init]; 31 | weakTarget.target = aTarget; 32 | weakTarget.selector = aSelector; 33 | weakTarget.timer = [self WT_safeScheduledTimerWithTimeInterval:ti target:weakTarget selector:@selector(timeSelector:) userInfo:userInfo repeats:yesOrNo]; 34 | return weakTarget.timer; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Timer/WTWeakTimerTarget.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTWeakTimerTarget.h 3 | // Pods 4 | // 5 | // Created by walter on 30/07/2017. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface WTWeakTimerTarget : NSObject 12 | 13 | @property (nonatomic, weak) id target; 14 | @property (nonatomic, assign) SEL selector; 15 | @property (nonatomic, weak) NSTimer* timer; 16 | 17 | - (void)timeSelector:(NSTimer *)timer; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/Timer/WTWeakTimerTarget.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTWeakTimerTarget.m 3 | // Pods 4 | // 5 | // Created by walter on 30/07/2017. 6 | // 7 | // 8 | 9 | #import "WTWeakTimerTarget.h" 10 | 11 | @implementation WTWeakTimerTarget 12 | 13 | - (void)timeSelector:(NSTimer *)timer 14 | { 15 | if(self.target) { 16 | #pragma clang diagnostic push 17 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 18 | [self.target performSelector:self.selector withObject:timer.userInfo afterDelay:0.0f]; 19 | #pragma clang diagnostic pop 20 | } else { 21 | [self.timer invalidate]; 22 | } 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/UI/UIPasteboard+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIPasteboard+WTSafe.h 3 | // WTSafeGuard 4 | // 5 | // Created by hongru qi on 26/09/2017. 6 | // 7 | 8 | #import 9 | 10 | @interface UIPasteboard (WTSafe) 11 | 12 | + (void)runSafeGuard; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/UI/UIPasteboard+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIPasteboard+WTSafe.m 3 | // WTSafeGuard 4 | // 5 | // Created by hongru qi on 26/09/2017. 6 | // 7 | 8 | #import "UIPasteboard+WTSafe.h" 9 | #import "JRSwizzle.h" 10 | #import 11 | #import "WTSafeGuard.h" 12 | 13 | @implementation UIPasteboard (WTSafe) 14 | 15 | + (void)runSafeGuard 16 | { 17 | NSError *error = nil; 18 | [UIPasteboard jr_swizzleMethod:@selector(pasteboardWithName: create:) withMethod:@selector(wt_pasteboardWithName: create:) error:&error]; 19 | } 20 | 21 | + (nullable UIPasteboard *)wt_pasteboardWithName:(UIPasteboardName)pasteboardName create:(BOOL)create 22 | { 23 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) { 24 | return [self wt_pasteboardWithName:pasteboardName create:create]; 25 | } else { 26 | __block UIPasteboard *board; 27 | dispatch_sync(dispatch_get_main_queue(), ^{ 28 | board = [self wt_pasteboardWithName:pasteboardName create:create]; 29 | }); 30 | 31 | return board; 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/UI/UIView+WTSafe.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+WTSafe.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/26. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (WTSafe) 12 | 13 | + (void)runSafeGuard; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/UI/UIView+WTSafe.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+WTSafe.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/26. 6 | // 7 | // 8 | 9 | #import "UIView+WTSafe.h" 10 | #import "JRSwizzle.h" 11 | #import 12 | #import "WTSafeGuard.h" 13 | 14 | @implementation UIView (WTSafe) 15 | 16 | + (void)runSafeGuard 17 | { 18 | NSError *error = nil; 19 | 20 | [UIView jr_swizzleMethod:@selector(setNeedsLayout) withMethod:@selector(WT_safe_setNeedsLayout) error:&error]; 21 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 22 | [UIView jr_swizzleMethod:@selector(layoutIfNeeded) withMethod:@selector(WT_safe_layoutIfNeeded) error:&error]; 23 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 24 | [UIView jr_swizzleMethod:@selector(layoutSubviews) withMethod:@selector(WT_safe_layoutSubviews) error:&error]; 25 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 26 | [UIView jr_swizzleMethod:@selector(setNeedsUpdateConstraints) withMethod:@selector(WT_safe_setNeedsUpdateConstraints) error:&error]; 27 | [WTSafeGuard logSafeMethodErrorThenSetNil:&error]; 28 | 29 | } 30 | 31 | - (void)WT_safe_setNeedsLayout 32 | { 33 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) { 34 | [self WT_safe_setNeedsLayout]; 35 | } else { 36 | dispatch_async(dispatch_get_main_queue(), ^{ 37 | [self WT_safe_setNeedsLayout]; 38 | }); 39 | } 40 | } 41 | 42 | - (void)WT_safe_layoutIfNeeded 43 | { 44 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) { 45 | [self WT_safe_layoutIfNeeded]; 46 | } else { 47 | dispatch_async(dispatch_get_main_queue(), ^{ 48 | [self WT_safe_layoutIfNeeded]; 49 | }); 50 | } 51 | } 52 | 53 | - (void)WT_safe_layoutSubviews 54 | { 55 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) { 56 | [self WT_safe_layoutSubviews]; 57 | } else { 58 | dispatch_async(dispatch_get_main_queue(), ^{ 59 | [self WT_safe_layoutSubviews]; 60 | }); 61 | } 62 | } 63 | 64 | - (void)WT_safe_setNeedsUpdateConstraints 65 | { 66 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) { 67 | [self WT_safe_setNeedsUpdateConstraints]; 68 | } else { 69 | dispatch_async(dispatch_get_main_queue(), ^{ 70 | [self WT_safe_setNeedsUpdateConstraints]; 71 | }); 72 | } 73 | } 74 | @end 75 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/WTSafeGuard.h: -------------------------------------------------------------------------------- 1 | // 2 | // WTSafeGuard.h 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/12. 6 | // 7 | // 8 | 9 | #import 10 | @class WTKVOResource; 11 | 12 | @protocol WTSafeGuardDelegate 13 | 14 | - (void)safeGuardCrashMessage:(NSString *)className selector:(NSString *)selector stack:(NSArray *)stack; 15 | 16 | @end 17 | 18 | typedef NS_OPTIONS(NSUInteger, WTSafeGuardType) { 19 | WTSafeGuardTypeNone = 0, 20 | WTSafeGuardType_MainThreadUI = 1 << 0, 21 | WTSafeGuardType_Foundation = 1 << 1, 22 | WTSafeGuardType_NilTarget = 1 << 2, 23 | WTSafeGuardType_KVO = 1 << 3, 24 | WTSafeGuardType_Timer = 1 << 4 25 | }; 26 | 27 | @interface WTSafeGuard : NSObject 28 | 29 | @property (nonatomic, weak) id delegate; 30 | 31 | + (WTSafeGuard *)shareInstance; 32 | 33 | + (void)startSafeGuardWithType:(WTSafeGuardType)type; 34 | 35 | + (id)createFakeForwardTargetObject:(id)aTarget selector:(SEL)aSelector; 36 | 37 | + (BOOL)logSafeMethodErrorThenSetNil:(NSError **)error; 38 | 39 | + (void)updateGuardCrashClassName:(NSString *)className selector:(NSString *)selector; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /WTSafeGuard/Classes/WTSafeGuard.m: -------------------------------------------------------------------------------- 1 | // 2 | // WTSafeGuard.m 3 | // Pods 4 | // 5 | // Created by hongru qi on 2017/6/12. 6 | // 7 | // 8 | 9 | #import "WTSafeGuard.h" 10 | #import "WTFakeForwardTargetObject.h" 11 | #import "NSObject+WTSafe.h" 12 | #import "NSDictionary+WTSafe.h" 13 | #import "NSMutableDictionary+WTSafe.h" 14 | #import "NSSet+WTSafe.h" 15 | #import "NSMutableSet+WTSafe.h" 16 | #import "NSString+WTSafe.h" 17 | #import "NSMutableString+WTSafe.h" 18 | #import "NSURL+WTSafe.h" 19 | #import "NSFileManager+WTSafe.h" 20 | #import "NSIndexPath+WTSafe.h" 21 | #import "NSJSONSerialization+WTSafe.h" 22 | #import "NSAttributedString+WTSafe.h" 23 | #import "WTKVOResource.h" 24 | #import "NSTimer+WTSafe.h" 25 | 26 | @interface WTSafeGuard () 27 | 28 | @end 29 | 30 | @implementation WTSafeGuard 31 | 32 | + (WTSafeGuard *)shareInstance 33 | { 34 | static dispatch_once_t onceToken; 35 | static WTSafeGuard *shareInstance; 36 | 37 | dispatch_once(&onceToken, ^{ 38 | shareInstance = [[WTSafeGuard alloc] init]; 39 | }); 40 | 41 | return shareInstance; 42 | } 43 | 44 | - (instancetype)init 45 | { 46 | if (self = [super init]) { 47 | } 48 | 49 | return self; 50 | } 51 | 52 | + (void)startSafeGuardWithType:(WTSafeGuardType)type 53 | { 54 | static dispatch_once_t onceToken; 55 | dispatch_once(&onceToken, ^{ 56 | 57 | if (type & WTSafeGuardType_MainThreadUI) { 58 | [self startGuardMainThread]; 59 | } 60 | 61 | if (type & WTSafeGuardType_Foundation){ 62 | [self startGuardFoundation]; 63 | } 64 | 65 | if (type & WTSafeGuardType_NilTarget){ 66 | [self startGuardNilTarget]; 67 | } 68 | 69 | if (type & WTSafeGuardType_KVO){ 70 | [self startGuardKVO]; 71 | } 72 | 73 | if (type & WTSafeGuardType_Timer) { 74 | [self startGuardTimer]; 75 | } 76 | }); 77 | } 78 | 79 | + (id)createFakeForwardTargetObject:(id)aTarget selector:(SEL)aSelector 80 | { 81 | if ([[NSString string] respondsToSelector:aSelector]) { 82 | NSString *szTarget = nil; 83 | if ([aTarget isKindOfClass:[NSNumber class]]) { 84 | szTarget = [NSString stringWithFormat:@"%@", aTarget]; 85 | } 86 | 87 | if (szTarget) { 88 | return szTarget; 89 | } 90 | } 91 | 92 | WTFakeForwardTargetObject *fakeTaget = [[WTFakeForwardTargetObject alloc] initWithSelector:aSelector]; 93 | return fakeTaget; 94 | } 95 | 96 | + (void)startGuardFoundation 97 | { 98 | [NSDictionary runSafeGuard]; 99 | [NSMutableDictionary runSafeGuard]; 100 | [NSSet runSafeGuard]; 101 | [NSMutableSet runSafeGuard]; 102 | [NSString runSafeGuard]; 103 | [NSMutableString runSafeGuard]; 104 | [NSURL runSafeGuard]; 105 | [NSFileManager runSafeGuard]; 106 | [NSIndexPath runSafeGuard]; 107 | [NSJSONSerialization runSafeGuard]; 108 | [NSAttributedString runSafeGuard]; 109 | [NSMutableAttributedString runSafeGuard]; 110 | } 111 | 112 | + (void)startGuardMainThread 113 | { 114 | [UIView runSafeGuard]; 115 | } 116 | 117 | + (void)startGuardNilTarget 118 | { 119 | [NSObject runSafeGuard]; 120 | } 121 | 122 | + (void)startGuardKVO 123 | { 124 | [NSObject runSafeGuardKVO]; 125 | } 126 | 127 | + (void)startGuardTimer 128 | { 129 | [NSTimer runSafeGuard]; 130 | } 131 | 132 | + (BOOL)logSafeMethodErrorThenSetNil:(NSError **)error 133 | { 134 | if (!error) { 135 | return YES; 136 | } 137 | 138 | if (*error) { 139 | #ifdef DEBUG 140 | NSLog(@"%@",(*error).debugDescription); 141 | #endif 142 | *error = nil; 143 | return NO; 144 | } 145 | 146 | return YES; 147 | } 148 | 149 | + (void)updateGuardCrashClassName:(NSString *)className selector:(NSString *)selector 150 | { 151 | NSArray *stack = [NSThread callStackSymbols]; 152 | 153 | if ([[WTSafeGuard shareInstance].delegate respondsToSelector:@selector(safeGuardCrashMessage:selector:stack:)]) { 154 | [[WTSafeGuard shareInstance].delegate safeGuardCrashMessage:className selector:selector stack:stack]; 155 | } 156 | 157 | NSLog(@"guard crash [%@ : %@], stack %@",className, selector, stack); 158 | } 159 | 160 | @end 161 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------