├── .gitignore ├── .travis.yml ├── Example ├── Demo.gif ├── Podfile ├── Podfile.lock ├── Pods │ ├── FBSnapshotTestCase │ │ ├── FBSnapshotTestCase │ │ │ ├── Categories │ │ │ │ ├── UIApplication+StrictKeyWindow.h │ │ │ │ ├── UIApplication+StrictKeyWindow.m │ │ │ │ ├── UIImage+Compare.h │ │ │ │ ├── UIImage+Compare.m │ │ │ │ ├── UIImage+Diff.h │ │ │ │ ├── UIImage+Diff.m │ │ │ │ ├── UIImage+Snapshot.h │ │ │ │ └── UIImage+Snapshot.m │ │ │ ├── FBSnapshotTestCase.h │ │ │ ├── FBSnapshotTestCase.m │ │ │ ├── FBSnapshotTestCasePlatform.h │ │ │ ├── FBSnapshotTestCasePlatform.m │ │ │ ├── FBSnapshotTestController.h │ │ │ ├── FBSnapshotTestController.m │ │ │ └── SwiftSupport.swift │ │ ├── LICENSE │ │ └── README.md │ ├── Local Podspecs │ │ └── WSProgressHUD.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── Shimmer │ │ ├── FBShimmering │ │ │ ├── FBShimmering.h │ │ │ ├── FBShimmeringLayer.h │ │ │ ├── FBShimmeringLayer.m │ │ │ ├── FBShimmeringView.h │ │ │ └── FBShimmeringView.m │ │ ├── LICENSE │ │ └── README.md │ └── Target Support Files │ │ ├── FBSnapshotTestCase │ │ ├── FBSnapshotTestCase-dummy.m │ │ ├── FBSnapshotTestCase-prefix.pch │ │ ├── FBSnapshotTestCase-umbrella.h │ │ ├── FBSnapshotTestCase.modulemap │ │ ├── FBSnapshotTestCase.xcconfig │ │ └── Info.plist │ │ ├── Pods-WSProgressHUD_Example │ │ ├── Info.plist │ │ ├── Pods-WSProgressHUD_Example-acknowledgements.markdown │ │ ├── Pods-WSProgressHUD_Example-acknowledgements.plist │ │ ├── Pods-WSProgressHUD_Example-dummy.m │ │ ├── Pods-WSProgressHUD_Example-frameworks.sh │ │ ├── Pods-WSProgressHUD_Example-resources.sh │ │ ├── Pods-WSProgressHUD_Example-umbrella.h │ │ ├── Pods-WSProgressHUD_Example.debug.xcconfig │ │ ├── Pods-WSProgressHUD_Example.modulemap │ │ └── Pods-WSProgressHUD_Example.release.xcconfig │ │ ├── Pods-WSProgressHUD_Tests │ │ ├── Info.plist │ │ ├── Pods-WSProgressHUD_Tests-acknowledgements.markdown │ │ ├── Pods-WSProgressHUD_Tests-acknowledgements.plist │ │ ├── Pods-WSProgressHUD_Tests-dummy.m │ │ ├── Pods-WSProgressHUD_Tests-frameworks.sh │ │ ├── Pods-WSProgressHUD_Tests-resources.sh │ │ ├── Pods-WSProgressHUD_Tests-umbrella.h │ │ ├── Pods-WSProgressHUD_Tests.debug.xcconfig │ │ ├── Pods-WSProgressHUD_Tests.modulemap │ │ └── Pods-WSProgressHUD_Tests.release.xcconfig │ │ ├── Shimmer │ │ ├── Info.plist │ │ ├── Shimmer-dummy.m │ │ ├── Shimmer-prefix.pch │ │ ├── Shimmer-umbrella.h │ │ ├── Shimmer.modulemap │ │ └── Shimmer.xcconfig │ │ └── WSProgressHUD │ │ ├── Info.plist │ │ ├── ResourceBundle-WSProgressHUD-Info.plist │ │ ├── WSProgressHUD-dummy.m │ │ ├── WSProgressHUD-prefix.pch │ │ ├── WSProgressHUD-umbrella.h │ │ ├── WSProgressHUD.modulemap │ │ └── WSProgressHUD.xcconfig ├── Tests │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj │ │ └── InfoPlist.strings ├── WSProgressHUD.xcodeproj │ └── project.pbxproj ├── WSProgressHUD │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Main.storyboard │ ├── TabViewController1.h │ ├── TabViewController1.m │ ├── TabViewController2.h │ ├── TabViewController2.m │ ├── ViewController.h │ ├── ViewController.m │ ├── WSAppDelegate.h │ ├── WSAppDelegate.m │ ├── WSProgressHUD-Info.plist │ ├── WSProgressHUD-Prefix.pch │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m └── build │ └── XCBuildData │ ├── 1a5c94668b3ca20b660beb5a33864065-desc.xcbuild │ ├── 1a5c94668b3ca20b660beb5a33864065-manifest.xcbuild │ └── BuildDescriptionCacheIndex-265ef7066956889aa1428aabb3b22a2e ├── LICENSE ├── README.md ├── WSProgressHUD.podspec └── WSProgressHUD ├── Assets ├── .gitkeep ├── angle-mask@3x.png ├── error@2x.png └── success@2x.png └── Classes ├── .gitkeep ├── MMMaterialDesignSpinner.h ├── MMMaterialDesignSpinner.m ├── WSIndefiniteAnimationView.h ├── WSIndefiniteAnimationView.m ├── WSProgressHUD.h └── WSProgressHUD.m /.gitignore: -------------------------------------------------------------------------------- 1 | Carthage 2 | xcuserdata 3 | .DS_Store 4 | __MACOSX 5 | DerivedData 6 | WSProgressHUD.framework.zip -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.2 3 | 4 | script: xcodebuild clean build -project Demo/WSProgressHUD.xcodeproj -scheme WSProgressHUD -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO build | xcpretty -c 5 | 6 | 7 | before_install: 8 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet 9 | 10 | 11 | # branches: 12 | # only: 13 | # - master -------------------------------------------------------------------------------- /Example/Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/Example/Demo.gif -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | platform :ios, '8.0' 4 | 5 | target 'WSProgressHUD_Example' do 6 | pod 'WSProgressHUD', :path => '../' 7 | 8 | target 'WSProgressHUD_Tests' do 9 | inherit! :search_paths 10 | 11 | pod 'FBSnapshotTestCase' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FBSnapshotTestCase (2.1.4): 3 | - FBSnapshotTestCase/SwiftSupport (= 2.1.4) 4 | - FBSnapshotTestCase/Core (2.1.4) 5 | - FBSnapshotTestCase/SwiftSupport (2.1.4): 6 | - FBSnapshotTestCase/Core 7 | - Shimmer (1.0.2) 8 | - WSProgressHUD (1.1.5): 9 | - Shimmer 10 | 11 | DEPENDENCIES: 12 | - FBSnapshotTestCase 13 | - WSProgressHUD (from `../`) 14 | 15 | SPEC REPOS: 16 | https://github.com/cocoapods/specs.git: 17 | - FBSnapshotTestCase 18 | - Shimmer 19 | 20 | EXTERNAL SOURCES: 21 | WSProgressHUD: 22 | :path: "../" 23 | 24 | SPEC CHECKSUMS: 25 | FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a 26 | Shimmer: c5374be1c2b0c9e292fb05b339a513cf291cac86 27 | WSProgressHUD: d66881ecb218926f7da320ae36b3426c2ef8d912 28 | 29 | PODFILE CHECKSUM: ab589241c2f3bd950585aebd9abd37de1a2541ed 30 | 31 | COCOAPODS: 1.5.3 32 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | @interface UIApplication (StrictKeyWindow) 14 | 15 | /** 16 | @return The receiver's @c keyWindow. Raises an assertion if @c nil. 17 | */ 18 | - (UIWindow *)fb_strictKeyWindow; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | @implementation UIApplication (StrictKeyWindow) 14 | 15 | - (UIWindow *)fb_strictKeyWindow 16 | { 17 | UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; 18 | if (!keyWindow) { 19 | [NSException raise:@"FBSnapshotTestCaseNilKeyWindowException" 20 | format:@"Snapshot tests must be hosted by an application with a key window. Please ensure your test" 21 | " host sets up a key window at launch (either via storyboards or programmatically) and doesn't" 22 | " do anything to remove it while snapshot tests are running."]; 23 | } 24 | return keyWindow; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | @interface UIImage (Compare) 34 | 35 | - (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | // This makes debugging much more fun 34 | typedef union { 35 | uint32_t raw; 36 | unsigned char bytes[4]; 37 | struct { 38 | char red; 39 | char green; 40 | char blue; 41 | char alpha; 42 | } __attribute__ ((packed)) pixels; 43 | } FBComparePixel; 44 | 45 | @implementation UIImage (Compare) 46 | 47 | - (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance 48 | { 49 | NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size."); 50 | 51 | CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)); 52 | CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); 53 | 54 | // The images have the equal size, so we could use the smallest amount of bytes because of byte padding 55 | size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage)); 56 | size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow; 57 | void *referenceImagePixels = calloc(1, referenceImageSizeBytes); 58 | void *imagePixels = calloc(1, referenceImageSizeBytes); 59 | 60 | if (!referenceImagePixels || !imagePixels) { 61 | free(referenceImagePixels); 62 | free(imagePixels); 63 | return NO; 64 | } 65 | 66 | CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels, 67 | referenceImageSize.width, 68 | referenceImageSize.height, 69 | CGImageGetBitsPerComponent(self.CGImage), 70 | minBytesPerRow, 71 | CGImageGetColorSpace(self.CGImage), 72 | (CGBitmapInfo)kCGImageAlphaPremultipliedLast 73 | ); 74 | CGContextRef imageContext = CGBitmapContextCreate(imagePixels, 75 | imageSize.width, 76 | imageSize.height, 77 | CGImageGetBitsPerComponent(image.CGImage), 78 | minBytesPerRow, 79 | CGImageGetColorSpace(image.CGImage), 80 | (CGBitmapInfo)kCGImageAlphaPremultipliedLast 81 | ); 82 | 83 | if (!referenceImageContext || !imageContext) { 84 | CGContextRelease(referenceImageContext); 85 | CGContextRelease(imageContext); 86 | free(referenceImagePixels); 87 | free(imagePixels); 88 | return NO; 89 | } 90 | 91 | CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage); 92 | CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage); 93 | 94 | CGContextRelease(referenceImageContext); 95 | CGContextRelease(imageContext); 96 | 97 | BOOL imageEqual = YES; 98 | 99 | // Do a fast compare if we can 100 | if (tolerance == 0) { 101 | imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0); 102 | } else { 103 | // Go through each pixel in turn and see if it is different 104 | const NSInteger pixelCount = referenceImageSize.width * referenceImageSize.height; 105 | 106 | FBComparePixel *p1 = referenceImagePixels; 107 | FBComparePixel *p2 = imagePixels; 108 | 109 | NSInteger numDiffPixels = 0; 110 | for (int n = 0; n < pixelCount; ++n) { 111 | // If this pixel is different, increment the pixel diff count and see 112 | // if we have hit our limit. 113 | if (p1->raw != p2->raw) { 114 | numDiffPixels ++; 115 | 116 | CGFloat percent = (CGFloat)numDiffPixels / pixelCount; 117 | if (percent > tolerance) { 118 | imageEqual = NO; 119 | break; 120 | } 121 | } 122 | 123 | p1++; 124 | p2++; 125 | } 126 | } 127 | 128 | free(referenceImagePixels); 129 | free(imagePixels); 130 | 131 | return imageEqual; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | @interface UIImage (Diff) 34 | 35 | - (UIImage *)fb_diffWithImage:(UIImage *)image; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | @implementation UIImage (Diff) 34 | 35 | - (UIImage *)fb_diffWithImage:(UIImage *)image 36 | { 37 | if (!image) { 38 | return nil; 39 | } 40 | CGSize imageSize = CGSizeMake(MAX(self.size.width, image.size.width), MAX(self.size.height, image.size.height)); 41 | UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0); 42 | CGContextRef context = UIGraphicsGetCurrentContext(); 43 | [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; 44 | CGContextSetAlpha(context, 0.5); 45 | CGContextBeginTransparencyLayer(context, NULL); 46 | [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; 47 | CGContextSetBlendMode(context, kCGBlendModeDifference); 48 | CGContextSetFillColorWithColor(context,[UIColor whiteColor].CGColor); 49 | CGContextFillRect(context, CGRectMake(0, 0, self.size.width, self.size.height)); 50 | CGContextEndTransparencyLayer(context); 51 | UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); 52 | UIGraphicsEndImageContext(); 53 | return returnImage; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | @interface UIImage (Snapshot) 14 | 15 | /// Uses renderInContext: to get a snapshot of the layer. 16 | + (UIImage *)fb_imageForLayer:(CALayer *)layer; 17 | 18 | /// Uses renderInContext: to get a snapshot of the view layer. 19 | + (UIImage *)fb_imageForViewLayer:(UIView *)view; 20 | 21 | /// Uses drawViewHierarchyInRect: to get a snapshot of the view and adds the view into a window if needed. 22 | + (UIImage *)fb_imageForView:(UIView *)view; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | @implementation UIImage (Snapshot) 15 | 16 | + (UIImage *)fb_imageForLayer:(CALayer *)layer 17 | { 18 | CGRect bounds = layer.bounds; 19 | NSAssert1(CGRectGetWidth(bounds), @"Zero width for layer %@", layer); 20 | NSAssert1(CGRectGetHeight(bounds), @"Zero height for layer %@", layer); 21 | 22 | UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); 23 | CGContextRef context = UIGraphicsGetCurrentContext(); 24 | NSAssert1(context, @"Could not generate context for layer %@", layer); 25 | CGContextSaveGState(context); 26 | [layer layoutIfNeeded]; 27 | [layer renderInContext:context]; 28 | CGContextRestoreGState(context); 29 | 30 | UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); 31 | UIGraphicsEndImageContext(); 32 | return snapshot; 33 | } 34 | 35 | + (UIImage *)fb_imageForViewLayer:(UIView *)view 36 | { 37 | [view layoutIfNeeded]; 38 | return [self fb_imageForLayer:view.layer]; 39 | } 40 | 41 | + (UIImage *)fb_imageForView:(UIView *)view 42 | { 43 | CGRect bounds = view.bounds; 44 | NSAssert1(CGRectGetWidth(bounds), @"Zero width for view %@", view); 45 | NSAssert1(CGRectGetHeight(bounds), @"Zero height for view %@", view); 46 | 47 | // If the input view is already a UIWindow, then just use that. Otherwise wrap in a window. 48 | UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *)view : view.window; 49 | BOOL removeFromSuperview = NO; 50 | if (!window) { 51 | window = [[UIApplication sharedApplication] fb_strictKeyWindow]; 52 | } 53 | 54 | if (!view.window && view != window) { 55 | [window addSubview:view]; 56 | removeFromSuperview = YES; 57 | } 58 | 59 | UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); 60 | [view layoutIfNeeded]; 61 | [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; 62 | 63 | UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); 64 | UIGraphicsEndImageContext(); 65 | 66 | if (removeFromSuperview) { 67 | [view removeFromSuperview]; 68 | } 69 | 70 | return snapshot; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | #import 15 | 16 | #import 17 | 18 | #import 19 | 20 | /* 21 | There are three ways of setting reference image directories. 22 | 23 | 1. Set the preprocessor macro FB_REFERENCE_IMAGE_DIR to a double quoted 24 | c-string with the path. 25 | 2. Set an environment variable named FB_REFERENCE_IMAGE_DIR with the path. This 26 | takes precedence over the preprocessor macro to allow for run-time override. 27 | 3. Keep everything unset, which will cause the reference images to be looked up 28 | inside the bundle holding the current test, in the 29 | Resources/ReferenceImages_* directories. 30 | */ 31 | #ifndef FB_REFERENCE_IMAGE_DIR 32 | #define FB_REFERENCE_IMAGE_DIR "" 33 | #endif 34 | 35 | /** 36 | Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though. 37 | @param view The view to snapshot 38 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 39 | @param suffixes An NSOrderedSet of strings for the different suffixes 40 | @param tolerance The percentage of pixels that can differ and still count as an 'identical' view 41 | */ 42 | #define FBSnapshotVerifyViewWithOptions(view__, identifier__, suffixes__, tolerance__) \ 43 | FBSnapshotVerifyViewOrLayerWithOptions(View, view__, identifier__, suffixes__, tolerance__) 44 | 45 | #define FBSnapshotVerifyView(view__, identifier__) \ 46 | FBSnapshotVerifyViewWithOptions(view__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0) 47 | 48 | 49 | /** 50 | Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though. 51 | @param layer The layer to snapshot 52 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 53 | @param suffixes An NSOrderedSet of strings for the different suffixes 54 | @param tolerance The percentage of pixels that can differ and still count as an 'identical' layer 55 | */ 56 | #define FBSnapshotVerifyLayerWithOptions(layer__, identifier__, suffixes__, tolerance__) \ 57 | FBSnapshotVerifyViewOrLayerWithOptions(Layer, layer__, identifier__, suffixes__, tolerance__) 58 | 59 | #define FBSnapshotVerifyLayer(layer__, identifier__) \ 60 | FBSnapshotVerifyLayerWithOptions(layer__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0) 61 | 62 | 63 | #define FBSnapshotVerifyViewOrLayerWithOptions(what__, viewOrLayer__, identifier__, suffixes__, tolerance__) \ 64 | { \ 65 | NSString *errorDescription = [self snapshotVerifyViewOrLayer:viewOrLayer__ identifier:identifier__ suffixes:suffixes__ tolerance:tolerance__]; \ 66 | BOOL noErrors = (errorDescription == nil); \ 67 | XCTAssertTrue(noErrors, @"%@", errorDescription); \ 68 | } 69 | 70 | 71 | /** 72 | The base class of view snapshotting tests. If you have small UI component, it's often easier to configure it in a test 73 | and compare an image of the view to a reference image that write lots of complex layout-code tests. 74 | 75 | In order to flip the tests in your subclass to record the reference images set @c recordMode to @c YES. 76 | 77 | @attention When recording, the reference image directory should be explicitly 78 | set, otherwise the images may be written to somewhere inside the 79 | simulator directory. 80 | 81 | For example: 82 | @code 83 | - (void)setUp 84 | { 85 | [super setUp]; 86 | self.recordMode = YES; 87 | } 88 | @endcode 89 | */ 90 | @interface FBSnapshotTestCase : XCTestCase 91 | 92 | /** 93 | When YES, the test macros will save reference images, rather than performing an actual test. 94 | */ 95 | @property (readwrite, nonatomic, assign) BOOL recordMode; 96 | 97 | /** 98 | When @c YES appends the name of the device model and OS to the snapshot file name. 99 | The default value is @c NO. 100 | */ 101 | @property (readwrite, nonatomic, assign, getter=isDeviceAgnostic) BOOL deviceAgnostic; 102 | 103 | /** 104 | When YES, renders a snapshot of the complete view hierarchy as visible onscreen. 105 | There are several things that do not work if renderInContext: is used. 106 | - UIVisualEffect #70 107 | - UIAppearance #91 108 | - Size Classes #92 109 | 110 | @attention If the view does't belong to a UIWindow, it will create one and add the view as a subview. 111 | */ 112 | @property (readwrite, nonatomic, assign) BOOL usesDrawViewHierarchyInRect; 113 | 114 | - (void)setUp NS_REQUIRES_SUPER; 115 | - (void)tearDown NS_REQUIRES_SUPER; 116 | 117 | /** 118 | Performs the comparison or records a snapshot of the layer if recordMode is YES. 119 | @param viewOrLayer The UIView or CALayer to snapshot 120 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 121 | @param suffixes An NSOrderedSet of strings for the different suffixes 122 | @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care 123 | @returns nil if the comparison (or saving of the reference image) succeeded. Otherwise it contains an error description. 124 | */ 125 | - (NSString *)snapshotVerifyViewOrLayer:(id)viewOrLayer 126 | identifier:(NSString *)identifier 127 | suffixes:(NSOrderedSet *)suffixes 128 | tolerance:(CGFloat)tolerance; 129 | 130 | /** 131 | Performs the comparison or records a snapshot of the layer if recordMode is YES. 132 | @param layer The Layer to snapshot 133 | @param referenceImagesDirectory The directory in which reference images are stored. 134 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 135 | @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care 136 | @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 137 | @returns YES if the comparison (or saving of the reference image) succeeded. 138 | */ 139 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 140 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 141 | identifier:(NSString *)identifier 142 | tolerance:(CGFloat)tolerance 143 | error:(NSError **)errorPtr; 144 | 145 | /** 146 | Performs the comparison or records a snapshot of the view if recordMode is YES. 147 | @param view The view to snapshot 148 | @param referenceImagesDirectory The directory in which reference images are stored. 149 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 150 | @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care 151 | @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 152 | @returns YES if the comparison (or saving of the reference image) succeeded. 153 | */ 154 | - (BOOL)compareSnapshotOfView:(UIView *)view 155 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 156 | identifier:(NSString *)identifier 157 | tolerance:(CGFloat)tolerance 158 | error:(NSError **)errorPtr; 159 | 160 | /** 161 | Checks if reference image with identifier based name exists in the reference images directory. 162 | @param referenceImagesDirectory The directory in which reference images are stored. 163 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 164 | @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 165 | @returns YES if reference image exists. 166 | */ 167 | - (BOOL)referenceImageRecordedInDirectory:(NSString *)referenceImagesDirectory 168 | identifier:(NSString *)identifier 169 | error:(NSError **)errorPtr; 170 | 171 | /** 172 | Returns the reference image directory. 173 | 174 | Helper function used to implement the assert macros. 175 | 176 | @param dir directory to use if environment variable not specified. Ignored if null or empty. 177 | */ 178 | - (NSString *)getReferenceImageDirectoryWithDefault:(NSString *)dir; 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | @implementation FBSnapshotTestCase 15 | { 16 | FBSnapshotTestController *_snapshotController; 17 | } 18 | 19 | #pragma mark - Overrides 20 | 21 | - (void)setUp 22 | { 23 | [super setUp]; 24 | _snapshotController = [[FBSnapshotTestController alloc] initWithTestName:NSStringFromClass([self class])]; 25 | } 26 | 27 | - (void)tearDown 28 | { 29 | _snapshotController = nil; 30 | [super tearDown]; 31 | } 32 | 33 | - (BOOL)recordMode 34 | { 35 | return _snapshotController.recordMode; 36 | } 37 | 38 | - (void)setRecordMode:(BOOL)recordMode 39 | { 40 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 41 | _snapshotController.recordMode = recordMode; 42 | } 43 | 44 | - (BOOL)isDeviceAgnostic 45 | { 46 | return _snapshotController.deviceAgnostic; 47 | } 48 | 49 | - (void)setDeviceAgnostic:(BOOL)deviceAgnostic 50 | { 51 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 52 | _snapshotController.deviceAgnostic = deviceAgnostic; 53 | } 54 | 55 | - (BOOL)usesDrawViewHierarchyInRect 56 | { 57 | return _snapshotController.usesDrawViewHierarchyInRect; 58 | } 59 | 60 | - (void)setUsesDrawViewHierarchyInRect:(BOOL)usesDrawViewHierarchyInRect 61 | { 62 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 63 | _snapshotController.usesDrawViewHierarchyInRect = usesDrawViewHierarchyInRect; 64 | } 65 | 66 | #pragma mark - Public API 67 | 68 | - (NSString *)snapshotVerifyViewOrLayer:(id)viewOrLayer 69 | identifier:(NSString *)identifier 70 | suffixes:(NSOrderedSet *)suffixes 71 | tolerance:(CGFloat)tolerance 72 | { 73 | if (nil == viewOrLayer) { 74 | return @"Object to be snapshotted must not be nil"; 75 | } 76 | NSString *referenceImageDirectory = [self getReferenceImageDirectoryWithDefault:(@ FB_REFERENCE_IMAGE_DIR)]; 77 | if (referenceImageDirectory == nil) { 78 | return @"Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme."; 79 | } 80 | if (suffixes.count == 0) { 81 | return [NSString stringWithFormat:@"Suffixes set cannot be empty %@", suffixes]; 82 | } 83 | 84 | BOOL testSuccess = NO; 85 | NSError *error = nil; 86 | NSMutableArray *errors = [NSMutableArray array]; 87 | 88 | if (self.recordMode) { 89 | NSString *referenceImagesDirectory = [NSString stringWithFormat:@"%@%@", referenceImageDirectory, suffixes.firstObject]; 90 | BOOL referenceImageSaved = [self _compareSnapshotOfViewOrLayer:viewOrLayer referenceImagesDirectory:referenceImagesDirectory identifier:(identifier) tolerance:tolerance error:&error]; 91 | if (!referenceImageSaved) { 92 | [errors addObject:error]; 93 | } 94 | } else { 95 | for (NSString *suffix in suffixes) { 96 | NSString *referenceImagesDirectory = [NSString stringWithFormat:@"%@%@", referenceImageDirectory, suffix]; 97 | BOOL referenceImageAvailable = [self referenceImageRecordedInDirectory:referenceImagesDirectory identifier:(identifier) error:&error]; 98 | 99 | if (referenceImageAvailable) { 100 | BOOL comparisonSuccess = [self _compareSnapshotOfViewOrLayer:viewOrLayer referenceImagesDirectory:referenceImagesDirectory identifier:identifier tolerance:tolerance error:&error]; 101 | [errors removeAllObjects]; 102 | if (comparisonSuccess) { 103 | testSuccess = YES; 104 | break; 105 | } else { 106 | [errors addObject:error]; 107 | } 108 | } else { 109 | [errors addObject:error]; 110 | } 111 | } 112 | } 113 | 114 | if (!testSuccess) { 115 | return [NSString stringWithFormat:@"Snapshot comparison failed: %@", errors.firstObject]; 116 | } 117 | if (self.recordMode) { 118 | return @"Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!"; 119 | } 120 | 121 | return nil; 122 | } 123 | 124 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 125 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 126 | identifier:(NSString *)identifier 127 | tolerance:(CGFloat)tolerance 128 | error:(NSError **)errorPtr 129 | { 130 | return [self _compareSnapshotOfViewOrLayer:layer 131 | referenceImagesDirectory:referenceImagesDirectory 132 | identifier:identifier 133 | tolerance:tolerance 134 | error:errorPtr]; 135 | } 136 | 137 | - (BOOL)compareSnapshotOfView:(UIView *)view 138 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 139 | identifier:(NSString *)identifier 140 | tolerance:(CGFloat)tolerance 141 | error:(NSError **)errorPtr 142 | { 143 | return [self _compareSnapshotOfViewOrLayer:view 144 | referenceImagesDirectory:referenceImagesDirectory 145 | identifier:identifier 146 | tolerance:tolerance 147 | error:errorPtr]; 148 | } 149 | 150 | - (BOOL)referenceImageRecordedInDirectory:(NSString *)referenceImagesDirectory 151 | identifier:(NSString *)identifier 152 | error:(NSError **)errorPtr 153 | { 154 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 155 | _snapshotController.referenceImagesDirectory = referenceImagesDirectory; 156 | UIImage *referenceImage = [_snapshotController referenceImageForSelector:self.invocation.selector 157 | identifier:identifier 158 | error:errorPtr]; 159 | 160 | return (referenceImage != nil); 161 | } 162 | 163 | - (NSString *)getReferenceImageDirectoryWithDefault:(NSString *)dir 164 | { 165 | NSString *envReferenceImageDirectory = [NSProcessInfo processInfo].environment[@"FB_REFERENCE_IMAGE_DIR"]; 166 | if (envReferenceImageDirectory) { 167 | return envReferenceImageDirectory; 168 | } 169 | if (dir && dir.length > 0) { 170 | return dir; 171 | } 172 | return [[NSBundle bundleForClass:self.class].resourcePath stringByAppendingPathComponent:@"ReferenceImages"]; 173 | } 174 | 175 | 176 | #pragma mark - Private API 177 | 178 | - (BOOL)_compareSnapshotOfViewOrLayer:(id)viewOrLayer 179 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 180 | identifier:(NSString *)identifier 181 | tolerance:(CGFloat)tolerance 182 | error:(NSError **)errorPtr 183 | { 184 | _snapshotController.referenceImagesDirectory = referenceImagesDirectory; 185 | return [_snapshotController compareSnapshotOfViewOrLayer:viewOrLayer 186 | selector:self.invocation.selector 187 | identifier:identifier 188 | tolerance:tolerance 189 | error:errorPtr]; 190 | } 191 | 192 | @end 193 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /** 18 | Returns a Boolean value that indicates whether the snapshot test is running in 64Bit. 19 | This method is a convenience for creating the suffixes set based on the architecture 20 | that the test is running. 21 | 22 | @returns @c YES if the test is running in 64bit, otherwise @c NO. 23 | */ 24 | BOOL FBSnapshotTestCaseIs64Bit(void); 25 | 26 | /** 27 | Returns a default set of strings that is used to append a suffix based on the architectures. 28 | @warning Do not modify this function, you can create your own and use it with @c FBSnapshotVerifyViewWithOptions() 29 | 30 | @returns An @c NSOrderedSet object containing strings that are appended to the reference images directory. 31 | */ 32 | NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void); 33 | 34 | /** 35 | Returns a fully «normalized» file name. 36 | Strips punctuation and spaces and replaces them with @c _. Also appends the device model, running OS and screen size to the file name. 37 | 38 | @returns An @c NSString object containing the passed @c fileName with the device model, OS and screen size appended at the end. 39 | */ 40 | NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | BOOL FBSnapshotTestCaseIs64Bit(void) 16 | { 17 | #if __LP64__ 18 | return YES; 19 | #else 20 | return NO; 21 | #endif 22 | } 23 | 24 | NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void) 25 | { 26 | NSMutableOrderedSet *suffixesSet = [[NSMutableOrderedSet alloc] init]; 27 | [suffixesSet addObject:@"_32"]; 28 | [suffixesSet addObject:@"_64"]; 29 | if (FBSnapshotTestCaseIs64Bit()) { 30 | return [suffixesSet reversedOrderedSet]; 31 | } 32 | return [suffixesSet copy]; 33 | } 34 | 35 | NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName) 36 | { 37 | UIDevice *device = [UIDevice currentDevice]; 38 | UIWindow *keyWindow = [[UIApplication sharedApplication] fb_strictKeyWindow]; 39 | CGSize screenSize = keyWindow.bounds.size; 40 | NSString *os = device.systemVersion; 41 | 42 | fileName = [NSString stringWithFormat:@"%@_%@%@_%.0fx%.0f", fileName, device.model, os, screenSize.width, screenSize.height]; 43 | 44 | NSMutableCharacterSet *invalidCharacters = [NSMutableCharacterSet new]; 45 | [invalidCharacters formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; 46 | [invalidCharacters formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; 47 | NSArray *validComponents = [fileName componentsSeparatedByCharactersInSet:invalidCharacters]; 48 | fileName = [validComponents componentsJoinedByString:@"_"]; 49 | 50 | return fileName; 51 | } -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | typedef NS_ENUM(NSInteger, FBSnapshotTestControllerErrorCode) { 15 | FBSnapshotTestControllerErrorCodeUnknown, 16 | FBSnapshotTestControllerErrorCodeNeedsRecord, 17 | FBSnapshotTestControllerErrorCodePNGCreationFailed, 18 | FBSnapshotTestControllerErrorCodeImagesDifferentSizes, 19 | FBSnapshotTestControllerErrorCodeImagesDifferent, 20 | }; 21 | /** 22 | Errors returned by the methods of FBSnapshotTestController use this domain. 23 | */ 24 | extern NSString *const FBSnapshotTestControllerErrorDomain; 25 | 26 | /** 27 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 28 | */ 29 | extern NSString *const FBReferenceImageFilePathKey; 30 | 31 | /** 32 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 33 | */ 34 | extern NSString *const FBReferenceImageKey; 35 | 36 | /** 37 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 38 | */ 39 | extern NSString *const FBCapturedImageKey; 40 | 41 | /** 42 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 43 | */ 44 | extern NSString *const FBDiffedImageKey; 45 | 46 | /** 47 | Provides the heavy-lifting for FBSnapshotTestCase. It loads and saves images, along with performing the actual pixel- 48 | by-pixel comparison of images. 49 | Instances are initialized with the test class, and directories to read and write to. 50 | */ 51 | @interface FBSnapshotTestController : NSObject 52 | 53 | /** 54 | Record snapshots. 55 | */ 56 | @property (readwrite, nonatomic, assign) BOOL recordMode; 57 | 58 | /** 59 | When @c YES appends the name of the device model and OS to the snapshot file name. 60 | The default value is @c NO. 61 | */ 62 | @property (readwrite, nonatomic, assign, getter=isDeviceAgnostic) BOOL deviceAgnostic; 63 | 64 | /** 65 | Uses drawViewHierarchyInRect:afterScreenUpdates: to draw the image instead of renderInContext: 66 | */ 67 | @property (readwrite, nonatomic, assign) BOOL usesDrawViewHierarchyInRect; 68 | 69 | /** 70 | The directory in which referfence images are stored. 71 | */ 72 | @property (readwrite, nonatomic, copy) NSString *referenceImagesDirectory; 73 | 74 | /** 75 | @param testClass The subclass of FBSnapshotTestCase that is using this controller. 76 | @returns An instance of FBSnapshotTestController. 77 | */ 78 | - (instancetype)initWithTestClass:(Class)testClass; 79 | 80 | /** 81 | Designated initializer. 82 | @param testName The name of the tests. 83 | @returns An instance of FBSnapshotTestController. 84 | */ 85 | - (instancetype)initWithTestName:(NSString *)testName; 86 | 87 | /** 88 | Performs the comparison of the layer. 89 | @param layer The Layer to snapshot. 90 | @param selector The test method being run. 91 | @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. 92 | @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 93 | @returns YES if the comparison (or saving of the reference image) succeeded. 94 | */ 95 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 96 | selector:(SEL)selector 97 | identifier:(NSString *)identifier 98 | error:(NSError **)errorPtr; 99 | 100 | /** 101 | Performs the comparison of the view. 102 | @param view The view to snapshot. 103 | @param selector The test method being run. 104 | @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. 105 | @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 106 | @returns YES if the comparison (or saving of the reference image) succeeded. 107 | */ 108 | - (BOOL)compareSnapshotOfView:(UIView *)view 109 | selector:(SEL)selector 110 | identifier:(NSString *)identifier 111 | error:(NSError **)errorPtr; 112 | 113 | /** 114 | Performs the comparison of a view or layer. 115 | @param view The view or layer to snapshot. 116 | @param selector The test method being run. 117 | @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. 118 | @param tolerance The percentage of pixels that can differ and still be considered 'identical' 119 | @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 120 | @returns YES if the comparison (or saving of the reference image) succeeded. 121 | */ 122 | - (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer 123 | selector:(SEL)selector 124 | identifier:(NSString *)identifier 125 | tolerance:(CGFloat)tolerance 126 | error:(NSError **)errorPtr; 127 | 128 | /** 129 | Loads a reference image. 130 | @param selector The test method being run. 131 | @param identifier The optional identifier, used when multiple images are tested in a single -test method. 132 | @param errorPtr An error, if this methods returns nil, the error will be something useful. 133 | @returns An image. 134 | */ 135 | - (UIImage *)referenceImageForSelector:(SEL)selector 136 | identifier:(NSString *)identifier 137 | error:(NSError **)errorPtr; 138 | 139 | /** 140 | Performs a pixel-by-pixel comparison of the two images with an allowable margin of error. 141 | @param referenceImage The reference (correct) image. 142 | @param image The image to test against the reference. 143 | @param tolerance The percentage of pixels that can differ and still be considered 'identical' 144 | @param errorPtr An error that indicates why the comparison failed if it does. 145 | @returns YES if the comparison succeeded and the images are the same(ish). 146 | */ 147 | - (BOOL)compareReferenceImage:(UIImage *)referenceImage 148 | toImage:(UIImage *)image 149 | tolerance:(CGFloat)tolerance 150 | error:(NSError **)errorPtr; 151 | 152 | /** 153 | Saves the reference image and the test image to `failedOutputDirectory`. 154 | @param referenceImage The reference (correct) image. 155 | @param testImage The image to test against the reference. 156 | @param selector The test method being run. 157 | @param identifier The optional identifier, used when multiple images are tested in a single -test method. 158 | @param errorPtr An error that indicates why the comparison failed if it does. 159 | @returns YES if the save succeeded. 160 | */ 161 | - (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage 162 | testImage:(UIImage *)testImage 163 | selector:(SEL)selector 164 | identifier:(NSString *)identifier 165 | error:(NSError **)errorPtr; 166 | @end 167 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | #import 18 | 19 | NSString *const FBSnapshotTestControllerErrorDomain = @"FBSnapshotTestControllerErrorDomain"; 20 | NSString *const FBReferenceImageFilePathKey = @"FBReferenceImageFilePathKey"; 21 | NSString *const FBReferenceImageKey = @"FBReferenceImageKey"; 22 | NSString *const FBCapturedImageKey = @"FBCapturedImageKey"; 23 | NSString *const FBDiffedImageKey = @"FBDiffedImageKey"; 24 | 25 | typedef NS_ENUM(NSUInteger, FBTestSnapshotFileNameType) { 26 | FBTestSnapshotFileNameTypeReference, 27 | FBTestSnapshotFileNameTypeFailedReference, 28 | FBTestSnapshotFileNameTypeFailedTest, 29 | FBTestSnapshotFileNameTypeFailedTestDiff, 30 | }; 31 | 32 | @implementation FBSnapshotTestController 33 | { 34 | NSString *_testName; 35 | NSFileManager *_fileManager; 36 | } 37 | 38 | #pragma mark - Initializers 39 | 40 | - (instancetype)initWithTestClass:(Class)testClass; 41 | { 42 | return [self initWithTestName:NSStringFromClass(testClass)]; 43 | } 44 | 45 | - (instancetype)initWithTestName:(NSString *)testName 46 | { 47 | if (self = [super init]) { 48 | _testName = [testName copy]; 49 | _deviceAgnostic = NO; 50 | 51 | _fileManager = [[NSFileManager alloc] init]; 52 | } 53 | return self; 54 | } 55 | 56 | #pragma mark - Overrides 57 | 58 | - (NSString *)description 59 | { 60 | return [NSString stringWithFormat:@"%@ %@", [super description], _referenceImagesDirectory]; 61 | } 62 | 63 | #pragma mark - Public API 64 | 65 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 66 | selector:(SEL)selector 67 | identifier:(NSString *)identifier 68 | error:(NSError **)errorPtr 69 | { 70 | return [self compareSnapshotOfViewOrLayer:layer 71 | selector:selector 72 | identifier:identifier 73 | tolerance:0 74 | error:errorPtr]; 75 | } 76 | 77 | - (BOOL)compareSnapshotOfView:(UIView *)view 78 | selector:(SEL)selector 79 | identifier:(NSString *)identifier 80 | error:(NSError **)errorPtr 81 | { 82 | return [self compareSnapshotOfViewOrLayer:view 83 | selector:selector 84 | identifier:identifier 85 | tolerance:0 86 | error:errorPtr]; 87 | } 88 | 89 | - (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer 90 | selector:(SEL)selector 91 | identifier:(NSString *)identifier 92 | tolerance:(CGFloat)tolerance 93 | error:(NSError **)errorPtr 94 | { 95 | if (self.recordMode) { 96 | return [self _recordSnapshotOfViewOrLayer:viewOrLayer selector:selector identifier:identifier error:errorPtr]; 97 | } else { 98 | return [self _performPixelComparisonWithViewOrLayer:viewOrLayer selector:selector identifier:identifier tolerance:tolerance error:errorPtr]; 99 | } 100 | } 101 | 102 | - (UIImage *)referenceImageForSelector:(SEL)selector 103 | identifier:(NSString *)identifier 104 | error:(NSError **)errorPtr 105 | { 106 | NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier]; 107 | UIImage *image = [UIImage imageWithContentsOfFile:filePath]; 108 | if (nil == image && NULL != errorPtr) { 109 | BOOL exists = [_fileManager fileExistsAtPath:filePath]; 110 | if (!exists) { 111 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 112 | code:FBSnapshotTestControllerErrorCodeNeedsRecord 113 | userInfo:@{ 114 | FBReferenceImageFilePathKey: filePath, 115 | NSLocalizedDescriptionKey: @"Unable to load reference image.", 116 | NSLocalizedFailureReasonErrorKey: @"Reference image not found. You need to run the test in record mode", 117 | }]; 118 | } else { 119 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 120 | code:FBSnapshotTestControllerErrorCodeUnknown 121 | userInfo:nil]; 122 | } 123 | } 124 | return image; 125 | } 126 | 127 | - (BOOL)compareReferenceImage:(UIImage *)referenceImage 128 | toImage:(UIImage *)image 129 | tolerance:(CGFloat)tolerance 130 | error:(NSError **)errorPtr 131 | { 132 | BOOL sameImageDimensions = CGSizeEqualToSize(referenceImage.size, image.size); 133 | if (sameImageDimensions && [referenceImage fb_compareWithImage:image tolerance:tolerance]) { 134 | return YES; 135 | } 136 | 137 | if (NULL != errorPtr) { 138 | NSString *errorDescription = sameImageDimensions ? @"Images different" : @"Images different sizes"; 139 | NSString *errorReason = sameImageDimensions ? [NSString stringWithFormat:@"image pixels differed by more than %.2f%% from the reference image", tolerance * 100] 140 | : [NSString stringWithFormat:@"referenceImage:%@, image:%@", NSStringFromCGSize(referenceImage.size), NSStringFromCGSize(image.size)]; 141 | FBSnapshotTestControllerErrorCode errorCode = sameImageDimensions ? FBSnapshotTestControllerErrorCodeImagesDifferent : FBSnapshotTestControllerErrorCodeImagesDifferentSizes; 142 | 143 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 144 | code:errorCode 145 | userInfo:@{ 146 | NSLocalizedDescriptionKey: errorDescription, 147 | NSLocalizedFailureReasonErrorKey: errorReason, 148 | FBReferenceImageKey: referenceImage, 149 | FBCapturedImageKey: image, 150 | FBDiffedImageKey: [referenceImage fb_diffWithImage:image], 151 | }]; 152 | } 153 | return NO; 154 | } 155 | 156 | - (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage 157 | testImage:(UIImage *)testImage 158 | selector:(SEL)selector 159 | identifier:(NSString *)identifier 160 | error:(NSError **)errorPtr 161 | { 162 | NSData *referencePNGData = UIImagePNGRepresentation(referenceImage); 163 | NSData *testPNGData = UIImagePNGRepresentation(testImage); 164 | 165 | NSString *referencePath = [self _failedFilePathForSelector:selector 166 | identifier:identifier 167 | fileNameType:FBTestSnapshotFileNameTypeFailedReference]; 168 | 169 | NSError *creationError = nil; 170 | BOOL didCreateDir = [_fileManager createDirectoryAtPath:[referencePath stringByDeletingLastPathComponent] 171 | withIntermediateDirectories:YES 172 | attributes:nil 173 | error:&creationError]; 174 | if (!didCreateDir) { 175 | if (NULL != errorPtr) { 176 | *errorPtr = creationError; 177 | } 178 | return NO; 179 | } 180 | 181 | if (![referencePNGData writeToFile:referencePath options:NSDataWritingAtomic error:errorPtr]) { 182 | return NO; 183 | } 184 | 185 | NSString *testPath = [self _failedFilePathForSelector:selector 186 | identifier:identifier 187 | fileNameType:FBTestSnapshotFileNameTypeFailedTest]; 188 | 189 | if (![testPNGData writeToFile:testPath options:NSDataWritingAtomic error:errorPtr]) { 190 | return NO; 191 | } 192 | 193 | NSString *diffPath = [self _failedFilePathForSelector:selector 194 | identifier:identifier 195 | fileNameType:FBTestSnapshotFileNameTypeFailedTestDiff]; 196 | 197 | UIImage *diffImage = [referenceImage fb_diffWithImage:testImage]; 198 | NSData *diffImageData = UIImagePNGRepresentation(diffImage); 199 | 200 | if (![diffImageData writeToFile:diffPath options:NSDataWritingAtomic error:errorPtr]) { 201 | return NO; 202 | } 203 | 204 | NSLog(@"If you have Kaleidoscope installed you can run this command to see an image diff:\n" 205 | @"ksdiff \"%@\" \"%@\"", referencePath, testPath); 206 | 207 | return YES; 208 | } 209 | 210 | #pragma mark - Private API 211 | 212 | - (NSString *)_fileNameForSelector:(SEL)selector 213 | identifier:(NSString *)identifier 214 | fileNameType:(FBTestSnapshotFileNameType)fileNameType 215 | { 216 | NSString *fileName = nil; 217 | switch (fileNameType) { 218 | case FBTestSnapshotFileNameTypeFailedReference: 219 | fileName = @"reference_"; 220 | break; 221 | case FBTestSnapshotFileNameTypeFailedTest: 222 | fileName = @"failed_"; 223 | break; 224 | case FBTestSnapshotFileNameTypeFailedTestDiff: 225 | fileName = @"diff_"; 226 | break; 227 | default: 228 | fileName = @""; 229 | break; 230 | } 231 | fileName = [fileName stringByAppendingString:NSStringFromSelector(selector)]; 232 | if (0 < identifier.length) { 233 | fileName = [fileName stringByAppendingFormat:@"_%@", identifier]; 234 | } 235 | 236 | if (self.isDeviceAgnostic) { 237 | fileName = FBDeviceAgnosticNormalizedFileName(fileName); 238 | } 239 | 240 | if ([[UIScreen mainScreen] scale] > 1) { 241 | fileName = [fileName stringByAppendingFormat:@"@%.fx", [[UIScreen mainScreen] scale]]; 242 | } 243 | fileName = [fileName stringByAppendingPathExtension:@"png"]; 244 | return fileName; 245 | } 246 | 247 | - (NSString *)_referenceFilePathForSelector:(SEL)selector 248 | identifier:(NSString *)identifier 249 | { 250 | NSString *fileName = [self _fileNameForSelector:selector 251 | identifier:identifier 252 | fileNameType:FBTestSnapshotFileNameTypeReference]; 253 | NSString *filePath = [_referenceImagesDirectory stringByAppendingPathComponent:_testName]; 254 | filePath = [filePath stringByAppendingPathComponent:fileName]; 255 | return filePath; 256 | } 257 | 258 | - (NSString *)_failedFilePathForSelector:(SEL)selector 259 | identifier:(NSString *)identifier 260 | fileNameType:(FBTestSnapshotFileNameType)fileNameType 261 | { 262 | NSString *fileName = [self _fileNameForSelector:selector 263 | identifier:identifier 264 | fileNameType:fileNameType]; 265 | NSString *folderPath = NSTemporaryDirectory(); 266 | if (getenv("IMAGE_DIFF_DIR")) { 267 | folderPath = @(getenv("IMAGE_DIFF_DIR")); 268 | } 269 | NSString *filePath = [folderPath stringByAppendingPathComponent:_testName]; 270 | filePath = [filePath stringByAppendingPathComponent:fileName]; 271 | return filePath; 272 | } 273 | 274 | - (BOOL)_performPixelComparisonWithViewOrLayer:(id)viewOrLayer 275 | selector:(SEL)selector 276 | identifier:(NSString *)identifier 277 | tolerance:(CGFloat)tolerance 278 | error:(NSError **)errorPtr 279 | { 280 | UIImage *referenceImage = [self referenceImageForSelector:selector identifier:identifier error:errorPtr]; 281 | if (nil != referenceImage) { 282 | UIImage *snapshot = [self _imageForViewOrLayer:viewOrLayer]; 283 | BOOL imagesSame = [self compareReferenceImage:referenceImage toImage:snapshot tolerance:tolerance error:errorPtr]; 284 | if (!imagesSame) { 285 | NSError *saveError = nil; 286 | if ([self saveFailedReferenceImage:referenceImage testImage:snapshot selector:selector identifier:identifier error:&saveError] == NO) { 287 | NSLog(@"Error saving test images: %@", saveError); 288 | } 289 | } 290 | return imagesSame; 291 | } 292 | return NO; 293 | } 294 | 295 | - (BOOL)_recordSnapshotOfViewOrLayer:(id)viewOrLayer 296 | selector:(SEL)selector 297 | identifier:(NSString *)identifier 298 | error:(NSError **)errorPtr 299 | { 300 | UIImage *snapshot = [self _imageForViewOrLayer:viewOrLayer]; 301 | return [self _saveReferenceImage:snapshot selector:selector identifier:identifier error:errorPtr]; 302 | } 303 | 304 | - (BOOL)_saveReferenceImage:(UIImage *)image 305 | selector:(SEL)selector 306 | identifier:(NSString *)identifier 307 | error:(NSError **)errorPtr 308 | { 309 | BOOL didWrite = NO; 310 | if (nil != image) { 311 | NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier]; 312 | NSData *pngData = UIImagePNGRepresentation(image); 313 | if (nil != pngData) { 314 | NSError *creationError = nil; 315 | BOOL didCreateDir = [_fileManager createDirectoryAtPath:[filePath stringByDeletingLastPathComponent] 316 | withIntermediateDirectories:YES 317 | attributes:nil 318 | error:&creationError]; 319 | if (!didCreateDir) { 320 | if (NULL != errorPtr) { 321 | *errorPtr = creationError; 322 | } 323 | return NO; 324 | } 325 | didWrite = [pngData writeToFile:filePath options:NSDataWritingAtomic error:errorPtr]; 326 | if (didWrite) { 327 | NSLog(@"Reference image save at: %@", filePath); 328 | } 329 | } else { 330 | if (nil != errorPtr) { 331 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 332 | code:FBSnapshotTestControllerErrorCodePNGCreationFailed 333 | userInfo:@{ 334 | FBReferenceImageFilePathKey: filePath, 335 | }]; 336 | } 337 | } 338 | } 339 | return didWrite; 340 | } 341 | 342 | - (UIImage *)_imageForViewOrLayer:(id)viewOrLayer 343 | { 344 | if ([viewOrLayer isKindOfClass:[UIView class]]) { 345 | if (_usesDrawViewHierarchyInRect) { 346 | return [UIImage fb_imageForView:viewOrLayer]; 347 | } else { 348 | return [UIImage fb_imageForViewLayer:viewOrLayer]; 349 | } 350 | } else if ([viewOrLayer isKindOfClass:[CALayer class]]) { 351 | return [UIImage fb_imageForLayer:viewOrLayer]; 352 | } else { 353 | [NSException raise:@"Only UIView and CALayer classes can be snapshotted" format:@"%@", viewOrLayer]; 354 | } 355 | return nil; 356 | } 357 | 358 | @end 359 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #if swift(>=3) 12 | public extension FBSnapshotTestCase { 13 | public func FBSnapshotVerifyView(_ view: UIView, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 14 | FBSnapshotVerifyViewOrLayer(view, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) 15 | } 16 | 17 | public func FBSnapshotVerifyLayer(_ layer: CALayer, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 18 | FBSnapshotVerifyViewOrLayer(layer, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) 19 | } 20 | 21 | private func FBSnapshotVerifyViewOrLayer(_ viewOrLayer: AnyObject, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 22 | let envReferenceImageDirectory = self.getReferenceImageDirectory(withDefault: FB_REFERENCE_IMAGE_DIR) 23 | var error: NSError? 24 | var comparisonSuccess = false 25 | 26 | if let envReferenceImageDirectory = envReferenceImageDirectory { 27 | for suffix in suffixes { 28 | let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)" 29 | if viewOrLayer.isKind(of: UIView.self) { 30 | do { 31 | try compareSnapshot(of: viewOrLayer as! UIView, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) 32 | comparisonSuccess = true 33 | } catch let error1 as NSError { 34 | error = error1 35 | comparisonSuccess = false 36 | } 37 | } else if viewOrLayer.isKind(of: CALayer.self) { 38 | do { 39 | try compareSnapshot(of: viewOrLayer as! CALayer, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) 40 | comparisonSuccess = true 41 | } catch let error1 as NSError { 42 | error = error1 43 | comparisonSuccess = false 44 | } 45 | } else { 46 | assertionFailure("Only UIView and CALayer classes can be snapshotted") 47 | } 48 | 49 | assert(recordMode == false, message: "Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!", file: file, line: line) 50 | 51 | if comparisonSuccess || recordMode { 52 | break 53 | } 54 | 55 | assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line) 56 | } 57 | } else { 58 | XCTFail("Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.") 59 | } 60 | } 61 | 62 | func assert(_ assertion: Bool, message: String, file: StaticString, line: UInt) { 63 | if !assertion { 64 | XCTFail(message, file: file, line: line) 65 | } 66 | } 67 | } 68 | #else 69 | public extension FBSnapshotTestCase { 70 | public func FBSnapshotVerifyView(view: UIView, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 71 | FBSnapshotVerifyViewOrLayer(view, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) 72 | } 73 | 74 | public func FBSnapshotVerifyLayer(layer: CALayer, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 75 | FBSnapshotVerifyViewOrLayer(layer, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) 76 | } 77 | 78 | private func FBSnapshotVerifyViewOrLayer(viewOrLayer: AnyObject, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 79 | let envReferenceImageDirectory = self.getReferenceImageDirectoryWithDefault(FB_REFERENCE_IMAGE_DIR) 80 | var error: NSError? 81 | var comparisonSuccess = false 82 | 83 | if let envReferenceImageDirectory = envReferenceImageDirectory { 84 | for suffix in suffixes { 85 | let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)" 86 | if viewOrLayer.isKindOfClass(UIView) { 87 | do { 88 | try compareSnapshotOfView(viewOrLayer as! UIView, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) 89 | comparisonSuccess = true 90 | } catch let error1 as NSError { 91 | error = error1 92 | comparisonSuccess = false 93 | } 94 | } else if viewOrLayer.isKindOfClass(CALayer) { 95 | do { 96 | try compareSnapshotOfLayer(viewOrLayer as! CALayer, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) 97 | comparisonSuccess = true 98 | } catch let error1 as NSError { 99 | error = error1 100 | comparisonSuccess = false 101 | } 102 | } else { 103 | assertionFailure("Only UIView and CALayer classes can be snapshotted") 104 | } 105 | 106 | assert(recordMode == false, message: "Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!", file: file, line: line) 107 | 108 | if comparisonSuccess || recordMode { 109 | break 110 | } 111 | 112 | assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line) 113 | } 114 | } else { 115 | XCTFail("Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.") 116 | } 117 | } 118 | 119 | func assert(assertion: Bool, message: String, file: StaticString, line: UInt) { 120 | if !assertion { 121 | XCTFail(message, file: file, line: line) 122 | } 123 | } 124 | } 125 | #endif 126 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For the FBSnapshotTestCase software 4 | 5 | Copyright (c) 2013, Facebook, Inc. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | * Neither the name Facebook nor the names of its contributors may be used to 17 | endorse or promote products derived from this software without specific 18 | prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/README.md: -------------------------------------------------------------------------------- 1 | FBSnapshotTestCase 2 | ====================== 3 | 4 | [![Build Status](https://travis-ci.org/facebook/ios-snapshot-test-case.svg)](https://travis-ci.org/facebook/ios-snapshot-test-case) [![Cocoa Pod Version](https://cocoapod-badges.herokuapp.com/v/FBSnapshotTestCase/badge.svg)](http://cocoadocs.org/docsets/FBSnapshotTestCase/) 5 | 6 | What it does 7 | ------------ 8 | 9 | A "snapshot test case" takes a configured `UIView` or `CALayer` and uses the 10 | `renderInContext:` method to get an image snapshot of its contents. It 11 | compares this snapshot to a "reference image" stored in your source code 12 | repository and fails the test if the two images don't match. 13 | 14 | Why? 15 | ---- 16 | 17 | At Facebook we write a lot of UI code. As you might imagine, each type of 18 | feed story is rendered using a subclass of `UIView`. There are a lot of edge 19 | cases that we want to handle correctly: 20 | 21 | - What if there is more text than can fit in the space available? 22 | - What if an image doesn't match the size of an image view? 23 | - What should the highlighted state look like? 24 | 25 | It's straightforward to test logic code, but less obvious how you should test 26 | views. You can do a lot of rectangle asserts, but these are hard to understand 27 | or visualize. Looking at an image diff shows you exactly what changed and how 28 | it will look to users. 29 | 30 | We developed `FBSnapshotTestCase` to make snapshot tests easy. 31 | 32 | Installation with CocoaPods 33 | --------------------------- 34 | 35 | 1. Add the following lines to your Podfile: 36 | 37 | ``` 38 | target "Tests" do 39 | pod 'FBSnapshotTestCase' 40 | end 41 | ``` 42 | 43 | If you support iOS 7 use `FBSnapshotTestCase/Core` instead, which doesn't contain Swift support. 44 | 45 | Replace "Tests" with the name of your test project. 46 | 47 | 2. There are [three ways](https://github.com/facebook/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/FBSnapshotTestCase.h#L19-L29) of setting reference image directories, the recommended one is to define `FB_REFERENCE_IMAGE_DIR` in your scheme. This should point to the directory where you want reference images to be stored. At Facebook, we normally use this: 48 | 49 | |Name|Value| 50 | |:---|:----| 51 | |`FB_REFERENCE_IMAGE_DIR`|`$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages`| 52 | 53 | 54 | ![](FBSnapshotTestCaseDemo/Scheme_FB_REFERENCE_IMAGE_DIR.png) 55 | 56 | Creating a snapshot test 57 | ------------------------ 58 | 59 | 1. Subclass `FBSnapshotTestCase` instead of `XCTestCase`. 60 | 2. From within your test, use `FBSnapshotVerifyView`. 61 | 3. Run the test once with `self.recordMode = YES;` in the test's `-setUp` 62 | method. (This creates the reference images on disk.) 63 | 4. Remove the line enabling record mode and run the test. 64 | 65 | Features 66 | -------- 67 | 68 | - Automatically names reference images on disk according to test class and 69 | selector. 70 | - Prints a descriptive error message to the console on failure. (Bonus: 71 | failure message includes a one-line command to see an image diff if 72 | you have [Kaleidoscope](http://www.kaleidoscopeapp.com) installed.) 73 | - Supply an optional "identifier" if you want to perform multiple snapshots 74 | in a single test method. 75 | - Support for `CALayer` via `FBSnapshotVerifyLayer`. 76 | - `usesDrawViewHierarchyInRect` to handle cases like `UIVisualEffect`, `UIAppearance` and Size Classes. 77 | - `isDeviceAgnostic` to allow appending the device model (`iPhone`, `iPad`, `iPod Touch`, etc), OS version and screen size to the images (allowing to have multiple tests for the same «snapshot» for different `OS`s and devices). 78 | 79 | Notes 80 | ----- 81 | 82 | Your unit test must be an "application test", not a "logic test." (That is, it 83 | must be run within the Simulator so that it has access to UIKit.) In Xcode 5 84 | and later new projects only offer application tests, but older projects will 85 | have separate targets for the two types. 86 | 87 | Authors 88 | ------- 89 | 90 | `FBSnapshotTestCase` was written at Facebook by 91 | [Jonathan Dann](https://facebook.com/j.p.dann) with significant contributions by 92 | [Todd Krabach](https://facebook.com/toddkrabach). 93 | 94 | License 95 | ------- 96 | 97 | `FBSnapshotTestCase` is BSD-licensed. See `LICENSE`. 98 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/WSProgressHUD.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WSProgressHUD", 3 | "version": "1.1.5", 4 | "summary": "WSProgressHUD is a beauful hud view for iPhone & iPad.", 5 | "description": "WSProgressHUD is a beauful hud view for iPhone & iPad. you can simple to use it.\n\n* Think: Why did you write this? What is the focus? What does it do?\n* CocoaPods will be using this to generate tags, and improve search results.\n* Try to keep it short, snappy and to the point.\n* Finally, don't worry about the indent, CocoaPods strips it", 6 | "homepage": "https://github.com/devSC/WSProgressHUD", 7 | "screenshots": "https://raw.githubusercontent.com/devSC/WSProgressHUD/master/Demo/Demo.gif", 8 | "license": "MIT", 9 | "authors": { 10 | "袁仕崇": "xiaochong2154@163.com" 11 | }, 12 | "platforms": { 13 | "ios": "6.0" 14 | }, 15 | "source": { 16 | "git": "https://github.com/devSC/WSProgressHUD.git", 17 | "tag": "1.1.5" 18 | }, 19 | "source_files": "WSProgressHUD/Classes/**/*", 20 | "exclude_files": "Demo/Exclude", 21 | "resource_bundles": { 22 | "WSProgressHUD": [ 23 | "WSProgressHUD/Assets/*.png" 24 | ] 25 | }, 26 | "frameworks": [ 27 | "UIKit", 28 | "QuartzCore", 29 | "CoreGraphics", 30 | "Foundation" 31 | ], 32 | "requires_arc": true, 33 | "dependencies": { 34 | "Shimmer": [ 35 | 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FBSnapshotTestCase (2.1.4): 3 | - FBSnapshotTestCase/SwiftSupport (= 2.1.4) 4 | - FBSnapshotTestCase/Core (2.1.4) 5 | - FBSnapshotTestCase/SwiftSupport (2.1.4): 6 | - FBSnapshotTestCase/Core 7 | - Shimmer (1.0.2) 8 | - WSProgressHUD (1.1.5): 9 | - Shimmer 10 | 11 | DEPENDENCIES: 12 | - FBSnapshotTestCase 13 | - WSProgressHUD (from `../`) 14 | 15 | SPEC REPOS: 16 | https://github.com/cocoapods/specs.git: 17 | - FBSnapshotTestCase 18 | - Shimmer 19 | 20 | EXTERNAL SOURCES: 21 | WSProgressHUD: 22 | :path: "../" 23 | 24 | SPEC CHECKSUMS: 25 | FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a 26 | Shimmer: c5374be1c2b0c9e292fb05b339a513cf291cac86 27 | WSProgressHUD: d66881ecb218926f7da320ae36b3426c2ef8d912 28 | 29 | PODFILE CHECKSUM: ab589241c2f3bd950585aebd9abd37de1a2541ed 30 | 31 | COCOAPODS: 1.5.3 32 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/FBShimmering/FBShimmering.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | typedef NS_ENUM(NSInteger, FBShimmerDirection) { 13 | FBShimmerDirectionRight, // Shimmer animation goes from left to right 14 | FBShimmerDirectionLeft, // Shimmer animation goes from right to left 15 | FBShimmerDirectionUp, // Shimmer animation goes from below to above 16 | FBShimmerDirectionDown, // Shimmer animation goes from above to below 17 | }; 18 | 19 | @protocol FBShimmering 20 | 21 | //! @abstract Set this to YES to start shimming and NO to stop. Defaults to NO. 22 | @property (nonatomic, assign, readwrite, getter = isShimmering) BOOL shimmering; 23 | 24 | //! @abstract The time interval between shimmerings in seconds. Defaults to 0.4. 25 | @property (assign, nonatomic, readwrite) CFTimeInterval shimmeringPauseDuration; 26 | 27 | //! @abstract The opacity of the content while it is shimmering. Defaults to 1.0. 28 | @property (assign, nonatomic, readwrite) CGFloat shimmeringAnimationOpacity; 29 | 30 | //! @abstract The opacity of the content before it is shimmering. Defaults to 0.5. 31 | @property (assign, nonatomic, readwrite) CGFloat shimmeringOpacity; 32 | 33 | //! @abstract The speed of shimmering, in points per second. Defaults to 230. 34 | @property (assign, nonatomic, readwrite) CGFloat shimmeringSpeed; 35 | 36 | //! @abstract The highlight length of shimmering. Range of [0,1], defaults to 0.33. 37 | @property (assign, nonatomic, readwrite) CGFloat shimmeringHighlightLength; 38 | 39 | //! @abstract @deprecated Same as "shimmeringHighlightLength", just for downward compatibility 40 | @property (assign, nonatomic, readwrite, getter = shimmeringHighlightLength, setter = setShimmeringHighlightLength:) CGFloat shimmeringHighlightWidth; 41 | 42 | //! @abstract The direction of shimmering animation. Defaults to FBShimmerDirectionRight. 43 | @property (assign, nonatomic, readwrite) FBShimmerDirection shimmeringDirection; 44 | 45 | //! @abstract The duration of the fade used when shimmer begins. Defaults to 0.1. 46 | @property (assign, nonatomic, readwrite) CFTimeInterval shimmeringBeginFadeDuration; 47 | 48 | //! @abstract The duration of the fade used when shimmer ends. Defaults to 0.3. 49 | @property (assign, nonatomic, readwrite) CFTimeInterval shimmeringEndFadeDuration; 50 | 51 | /** 52 | @abstract The absolute CoreAnimation media time when the shimmer will fade in. 53 | @discussion Only valid after setting {@ref shimmering} to NO. 54 | */ 55 | @property (assign, nonatomic, readonly) CFTimeInterval shimmeringFadeTime; 56 | 57 | @end 58 | 59 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/FBShimmering/FBShimmeringLayer.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "FBShimmering.h" 13 | 14 | /** 15 | @abstract Lightweight, generic shimmering layer. 16 | */ 17 | @interface FBShimmeringLayer : CALayer 18 | 19 | //! @abstract The content layer to be shimmered. 20 | @property (strong, nonatomic) CALayer *contentLayer; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/FBShimmering/FBShimmeringLayer.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "FBShimmeringLayer.h" 11 | 12 | #import 13 | #import 14 | #import 15 | 16 | #import 17 | #import 18 | 19 | #if !__has_feature(objc_arc) 20 | #error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag. 21 | #endif 22 | 23 | #if TARGET_IPHONE_SIMULATOR 24 | UIKIT_EXTERN float UIAnimationDragCoefficient(void); // UIKit private drag coeffient, use judiciously 25 | #endif 26 | 27 | static CGFloat FBShimmeringLayerDragCoefficient(void) 28 | { 29 | #if TARGET_IPHONE_SIMULATOR 30 | return UIAnimationDragCoefficient(); 31 | #else 32 | return 1.0; 33 | #endif 34 | } 35 | 36 | static void FBShimmeringLayerAnimationApplyDragCoefficient(CAAnimation *animation) 37 | { 38 | CGFloat k = FBShimmeringLayerDragCoefficient(); 39 | 40 | if (k != 0 && k != 1) { 41 | animation.speed = 1 / k; 42 | } 43 | } 44 | 45 | // animations keys 46 | static NSString *const kFBShimmerSlideAnimationKey = @"slide"; 47 | static NSString *const kFBFadeAnimationKey = @"fade"; 48 | static NSString *const kFBEndFadeAnimationKey = @"fade-end"; 49 | 50 | static CABasicAnimation *fade_animation(id delegate, CALayer *layer, CGFloat opacity, CFTimeInterval duration) 51 | { 52 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 53 | animation.delegate = delegate; 54 | animation.fromValue = @([(layer.presentationLayer ?: layer) opacity]); 55 | animation.toValue = @(opacity); 56 | animation.fillMode = kCAFillModeBoth; 57 | animation.removedOnCompletion = NO; 58 | animation.duration = duration; 59 | FBShimmeringLayerAnimationApplyDragCoefficient(animation); 60 | return animation; 61 | } 62 | 63 | static CABasicAnimation *shimmer_begin_fade_animation(id delegate, CALayer *layer, CGFloat opacity, CGFloat duration) 64 | { 65 | return fade_animation(delegate, layer, opacity, duration); 66 | } 67 | 68 | static CABasicAnimation *shimmer_end_fade_animation(id delegate, CALayer *layer, CGFloat opacity, CGFloat duration) 69 | { 70 | CABasicAnimation *animation = fade_animation(delegate, layer, opacity, duration); 71 | [animation setValue:@YES forKey:kFBEndFadeAnimationKey]; 72 | return animation; 73 | } 74 | 75 | static CABasicAnimation *shimmer_slide_animation(id delegate, CFTimeInterval duration, FBShimmerDirection direction) 76 | { 77 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; 78 | animation.delegate = delegate; 79 | animation.toValue = [NSValue valueWithCGPoint:CGPointZero]; 80 | animation.duration = duration; 81 | animation.repeatCount = HUGE_VALF; 82 | FBShimmeringLayerAnimationApplyDragCoefficient(animation); 83 | if (direction == FBShimmerDirectionLeft || 84 | direction == FBShimmerDirectionUp) { 85 | animation.speed = -fabsf(animation.speed); 86 | } 87 | return animation; 88 | } 89 | 90 | // take a shimmer slide animation and turns into repeating 91 | static CAAnimation *shimmer_slide_repeat(CAAnimation *a, CFTimeInterval duration, FBShimmerDirection direction) 92 | { 93 | CAAnimation *anim = [a copy]; 94 | anim.repeatCount = HUGE_VALF; 95 | anim.duration = duration; 96 | anim.speed = (direction == FBShimmerDirectionRight || direction == FBShimmerDirectionDown) ? fabsf(anim.speed) : -fabsf(anim.speed); 97 | return anim; 98 | } 99 | 100 | // take a shimmer slide animation and turns into finish 101 | static CAAnimation *shimmer_slide_finish(CAAnimation *a) 102 | { 103 | CAAnimation *anim = [a copy]; 104 | anim.repeatCount = 0; 105 | return anim; 106 | } 107 | 108 | @interface FBShimmeringMaskLayer : CAGradientLayer 109 | @property (readonly, nonatomic) CALayer *fadeLayer; 110 | @end 111 | 112 | @implementation FBShimmeringMaskLayer 113 | 114 | - (instancetype)init 115 | { 116 | self = [super init]; 117 | if (nil != self) { 118 | _fadeLayer = [[CALayer alloc] init]; 119 | _fadeLayer.backgroundColor = [UIColor whiteColor].CGColor; 120 | [self addSublayer:_fadeLayer]; 121 | } 122 | return self; 123 | } 124 | 125 | - (void)layoutSublayers 126 | { 127 | [super layoutSublayers]; 128 | CGRect r = self.bounds; 129 | _fadeLayer.bounds = r; 130 | _fadeLayer.position = CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r)); 131 | } 132 | 133 | @end 134 | 135 | @interface FBShimmeringLayer () 136 | @property (strong, nonatomic) FBShimmeringMaskLayer *maskLayer; 137 | @end 138 | 139 | @implementation FBShimmeringLayer 140 | { 141 | CALayer *_contentLayer; 142 | FBShimmeringMaskLayer *_maskLayer; 143 | } 144 | 145 | #pragma mark - Lifecycle 146 | 147 | @synthesize shimmering = _shimmering; 148 | @synthesize shimmeringPauseDuration = _shimmeringPauseDuration; 149 | @synthesize shimmeringAnimationOpacity = _shimmeringAnimationOpacity; 150 | @synthesize shimmeringOpacity = _shimmeringOpacity; 151 | @synthesize shimmeringSpeed = _shimmeringSpeed; 152 | @synthesize shimmeringHighlightLength = _shimmeringHighlightLength; 153 | @synthesize shimmeringDirection = _shimmeringDirection; 154 | @synthesize shimmeringFadeTime = _shimmeringFadeTime; 155 | @synthesize shimmeringBeginFadeDuration = _shimmeringBeginFadeDuration; 156 | @synthesize shimmeringEndFadeDuration = _shimmeringEndFadeDuration; 157 | @dynamic shimmeringHighlightWidth; 158 | 159 | - (instancetype)init 160 | { 161 | self = [super init]; 162 | if (nil != self) { 163 | // default configuration 164 | _shimmeringPauseDuration = 0.4; 165 | _shimmeringSpeed = 230.0; 166 | _shimmeringHighlightLength = 1.0; 167 | _shimmeringAnimationOpacity = 0.5; 168 | _shimmeringOpacity = 1.0; 169 | _shimmeringDirection = FBShimmerDirectionRight; 170 | _shimmeringBeginFadeDuration = 0.1; 171 | _shimmeringEndFadeDuration = 0.3; 172 | } 173 | return self; 174 | } 175 | 176 | #pragma mark - Properties 177 | 178 | - (void)setContentLayer:(CALayer *)contentLayer 179 | { 180 | // reset mask 181 | self.maskLayer = nil; 182 | 183 | // note content layer and add for display 184 | _contentLayer = contentLayer; 185 | self.sublayers = contentLayer ? @[contentLayer] : nil; 186 | 187 | // update shimmering animation 188 | [self _updateShimmering]; 189 | } 190 | 191 | - (void)setShimmering:(BOOL)shimmering 192 | { 193 | if (shimmering != _shimmering) { 194 | _shimmering = shimmering; 195 | [self _updateShimmering]; 196 | } 197 | } 198 | 199 | - (void)setShimmeringSpeed:(CGFloat)speed 200 | { 201 | if (speed != _shimmeringSpeed) { 202 | _shimmeringSpeed = speed; 203 | [self _updateShimmering]; 204 | } 205 | } 206 | 207 | - (void)setShimmeringHighlightLength:(CGFloat)length 208 | { 209 | if (length != _shimmeringHighlightLength) { 210 | _shimmeringHighlightLength = length; 211 | [self _updateShimmering]; 212 | } 213 | } 214 | 215 | - (void)setShimmeringDirection:(FBShimmerDirection)direction 216 | { 217 | if (direction != _shimmeringDirection) { 218 | _shimmeringDirection = direction; 219 | [self _updateShimmering]; 220 | } 221 | } 222 | 223 | - (void)setShimmeringPauseDuration:(CFTimeInterval)duration 224 | { 225 | if (duration != _shimmeringPauseDuration) { 226 | _shimmeringPauseDuration = duration; 227 | [self _updateShimmering]; 228 | } 229 | } 230 | 231 | - (void)setShimmeringAnimationOpacity:(CGFloat)shimmeringAnimationOpacity 232 | { 233 | if (shimmeringAnimationOpacity != _shimmeringAnimationOpacity) { 234 | _shimmeringAnimationOpacity = shimmeringAnimationOpacity; 235 | [self _updateMaskColors]; 236 | } 237 | } 238 | 239 | - (void)setShimmeringOpacity:(CGFloat)shimmeringOpacity 240 | { 241 | if (shimmeringOpacity != _shimmeringOpacity) { 242 | _shimmeringOpacity = shimmeringOpacity; 243 | [self _updateMaskColors]; 244 | } 245 | } 246 | 247 | - (void)layoutSublayers 248 | { 249 | [super layoutSublayers]; 250 | CGRect r = self.bounds; 251 | _contentLayer.anchorPoint = CGPointMake(0.5, 0.5); 252 | _contentLayer.bounds = r; 253 | _contentLayer.position = CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r)); 254 | 255 | if (nil != _maskLayer) { 256 | [self _updateMaskLayout]; 257 | } 258 | } 259 | 260 | - (void)setBounds:(CGRect)bounds 261 | { 262 | if (!CGRectEqualToRect(self.bounds, bounds)) { 263 | [super setBounds:bounds]; 264 | 265 | [self _updateShimmering]; 266 | } 267 | } 268 | 269 | #pragma mark - Internal 270 | 271 | - (void)_clearMask 272 | { 273 | if (nil == _maskLayer) { 274 | return; 275 | } 276 | 277 | BOOL disableActions = [CATransaction disableActions]; 278 | [CATransaction setDisableActions:YES]; 279 | 280 | self.maskLayer = nil; 281 | _contentLayer.mask = nil; 282 | 283 | [CATransaction setDisableActions:disableActions]; 284 | } 285 | 286 | - (void)_createMaskIfNeeded 287 | { 288 | if (_shimmering && !_maskLayer) { 289 | _maskLayer = [FBShimmeringMaskLayer layer]; 290 | _maskLayer.delegate = self; 291 | _contentLayer.mask = _maskLayer; 292 | [self _updateMaskColors]; 293 | [self _updateMaskLayout]; 294 | } 295 | } 296 | 297 | - (void)_updateMaskColors 298 | { 299 | if (nil == _maskLayer) { 300 | return; 301 | } 302 | 303 | // We create a gradient to be used as a mask. 304 | // In a mask, the colors do not matter, it's the alpha that decides the degree of masking. 305 | UIColor *maskedColor = [UIColor colorWithWhite:1.0 alpha:_shimmeringOpacity]; 306 | UIColor *unmaskedColor = [UIColor colorWithWhite:1.0 alpha:_shimmeringAnimationOpacity]; 307 | 308 | // Create a gradient from masked to unmasked to masked. 309 | _maskLayer.colors = @[(__bridge id)maskedColor.CGColor, (__bridge id)unmaskedColor.CGColor, (__bridge id)maskedColor.CGColor]; 310 | } 311 | 312 | - (void)_updateMaskLayout 313 | { 314 | // Everything outside the mask layer is hidden, so we need to create a mask long enough for the shimmered layer to be always covered by the mask. 315 | CGFloat length = 0.0f; 316 | if (_shimmeringDirection == FBShimmerDirectionDown || 317 | _shimmeringDirection == FBShimmerDirectionUp) { 318 | length = CGRectGetHeight(_contentLayer.bounds); 319 | } else { 320 | length = CGRectGetWidth(_contentLayer.bounds); 321 | } 322 | if (0 == length) { 323 | return; 324 | } 325 | 326 | // extra distance for the gradient to travel during the pause. 327 | CGFloat extraDistance = length + _shimmeringSpeed * _shimmeringPauseDuration; 328 | 329 | // compute how far the shimmering goes 330 | CGFloat fullShimmerLength = length * 3.0f + extraDistance; 331 | CGFloat travelDistance = length * 2.0f + extraDistance; 332 | 333 | // position the gradient for the desired width 334 | CGFloat highlightOutsideLength = (1.0 - _shimmeringHighlightLength) / 2.0; 335 | _maskLayer.locations = @[@(highlightOutsideLength), 336 | @(0.5), 337 | @(1.0 - highlightOutsideLength)]; 338 | 339 | CGFloat startPoint = (length + extraDistance) / fullShimmerLength; 340 | CGFloat endPoint = travelDistance / fullShimmerLength; 341 | 342 | // position for the start of the animation 343 | _maskLayer.anchorPoint = CGPointZero; 344 | if (_shimmeringDirection == FBShimmerDirectionDown || 345 | _shimmeringDirection == FBShimmerDirectionUp) { 346 | _maskLayer.startPoint = CGPointMake(0.0, startPoint); 347 | _maskLayer.endPoint = CGPointMake(0.0, endPoint); 348 | _maskLayer.position = CGPointMake(0.0, -travelDistance); 349 | _maskLayer.bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_contentLayer.bounds), fullShimmerLength); 350 | } else { 351 | _maskLayer.startPoint = CGPointMake(startPoint, 0.0); 352 | _maskLayer.endPoint = CGPointMake(endPoint, 0.0); 353 | _maskLayer.position = CGPointMake(-travelDistance, 0.0); 354 | _maskLayer.bounds = CGRectMake(0.0, 0.0, fullShimmerLength, CGRectGetHeight(_contentLayer.bounds)); 355 | } 356 | } 357 | 358 | - (void)_updateShimmering 359 | { 360 | // create mask if needed 361 | [self _createMaskIfNeeded]; 362 | 363 | // if not shimmering and no mask, noop 364 | if (!_shimmering && !_maskLayer) { 365 | return; 366 | } 367 | 368 | // ensure layed out 369 | [self layoutIfNeeded]; 370 | 371 | BOOL disableActions = [CATransaction disableActions]; 372 | if (!_shimmering) { 373 | if (disableActions) { 374 | // simply remove mask 375 | [self _clearMask]; 376 | } else { 377 | // end slide 378 | CFTimeInterval slideEndTime = 0; 379 | 380 | CAAnimation *slideAnimation = [_maskLayer animationForKey:kFBShimmerSlideAnimationKey]; 381 | if (slideAnimation != nil) { 382 | // determing total time sliding 383 | CFTimeInterval now = CACurrentMediaTime(); 384 | CFTimeInterval slideTotalDuration = now - slideAnimation.beginTime; 385 | 386 | // determine time offset into current slide 387 | CFTimeInterval slideTimeOffset = fmod(slideTotalDuration, slideAnimation.duration); 388 | 389 | // transition to non-repeating slide 390 | CAAnimation *finishAnimation = shimmer_slide_finish(slideAnimation); 391 | 392 | // adjust begin time to now - offset 393 | finishAnimation.beginTime = now - slideTimeOffset; 394 | 395 | // note slide end time and begin 396 | slideEndTime = finishAnimation.beginTime + slideAnimation.duration; 397 | [_maskLayer addAnimation:finishAnimation forKey:kFBShimmerSlideAnimationKey]; 398 | } 399 | 400 | // fade in text at slideEndTime 401 | CABasicAnimation *fadeInAnimation = shimmer_end_fade_animation(self, _maskLayer.fadeLayer, 1.0, _shimmeringEndFadeDuration); 402 | fadeInAnimation.beginTime = slideEndTime; 403 | [_maskLayer.fadeLayer addAnimation:fadeInAnimation forKey:kFBFadeAnimationKey]; 404 | 405 | // expose end time for synchronization 406 | _shimmeringFadeTime = slideEndTime; 407 | } 408 | } else { 409 | // fade out text, optionally animated 410 | CABasicAnimation *fadeOutAnimation = nil; 411 | if (_shimmeringBeginFadeDuration > 0.0 && !disableActions) { 412 | fadeOutAnimation = shimmer_begin_fade_animation(self, _maskLayer.fadeLayer, 0.0, _shimmeringBeginFadeDuration); 413 | [_maskLayer.fadeLayer addAnimation:fadeOutAnimation forKey:kFBFadeAnimationKey]; 414 | } else { 415 | BOOL innerDisableActions = [CATransaction disableActions]; 416 | [CATransaction setDisableActions:YES]; 417 | 418 | _maskLayer.fadeLayer.opacity = 0.0; 419 | [_maskLayer.fadeLayer removeAllAnimations]; 420 | 421 | [CATransaction setDisableActions:innerDisableActions]; 422 | } 423 | 424 | // begin slide animation 425 | CAAnimation *slideAnimation = [_maskLayer animationForKey:kFBShimmerSlideAnimationKey]; 426 | 427 | // compute shimmer duration 428 | CGFloat length = 0.0f; 429 | if (_shimmeringDirection == FBShimmerDirectionDown || 430 | _shimmeringDirection == FBShimmerDirectionUp) { 431 | length = CGRectGetHeight(_contentLayer.bounds); 432 | } else { 433 | length = CGRectGetWidth(_contentLayer.bounds); 434 | } 435 | CFTimeInterval animationDuration = (length / _shimmeringSpeed) + _shimmeringPauseDuration; 436 | 437 | if (slideAnimation != nil) { 438 | // ensure existing slide animation repeats 439 | [_maskLayer addAnimation:shimmer_slide_repeat(slideAnimation, animationDuration, _shimmeringDirection) forKey:kFBShimmerSlideAnimationKey]; 440 | } else { 441 | // add slide animation 442 | slideAnimation = shimmer_slide_animation(self, animationDuration, _shimmeringDirection); 443 | slideAnimation.fillMode = kCAFillModeForwards; 444 | slideAnimation.removedOnCompletion = NO; 445 | slideAnimation.beginTime = CACurrentMediaTime() + fadeOutAnimation.duration; 446 | [_maskLayer addAnimation:slideAnimation forKey:kFBShimmerSlideAnimationKey]; 447 | } 448 | } 449 | } 450 | 451 | #pragma mark - CALayerDelegate 452 | 453 | - (id)actionForLayer:(CALayer *)layer forKey:(NSString *)event 454 | { 455 | // no associated actions 456 | return (id)kCFNull; 457 | } 458 | 459 | #pragma mark - CAAnimationDelegate 460 | 461 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 462 | { 463 | if (flag && [[anim valueForKey:kFBEndFadeAnimationKey] boolValue]) { 464 | [self _clearMask]; 465 | } 466 | } 467 | 468 | @end 469 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/FBShimmering/FBShimmeringView.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "FBShimmering.h" 13 | 14 | /** 15 | @abstract Lightweight, generic shimmering view. 16 | */ 17 | @interface FBShimmeringView : UIView 18 | 19 | //! @abstract The content view to be shimmered. 20 | @property (strong, nonatomic) UIView *contentView; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/FBShimmering/FBShimmeringView.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "FBShimmeringView.h" 11 | 12 | #import "FBShimmeringLayer.h" 13 | 14 | #if !__has_feature(objc_arc) 15 | #error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag. 16 | #endif 17 | 18 | @implementation FBShimmeringView 19 | 20 | + (Class)layerClass 21 | { 22 | return [FBShimmeringLayer class]; 23 | } 24 | 25 | #define __layer ((FBShimmeringLayer *)self.layer) 26 | 27 | #define LAYER_ACCESSOR(accessor, ctype) \ 28 | - (ctype)accessor { \ 29 | return [__layer accessor]; \ 30 | } 31 | 32 | #define LAYER_MUTATOR(mutator, ctype) \ 33 | - (void)mutator (ctype)value { \ 34 | [__layer mutator value]; \ 35 | } 36 | 37 | #define LAYER_RW_PROPERTY(accessor, mutator, ctype) \ 38 | LAYER_ACCESSOR (accessor, ctype) \ 39 | LAYER_MUTATOR (mutator, ctype) 40 | 41 | LAYER_RW_PROPERTY(isShimmering, setShimmering:, BOOL) 42 | LAYER_RW_PROPERTY(shimmeringPauseDuration, setShimmeringPauseDuration:, CFTimeInterval) 43 | LAYER_RW_PROPERTY(shimmeringAnimationOpacity, setShimmeringAnimationOpacity:, CGFloat) 44 | LAYER_RW_PROPERTY(shimmeringOpacity, setShimmeringOpacity:, CGFloat) 45 | LAYER_RW_PROPERTY(shimmeringSpeed, setShimmeringSpeed:, CGFloat) 46 | LAYER_RW_PROPERTY(shimmeringHighlightLength, setShimmeringHighlightLength:, CGFloat) 47 | LAYER_RW_PROPERTY(shimmeringDirection, setShimmeringDirection:, FBShimmerDirection) 48 | LAYER_ACCESSOR(shimmeringFadeTime, CFTimeInterval) 49 | LAYER_RW_PROPERTY(shimmeringBeginFadeDuration, setShimmeringBeginFadeDuration:, CFTimeInterval) 50 | LAYER_RW_PROPERTY(shimmeringEndFadeDuration, setShimmeringEndFadeDuration:, CFTimeInterval) 51 | 52 | - (void)setContentView:(UIView *)contentView 53 | { 54 | if (contentView != _contentView) { 55 | _contentView = contentView; 56 | [self addSubview:contentView]; 57 | __layer.contentLayer = contentView.layer; 58 | } 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For Shimmer software 4 | 5 | Copyright (c) 2014, Facebook, Inc. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name Facebook nor the names of its contributors may be used to 18 | endorse or promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /Example/Pods/Shimmer/README.md: -------------------------------------------------------------------------------- 1 | # Shimmer 2 | Shimmer is an easy way to add a shimmering effect to any view in your app. It's useful as an unobtrusive loading indicator. 3 | 4 | Shimmer was originally developed to show loading status in [Paper](http://facebook.com/paper). 5 | 6 | ![Shimmer](https://github.com/facebook/Shimmer/blob/master/shimmer.gif?raw=true) 7 | 8 | ## Usage 9 | To use Shimmer, create a `FBShimmeringView` or `FBShimmeringLayer` and add your content. To start shimmering, set the `shimmering` property to `YES`. 10 | 11 | An example of making a label shimmer: 12 | 13 | ```objective-c 14 | FBShimmeringView *shimmeringView = [[FBShimmeringView alloc] initWithFrame:self.view.bounds]; 15 | [self.view addSubview:shimmeringView]; 16 | 17 | UILabel *loadingLabel = [[UILabel alloc] initWithFrame:shimmeringView.bounds]; 18 | loadingLabel.textAlignment = NSTextAlignmentCenter; 19 | loadingLabel.text = NSLocalizedString(@"Shimmer", nil); 20 | shimmeringView.contentView = loadingLabel; 21 | 22 | // Start shimmering. 23 | shimmeringView.shimmering = YES; 24 | ``` 25 | 26 | There's also an example project. In the example, you can swipe horizontally and vertically to try various shimmering parameters, or tap to start or stop shimmering. (To build the example locally, you'll need to open `FBShimmering.xcworkpace` rather than the `.xcodeproj`.) 27 | 28 | ## Installation 29 | There are two options: 30 | 31 | 1. Shimmer is available as `Shimmer` in [Cocoapods](http://cocoapods.org). 32 | 2. Manually add the files into your Xcode project. Slightly simpler, but updates are also manual. 33 | 34 | Shimmer requires iOS 6 or later. 35 | 36 | ## How it works 37 | Shimmer uses the `-[CALayer mask]` property to enable shimmering, similar to what's described in John Harper's 2009 WWDC talk (unfortunately no longer online). Shimmer uses CoreAnimation's timing features to smoothly transition "on-beat" when starting and stopping the shimmer. 38 | 39 | ## Contributing 40 | See the CONTRIBUTING file for how to help out. 41 | 42 | ## License 43 | Shimmer is BSD-licensed. We also provide an additional patent grant. 44 | 45 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_FBSnapshotTestCase : NSObject 3 | @end 4 | @implementation PodsDummy_FBSnapshotTestCase 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-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/FBSnapshotTestCase/FBSnapshotTestCase-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 "FBSnapshotTestCase.h" 14 | #import "FBSnapshotTestCasePlatform.h" 15 | #import "FBSnapshotTestController.h" 16 | 17 | FOUNDATION_EXPORT double FBSnapshotTestCaseVersionNumber; 18 | FOUNDATION_EXPORT const unsigned char FBSnapshotTestCaseVersionString[]; 19 | 20 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap: -------------------------------------------------------------------------------- 1 | framework module FBSnapshotTestCase { 2 | umbrella header "FBSnapshotTestCase-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase 2 | ENABLE_BITCODE = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_LDFLAGS = -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSnapshotTestCase 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/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 | 2.1.4 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_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-WSProgressHUD_Example/Pods-WSProgressHUD_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Shimmer 5 | 6 | BSD License 7 | 8 | For Shimmer software 9 | 10 | Copyright (c) 2014, Facebook, Inc. All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without modification, 13 | are permitted provided that the following conditions are met: 14 | 15 | * Redistributions of source code must retain the above copyright notice, this 16 | list of conditions and the following disclaimer. 17 | 18 | * Redistributions in binary form must reproduce the above copyright notice, 19 | this list of conditions and the following disclaimer in the documentation 20 | and/or other materials provided with the distribution. 21 | 22 | * Neither the name Facebook nor the names of its contributors may be used to 23 | endorse or promote products derived from this software without specific 24 | prior written permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 27 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 30 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 33 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | 38 | ## WSProgressHUD 39 | 40 | Copyright (c) 2019 devSC 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to deal 44 | in the Software without restriction, including without limitation the rights 45 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 46 | copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in 50 | all copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 58 | THE SOFTWARE. 59 | 60 | Generated by CocoaPods - https://cocoapods.org 61 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_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 | BSD License 18 | 19 | For Shimmer software 20 | 21 | Copyright (c) 2014, Facebook, Inc. All rights reserved. 22 | 23 | Redistribution and use in source and binary forms, with or without modification, 24 | are permitted provided that the following conditions are met: 25 | 26 | * Redistributions of source code must retain the above copyright notice, this 27 | list of conditions and the following disclaimer. 28 | 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimer in the documentation 31 | and/or other materials provided with the distribution. 32 | 33 | * Neither the name Facebook nor the names of its contributors may be used to 34 | endorse or promote products derived from this software without specific 35 | prior written permission. 36 | 37 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 38 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 39 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 41 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 44 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 46 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | 48 | License 49 | BSD 50 | Title 51 | Shimmer 52 | Type 53 | PSGroupSpecifier 54 | 55 | 56 | FooterText 57 | Copyright (c) 2019 devSC <xiaochong2154@163.com> 58 | 59 | Permission is hereby granted, free of charge, to any person obtaining a copy 60 | of this software and associated documentation files (the "Software"), to deal 61 | in the Software without restriction, including without limitation the rights 62 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63 | copies of the Software, and to permit persons to whom the Software is 64 | furnished to do so, subject to the following conditions: 65 | 66 | The above copyright notice and this permission notice shall be included in 67 | all copies or substantial portions of the Software. 68 | 69 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 70 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 71 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 72 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 73 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 74 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 75 | THE SOFTWARE. 76 | 77 | License 78 | MIT 79 | Title 80 | WSProgressHUD 81 | Type 82 | PSGroupSpecifier 83 | 84 | 85 | FooterText 86 | Generated by CocoaPods - https://cocoapods.org 87 | Title 88 | 89 | Type 90 | PSGroupSpecifier 91 | 92 | 93 | StringsTable 94 | Acknowledgements 95 | Title 96 | Acknowledgements 97 | 98 | 99 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_WSProgressHUD_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_WSProgressHUD_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | 145 | if [[ "$CONFIGURATION" == "Debug" ]]; then 146 | install_framework "${BUILT_PRODUCTS_DIR}/Shimmer/Shimmer.framework" 147 | install_framework "${BUILT_PRODUCTS_DIR}/WSProgressHUD/WSProgressHUD.framework" 148 | fi 149 | if [[ "$CONFIGURATION" == "Release" ]]; then 150 | install_framework "${BUILT_PRODUCTS_DIR}/Shimmer/Shimmer.framework" 151 | install_framework "${BUILT_PRODUCTS_DIR}/WSProgressHUD/WSProgressHUD.framework" 152 | fi 153 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 154 | wait 155 | fi 156 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | 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 60 | 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} 61 | ;; 62 | *.xib) 63 | 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 64 | 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} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | 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}" 115 | else 116 | 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}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_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_WSProgressHUD_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_WSProgressHUD_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer" "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD" 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}/Shimmer/Shimmer.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD/WSProgressHUD.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "Shimmer" -framework "WSProgressHUD" 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-WSProgressHUD_Example/Pods-WSProgressHUD_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_WSProgressHUD_Example { 2 | umbrella header "Pods-WSProgressHUD_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Example/Pods-WSProgressHUD_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer" "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD" 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}/Shimmer/Shimmer.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD/WSProgressHUD.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "Shimmer" -framework "WSProgressHUD" 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-WSProgressHUD_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-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## FBSnapshotTestCase 5 | 6 | BSD License 7 | 8 | For the FBSnapshotTestCase software 9 | 10 | Copyright (c) 2013, Facebook, Inc. 11 | All rights reserved. 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | * Redistributions of source code must retain the above copyright notice, 17 | this list of conditions and the following disclaimer. 18 | * Redistributions in binary form must reproduce the above copyright notice, 19 | this list of conditions and the following disclaimer in the documentation 20 | and/or other materials provided with the distribution. 21 | * Neither the name Facebook nor the names of its contributors may be used to 22 | endorse or promote products derived from this software without specific 23 | prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | Generated by CocoaPods - https://cocoapods.org 37 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_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 | BSD License 18 | 19 | For the FBSnapshotTestCase software 20 | 21 | Copyright (c) 2013, Facebook, Inc. 22 | All rights reserved. 23 | 24 | Redistribution and use in source and binary forms, with or without 25 | modification, are permitted provided that the following conditions are met: 26 | 27 | * Redistributions of source code must retain the above copyright notice, 28 | this list of conditions and the following disclaimer. 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimer in the documentation 31 | and/or other materials provided with the distribution. 32 | * Neither the name Facebook nor the names of its contributors may be used to 33 | endorse or promote products derived from this software without specific 34 | prior written permission. 35 | 36 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 37 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 40 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 42 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 43 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | 47 | License 48 | BSD 49 | Title 50 | FBSnapshotTestCase 51 | Type 52 | PSGroupSpecifier 53 | 54 | 55 | FooterText 56 | Generated by CocoaPods - https://cocoapods.org 57 | Title 58 | 59 | Type 60 | PSGroupSpecifier 61 | 62 | 63 | StringsTable 64 | Acknowledgements 65 | Title 66 | Acknowledgements 67 | 68 | 69 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_WSProgressHUD_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_WSProgressHUD_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | 145 | if [[ "$CONFIGURATION" == "Debug" ]]; then 146 | install_framework "${BUILT_PRODUCTS_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework" 147 | fi 148 | if [[ "$CONFIGURATION" == "Release" ]]; then 149 | install_framework "${BUILT_PRODUCTS_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework" 150 | fi 151 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 152 | wait 153 | fi 154 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | 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 60 | 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} 61 | ;; 62 | *.xib) 63 | 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 64 | 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} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | 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}" 115 | else 116 | 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}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_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_WSProgressHUD_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_WSProgressHUD_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer" "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer/Shimmer.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD/WSProgressHUD.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "FBSnapshotTestCase" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_WSProgressHUD_Tests { 2 | umbrella header "Pods-WSProgressHUD_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-WSProgressHUD_Tests/Pods-WSProgressHUD_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/Library/Frameworks "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer" "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer/Shimmer.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD/WSProgressHUD.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "FBSnapshotTestCase" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Shimmer/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.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Shimmer/Shimmer-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Shimmer : NSObject 3 | @end 4 | @implementation PodsDummy_Shimmer 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Shimmer/Shimmer-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/Shimmer/Shimmer-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 "FBShimmering.h" 14 | #import "FBShimmeringLayer.h" 15 | #import "FBShimmeringView.h" 16 | 17 | FOUNDATION_EXPORT double ShimmerVersionNumber; 18 | FOUNDATION_EXPORT const unsigned char ShimmerVersionString[]; 19 | 20 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Shimmer/Shimmer.modulemap: -------------------------------------------------------------------------------- 1 | framework module Shimmer { 2 | umbrella header "Shimmer-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Shimmer/Shimmer.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Shimmer 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | PODS_BUILD_DIR = ${BUILD_DIR} 4 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 5 | PODS_ROOT = ${SRCROOT} 6 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Shimmer 7 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 8 | SKIP_INSTALL = YES 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WSProgressHUD/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.1.5 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WSProgressHUD/ResourceBundle-WSProgressHUD-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.1.5 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WSProgressHUD/WSProgressHUD-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_WSProgressHUD : NSObject 3 | @end 4 | @implementation PodsDummy_WSProgressHUD 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WSProgressHUD/WSProgressHUD-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/WSProgressHUD/WSProgressHUD-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 "MMMaterialDesignSpinner.h" 14 | #import "WSIndefiniteAnimationView.h" 15 | #import "WSProgressHUD.h" 16 | 17 | FOUNDATION_EXPORT double WSProgressHUDVersionNumber; 18 | FOUNDATION_EXPORT const unsigned char WSProgressHUDVersionString[]; 19 | 20 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WSProgressHUD/WSProgressHUD.modulemap: -------------------------------------------------------------------------------- 1 | framework module WSProgressHUD { 2 | umbrella header "WSProgressHUD-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/WSProgressHUD/WSProgressHUD.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WSProgressHUD 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Shimmer" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = -framework "CoreGraphics" -framework "Foundation" -framework "QuartzCore" -framework "UIKit" 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 | @import FBSnapshotTestCase; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WSProgressHUDTests.m 3 | // WSProgressHUDTests 4 | // 5 | // Created by devSC on 10/19/2019. 6 | // Copyright (c) 2019 devSC. 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/WSProgressHUD/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 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/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 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/TabViewController1.h: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewController1.h 3 | // WSProgressHUD 4 | // 5 | // Created by YSC on 15/7/21. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TabViewController1 : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/TabViewController1.m: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewController1.m 3 | // WSProgressHUD 4 | // 5 | // Created by YSC on 15/7/21. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import "TabViewController1.h" 10 | #import "WSProgressHUD.h" 11 | @interface TabViewController1 () 12 | 13 | @end 14 | 15 | @implementation TabViewController1 16 | { 17 | WSProgressHUD *hud; 18 | } 19 | 20 | - (void)viewWillAppear:(BOOL)animated 21 | { 22 | [super viewWillAppear:animated]; 23 | } 24 | 25 | - (void)viewWillDisappear:(BOOL)animated 26 | { 27 | [super viewWillDisappear:animated]; 28 | 29 | [WSProgressHUD dismiss]; 30 | } 31 | - (void)viewDidLoad { 32 | [super viewDidLoad]; 33 | // Do any additional setup after loading the view. 34 | hud = [[WSProgressHUD alloc] initWithView:self.view]; 35 | [self.view addSubview:hud]; 36 | 37 | [hud showWithString:nil maskType:WSProgressHUDMaskTypeBlack]; 38 | 39 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 40 | [hud dismiss]; 41 | }); 42 | 43 | } 44 | 45 | - (void)didReceiveMemoryWarning { 46 | [super didReceiveMemoryWarning]; 47 | // Dispose of any resources that can be recreated. 48 | } 49 | - (IBAction)show:(id)sender { 50 | [hud showWithString:@"Loading..."]; 51 | 52 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 53 | [hud dismiss]; 54 | }); 55 | 56 | 57 | } 58 | - (IBAction)showOnTheWindow:(id)sender { 59 | [WSProgressHUD showWithStatus:@"Loading..." maskType:WSProgressHUDMaskTypeBlack maskWithout:WSProgressHUDMaskWithoutNavAndTabbar]; 60 | } 61 | 62 | /* 63 | #pragma mark - Navigation 64 | 65 | // In a storyboard-based application, you will often want to do a little preparation before navigation 66 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 67 | // Get the new view controller using [segue destinationViewController]. 68 | // Pass the selected object to the new view controller. 69 | } 70 | */ 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/TabViewController2.h: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewController2.h 3 | // WSProgressHUD 4 | // 5 | // Created by YSC on 15/7/23. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TabViewController2 : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/TabViewController2.m: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewController2.m 3 | // WSProgressHUD 4 | // 5 | // Created by YSC on 15/7/23. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import "TabViewController2.h" 10 | #import "WSProgressHUD.h" 11 | 12 | @interface TabViewController2 () 13 | 14 | @end 15 | 16 | @implementation TabViewController2 17 | { 18 | WSProgressHUD *hud; 19 | } 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view. 23 | hud = [[WSProgressHUD alloc] initWithView:self.view]; 24 | [self.view addSubview:hud]; 25 | 26 | [hud showShimmeringString:@"Loading...."]; 27 | 28 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 29 | [hud dismiss]; 30 | }); 31 | 32 | } 33 | 34 | - (void)didReceiveMemoryWarning { 35 | [super didReceiveMemoryWarning]; 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | /* 40 | #pragma mark - Navigation 41 | 42 | // In a storyboard-based application, you will often want to do a little preparation before navigation 43 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 44 | // Get the new view controller using [segue destinationViewController]. 45 | // Pass the selected object to the new view controller. 46 | } 47 | */ 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // WSProgressHUD 4 | // 5 | // Created by Wilson-Yuan on 15/7/17. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // WSProgressHUD 4 | // 5 | // Created by Wilson-Yuan on 15/7/17. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "WSProgressHUD.h" 11 | 12 | #import "MMMaterialDesignSpinner.h" 13 | 14 | #define isIphoneX ({\ 15 | BOOL isPhoneX = NO;\ 16 | if (@available(iOS 11.0, *)) {\ 17 | if (!UIEdgeInsetsEqualToEdgeInsets([UIApplication sharedApplication].delegate.window.safeAreaInsets, UIEdgeInsetsZero)) {\ 18 | isPhoneX = YES;\ 19 | }\ 20 | }\ 21 | isPhoneX;\ 22 | }) 23 | 24 | 25 | 26 | @interface ViewController () 27 | 28 | @property (weak, nonatomic) IBOutlet MMMaterialDesignSpinner *spinner; 29 | 30 | @end 31 | 32 | @implementation ViewController 33 | { 34 | WSProgressHUD *hud; 35 | } 36 | - (void)viewDidLoad { 37 | [super viewDidLoad]; 38 | // Do any additional setup after loading the view, typically from a nib. 39 | 40 | //Add HUD to view 41 | hud = [[WSProgressHUD alloc] initWithView:self.navigationController.view]; 42 | [self.view addSubview:hud]; 43 | 44 | //show 45 | [hud showWithString:@"Wating..." maskType:WSProgressHUDMaskTypeBlack]; 46 | 47 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 48 | [hud dismiss]; 49 | }); 50 | 51 | 52 | NSLog(@"isPhoneX: %@ safeAreaInsets: %@", @(isIphoneX), NSStringFromUIEdgeInsets([UIApplication sharedApplication].delegate.window.safeAreaInsets)); 53 | 54 | //IpHONE11 : 2019-10-12 13:47:13.977848+0800 WSProgressHUD-Demo[11856:364632] safeAreaInsets: {44, 0, 34, 0} 55 | //IPhone8 2019-10-12 13:48:20.355807+0800 WSProgressHUD-Demo[12002:367684] safeAreaInsets: {0, 0, 0, 0} 56 | } 57 | 58 | - (void)didReceiveMemoryWarning { 59 | [super didReceiveMemoryWarning]; 60 | // Dispose of any resources that can be recreated. 61 | } 62 | - (IBAction)show:(id)sender { 63 | 64 | [WSProgressHUD setProgressHUDIndicatorStyle:WSProgressHUDIndicatorBigGray]; 65 | [WSProgressHUD show]; 66 | [self autoDismiss]; 67 | } 68 | 69 | - (IBAction)showShimmeringString:(id)sender { 70 | 71 | [WSProgressHUD showShimmeringString:@"WSProgressHUD Loading..." maskType:WSProgressHUDMaskTypeBlack maskWithout:WSProgressHUDMaskWithoutNavigation]; 72 | 73 | [self autoDismiss]; 74 | } 75 | - (IBAction)showWithString:(id)sender { 76 | [WSProgressHUD showWithStatus:@"Loading..." maskType:WSProgressHUDMaskTypeBlack]; 77 | [self autoDismiss]; 78 | 79 | } 80 | - (IBAction)showProgress:(id)sender { 81 | [self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.3f]; 82 | } 83 | 84 | 85 | static float progress = 0.0f; 86 | 87 | - (void)increaseProgress { 88 | progress+=0.1f; 89 | [WSProgressHUD showProgress:progress status:@"Updating..."]; 90 | 91 | if(progress < 1.0f) { 92 | [self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.3f]; 93 | } else { 94 | [WSProgressHUD showImage:nil status:@"Success Update"]; 95 | progress = 0; 96 | } 97 | } 98 | 99 | 100 | - (IBAction)showImage:(id)sender { 101 | 102 | [WSProgressHUD showSuccessWithStatus:@"I was not delivered unto this world in defeat, nor does failure course in my veins. I am not a sheep waiting to be prodded by my shepherd. I am a lion and I refuse to talk, to walk, to sleep with the sheep. I will hear not those who weep and complain, for their disease is contagious. Let them join the sheep. The slaughterhouse of failure is not my destiny."]; 103 | 104 | } 105 | - (IBAction)showString:(id)sender { 106 | [WSProgressHUD showImage:nil status:@"WSProgressHUD"]; 107 | } 108 | 109 | - (IBAction)dismiss:(id)sender { 110 | [WSProgressHUD dismiss]; 111 | } 112 | 113 | 114 | - (void)autoDismiss 115 | { 116 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 117 | [WSProgressHUD dismiss]; 118 | }); 119 | 120 | } 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/WSAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // WSAppDelegate.h 3 | // WSProgressHUD 4 | // 5 | // Created by devSC on 10/19/2019. 6 | // Copyright (c) 2019 devSC. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface WSAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/WSAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // WSAppDelegate.m 3 | // WSProgressHUD 4 | // 5 | // Created by devSC on 10/19/2019. 6 | // Copyright (c) 2019 devSC. All rights reserved. 7 | // 8 | 9 | #import "WSAppDelegate.h" 10 | 11 | @implementation WSAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // 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. 22 | // 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. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // 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. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/WSProgressHUD-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/WSProgressHUD/WSProgressHUD-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/WSProgressHUD/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/WSProgressHUD/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WSProgressHUD 4 | // 5 | // Created by devSC on 10/19/2019. 6 | // Copyright (c) 2019 devSC. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "WSAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([WSAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/build/XCBuildData/1a5c94668b3ca20b660beb5a33864065-desc.xcbuild: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/Example/build/XCBuildData/1a5c94668b3ca20b660beb5a33864065-desc.xcbuild -------------------------------------------------------------------------------- /Example/build/XCBuildData/BuildDescriptionCacheIndex-265ef7066956889aa1428aabb3b22a2e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/Example/build/XCBuildData/BuildDescriptionCacheIndex-265ef7066956889aa1428aabb3b22a2e -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Wilson-yuan 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WSProgressHUD 2 | This is a beauful hud view for iPhone & iPad 3 | 4 | [![CI Status](http://img.shields.io/travis/devSC/WSProgressHUD.svg?style=flat)](https://travis-ci.org/devSC/WSProgressHUD) 5 | [![Version](https://img.shields.io/cocoapods/v/WSProgressHUD.svg?style=flat)](http://cocoapods.org/pods/WSProgressHUD) 6 | [![License](https://img.shields.io/cocoapods/l/WSProgressHUD.svg?style=flat)](http://cocoapods.org/pods/WSProgressHUD) 7 | [![Platform](https://img.shields.io/cocoapods/p/WSProgressHUD.svg?style=flat)](http://cocoapods.org/pods/WSProgressHUD) 8 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/devSC/WSProgressHUD) 9 | 10 | 11 | 12 | ![Example](Example/Demo.gif) 13 | 14 | # Usage 15 | To Download the project. Run the WSProgressHUD.xcodeproj in the demo directory. 16 | 17 | ``` objc 18 | 19 | [WSProgressHUD show]; 20 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 21 | ... 22 | 23 | dispatch_async(dispatch_get_main_queue(), ^{ 24 | ... 25 | [WSProgressHUD dismiss]; 26 | }); 27 | }); 28 | 29 | //Show on the self.view 30 | 31 | @implementation ViewController 32 | { 33 | WSProgressHUD *hud; 34 | } 35 | - (void)viewDidLoad { 36 | [super viewDidLoad]; 37 | // Do any additional setup after loading the view, typically from a nib. 38 | 39 | //Add HUD to view 40 | hud = [[WSProgressHUD alloc] initWithView:self.navigationController.view]; 41 | [self.view addSubview:hud]; 42 | 43 | //show 44 | [hud showWithString:@"Wating..." maskType:WSProgressHUDMaskTypeBlack]; 45 | 46 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 47 | [hud dismiss]; 48 | }); 49 | 50 | } 51 | 52 | //Show on the window 53 | //show 54 | [WSProgressHUD show]; 55 | 56 | //Show with mask 57 | [WSProgressHUD showWithMaskType:WSProgressHUDMaskTypeBlack]; 58 | 59 | //Show with mask without tabbar 60 | [WSProgressHUD showWithStatus:@"Loading..." maskType:WSProgressHUDMaskTypeBlack maskWithout:WSProgressHUDMaskWithoutTabbar]; 61 | 62 | //Show with string 63 | [WSProgressHUD showWithStatus:@"Loading..."]; 64 | 65 | //Show with facebook shimmering 66 | [WSProgressHUD showShimmeringString:@"WSProgressHUD Loading..."]; 67 | 68 | //Show with Progress 69 | [WSProgressHUD showProgress:progress status:@"Updating..."]; 70 | 71 | //Show with image 72 | [WSProgressHUD showSuccessWithStatus:@"Thanks.."]; 73 | 74 | //Show with string 75 | [WSProgressHUD showImage:nil status:@"WSProgressHUD"] 76 | 77 | //Dismiss 78 | [WSProgressHUD dismiss]; 79 | 80 | //And There have 3 indicator style for your choice 81 | [WSProgressHUD setProgressHUDIndicatorStyle:WSProgressHUDIndicatorSmall] //small custom spinner 82 | 83 | ``` 84 | ## Installation 85 | 86 | ### From CocoaPods 87 | 88 | WSProgressHUD is available through [CocoaPods](http://cocoapods.org). To install 89 | it, simply add the following line to your Podfile: 90 | 91 | ```ruby 92 | pod 'WSProgressHUD' 93 | 94 | ``` 95 | 96 | ### Carthage 97 | 98 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate `WSProgressHUD` into your Xcode project using Carthage, specify it in your `Cartfile`: 99 | 100 | ```ogdl 101 | github "devSC/WSProgressHUD" 102 | ``` 103 | 104 | Run `carthage update` to build the framework and drag the built `WSProgressHUD.framework` (in Carthage/Build/iOS folder) into your Xcode project (Linked Frameworks and Libraries in `Targets`). 105 | 106 | ### Manually 107 | 108 | Drag the `WSProgressHUD/Demo/WSProgressHUD` folder into your project. 109 | Then take care that `WSProgressHUD.bundle` is added to Targets->Build Phases->Copy Bundle Resources. 110 | Add the QuartzCore framework to your project. 111 | 112 | ## Swift 113 | 114 | Even though `WSProgressHUD` is written in Objective-C, it can be used in Swift with no hassle. If you use [CocoaPods](http://cocoapods.org) add the following line to your [Podfile](http://guides.cocoapods.org/using/using-cocoapods.html): 115 | 116 | ```ruby 117 | use_frameworks! 118 | ``` 119 | 120 | If you added `WSProgressHUD` manually, just add a [bridging header](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html) file to your project with the `WSProgressHUD` header included. 121 | 122 | ## Thanks 123 | 124 | @Shimmering 125 | @SVProgressHUD 126 | @MMMaterialDesignSpinner 127 | 128 | ## Author 129 | Wilson-Yuan, xiaochong2154@163.com 130 | 131 | ## License 132 | WSProgressHUD is available under the MIT license. See the [LICENSE](https://github.com/devSC/WSProgressHUD/blob/master/LICENSE) 133 | file for more info. 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /WSProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint WSProgressHUD.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "WSProgressHUD" 19 | s.version = "1.1.5" 20 | s.summary = "WSProgressHUD is a beauful hud view for iPhone & iPad." 21 | 22 | s.description = <<-DESC 23 | WSProgressHUD is a beauful hud view for iPhone & iPad. you can simple to use it. 24 | 25 | * Think: Why did you write this? What is the focus? What does it do? 26 | * CocoaPods will be using this to generate tags, and improve search results. 27 | * Try to keep it short, snappy and to the point. 28 | * Finally, don't worry about the indent, CocoaPods strips it 29 | DESC 30 | 31 | s.homepage = "https://github.com/devSC/WSProgressHUD" 32 | s.screenshots = "https://raw.githubusercontent.com/devSC/WSProgressHUD/master/Demo/Demo.gif" 33 | s.license = "MIT" 34 | 35 | s.author = { "袁仕崇" => "xiaochong2154@163.com" } 36 | s.platform = :ios, "6.0" 37 | s.source = { :git => "https://github.com/devSC/WSProgressHUD.git", :tag => "1.1.5" } 38 | s.source_files = 'WSProgressHUD/Classes/**/*' 39 | s.exclude_files = "Demo/Exclude" 40 | 41 | s.resource_bundles = { 42 | 'WSProgressHUD' => ['WSProgressHUD/Assets/*.png'] 43 | } 44 | # s.resources = "WSProgressHUD/*.bundle" 45 | s.frameworks = "UIKit", "QuartzCore","CoreGraphics","Foundation" 46 | 47 | s.requires_arc = true 48 | s.dependency 'Shimmer' 49 | 50 | end 51 | -------------------------------------------------------------------------------- /WSProgressHUD/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/WSProgressHUD/Assets/.gitkeep -------------------------------------------------------------------------------- /WSProgressHUD/Assets/angle-mask@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/WSProgressHUD/Assets/angle-mask@3x.png -------------------------------------------------------------------------------- /WSProgressHUD/Assets/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/WSProgressHUD/Assets/error@2x.png -------------------------------------------------------------------------------- /WSProgressHUD/Assets/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/WSProgressHUD/Assets/success@2x.png -------------------------------------------------------------------------------- /WSProgressHUD/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devSC/WSProgressHUD/2e9058b067894925fbc79678be459e0cb44a667c/WSProgressHUD/Classes/.gitkeep -------------------------------------------------------------------------------- /WSProgressHUD/Classes/MMMaterialDesignSpinner.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMMaterialDesignSpinner.h 3 | // Pods 4 | // 5 | // Created by Michael Maxwell on 12/28/14. 6 | // 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for MMMaterialDesignSpinner. 12 | FOUNDATION_EXPORT double MMMaterialDesignSpinnerVersionNumber; 13 | 14 | //! Project version string for MMMaterialDesignSpinner. 15 | FOUNDATION_EXPORT const unsigned char MMMaterialDesignSpinnerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | /** 20 | * A control similar to iOS' UIActivityIndicatorView modeled after Google's Material Design Activity spinner. 21 | */ 22 | @interface MMMaterialDesignSpinner : UIView 23 | 24 | /** Sets the line width of the spinner's circle. */ 25 | @property (nonatomic) CGFloat lineWidth; 26 | 27 | /** Sets whether the view is hidden when not animating. */ 28 | @property (nonatomic) BOOL hidesWhenStopped; 29 | 30 | /** Specifies the timing function to use for the control's animation. Defaults to kCAMediaTimingFunctionEaseInEaseOut */ 31 | @property (nonatomic, strong) CAMediaTimingFunction *timingFunction; 32 | 33 | /** Property indicating whether the view is currently animating. */ 34 | @property (nonatomic, readonly) BOOL isAnimating; 35 | 36 | @property (nonatomic, strong) UIColor *spinnerColor; 37 | /** 38 | * Convenience function for starting & stopping animation with a boolean variable instead of explicit 39 | * method calls. 40 | * 41 | * @param animate true to start animating, false to stop animating. 42 | @note This method simply calls the startAnimating or stopAnimating methods based on the value of the animate parameter. 43 | */ 44 | - (void)setAnimating:(BOOL)animate; 45 | 46 | /** 47 | * Starts animation of the spinner. 48 | */ 49 | - (void)startAnimating; 50 | 51 | /** 52 | * Stops animation of the spinnner. 53 | */ 54 | - (void)stopAnimating; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /WSProgressHUD/Classes/MMMaterialDesignSpinner.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMMaterialDesignSpinner.m 3 | // Pods 4 | // 5 | // Created by Michael Maxwell on 12/28/14. 6 | // 7 | // 8 | 9 | #import "MMMaterialDesignSpinner.h" 10 | 11 | static NSString *kMMRingStrokeAnimationKey = @"mmmaterialdesignspinner.stroke"; 12 | static NSString *kMMRingRotationAnimationKey = @"mmmaterialdesignspinner.rotation"; 13 | 14 | @interface MMMaterialDesignSpinner () 15 | @property (nonatomic, readonly) CAShapeLayer *progressLayer; 16 | @property (nonatomic, readwrite) BOOL isAnimating; 17 | @end 18 | 19 | @implementation MMMaterialDesignSpinner 20 | 21 | @synthesize progressLayer=_progressLayer; 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame { 24 | if (self = [super initWithFrame:frame]) { 25 | [self initialize]; 26 | } 27 | return self; 28 | } 29 | 30 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 31 | if (self = [super initWithCoder:aDecoder]) { 32 | [self initialize]; 33 | } 34 | return self; 35 | } 36 | 37 | - (void)awakeFromNib 38 | { 39 | [super awakeFromNib]; 40 | 41 | [self initialize]; 42 | } 43 | 44 | - (void)initialize { 45 | _timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 46 | 47 | [self.layer addSublayer:self.progressLayer]; 48 | 49 | // See comment in resetAnimations on why this notification is used. 50 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resetAnimations) name:UIApplicationDidBecomeActiveNotification object:nil]; 51 | } 52 | 53 | - (void)dealloc 54 | { 55 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; 56 | } 57 | 58 | - (void)layoutSubviews { 59 | [super layoutSubviews]; 60 | 61 | self.progressLayer.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 62 | [self updatePath]; 63 | } 64 | 65 | - (void)tintColorDidChange { 66 | [super tintColorDidChange]; 67 | 68 | self.progressLayer.strokeColor = self.tintColor.CGColor; 69 | } 70 | 71 | - (void)resetAnimations { 72 | // If the app goes to the background, returning it to the foreground causes the animation to stop (even though it's not explicitly stopped by our code). Resetting the animation seems to kick it back into gear. 73 | if (self.isAnimating) { 74 | [self stopAnimating]; 75 | [self startAnimating]; 76 | } 77 | } 78 | 79 | - (void)setAnimating:(BOOL)animate { 80 | (animate ? [self startAnimating] : [self stopAnimating]); 81 | } 82 | 83 | - (void)startAnimating { 84 | if (self.isAnimating) 85 | return; 86 | 87 | CABasicAnimation *animation = [CABasicAnimation animation]; 88 | animation.keyPath = @"transform.rotation"; 89 | animation.duration = 4.f; 90 | animation.fromValue = @(0.f); 91 | animation.toValue = @(2 * M_PI); 92 | animation.repeatCount = INFINITY; 93 | animation.removedOnCompletion = NO; 94 | [self.progressLayer addAnimation:animation forKey:kMMRingRotationAnimationKey]; 95 | 96 | CABasicAnimation *headAnimation = [CABasicAnimation animation]; 97 | headAnimation.keyPath = @"strokeStart"; 98 | headAnimation.duration = 1.f; 99 | headAnimation.fromValue = @(0.f); 100 | headAnimation.toValue = @(0.25f); 101 | headAnimation.timingFunction = self.timingFunction; 102 | 103 | CABasicAnimation *tailAnimation = [CABasicAnimation animation]; 104 | tailAnimation.keyPath = @"strokeEnd"; 105 | tailAnimation.duration = 1.f; 106 | tailAnimation.fromValue = @(0.f); 107 | tailAnimation.toValue = @(1.f); 108 | tailAnimation.timingFunction = self.timingFunction; 109 | 110 | 111 | CABasicAnimation *endHeadAnimation = [CABasicAnimation animation]; 112 | endHeadAnimation.keyPath = @"strokeStart"; 113 | endHeadAnimation.beginTime = 1.f; 114 | endHeadAnimation.duration = 0.5f; 115 | endHeadAnimation.fromValue = @(0.25f); 116 | endHeadAnimation.toValue = @(1.f); 117 | endHeadAnimation.timingFunction = self.timingFunction; 118 | 119 | CABasicAnimation *endTailAnimation = [CABasicAnimation animation]; 120 | endTailAnimation.keyPath = @"strokeEnd"; 121 | endTailAnimation.beginTime = 1.f; 122 | endTailAnimation.duration = 0.5f; 123 | endTailAnimation.fromValue = @(1.f); 124 | endTailAnimation.toValue = @(1.f); 125 | endTailAnimation.timingFunction = self.timingFunction; 126 | 127 | CAAnimationGroup *animations = [CAAnimationGroup animation]; 128 | [animations setDuration:1.5f]; 129 | [animations setAnimations:@[headAnimation, tailAnimation, endHeadAnimation, endTailAnimation]]; 130 | animations.repeatCount = INFINITY; 131 | animations.removedOnCompletion = NO; 132 | [self.progressLayer addAnimation:animations forKey:kMMRingStrokeAnimationKey]; 133 | 134 | 135 | self.isAnimating = true; 136 | 137 | if (self.hidesWhenStopped) { 138 | self.hidden = NO; 139 | } 140 | } 141 | 142 | - (void)stopAnimating { 143 | if (!self.isAnimating) 144 | return; 145 | 146 | [self.progressLayer removeAnimationForKey:kMMRingRotationAnimationKey]; 147 | [self.progressLayer removeAnimationForKey:kMMRingStrokeAnimationKey]; 148 | self.isAnimating = false; 149 | 150 | if (self.hidesWhenStopped) { 151 | self.hidden = YES; 152 | } 153 | } 154 | 155 | #pragma mark - Private 156 | 157 | - (void)updatePath { 158 | CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 159 | CGFloat radius = MIN(CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2) - self.progressLayer.lineWidth / 2; 160 | CGFloat startAngle = (CGFloat)(0); 161 | CGFloat endAngle = (CGFloat)(2*M_PI); 162 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 163 | self.progressLayer.path = path.CGPath; 164 | 165 | self.progressLayer.strokeStart = 0.f; 166 | self.progressLayer.strokeEnd = 0.f; 167 | } 168 | 169 | #pragma mark - Properties 170 | 171 | - (CAShapeLayer *)progressLayer { 172 | if (!_progressLayer) { 173 | _progressLayer = [CAShapeLayer layer]; 174 | _progressLayer.strokeColor = [UIColor blueColor].CGColor; 175 | _progressLayer.fillColor = nil; 176 | _progressLayer.lineWidth = 1.5f; 177 | } 178 | return _progressLayer; 179 | } 180 | - (void)setSpinnerColor:(UIColor *)spinnerColor 181 | { 182 | self.progressLayer.strokeColor = spinnerColor.CGColor; 183 | } 184 | 185 | 186 | - (BOOL)isAnimating { 187 | return _isAnimating; 188 | } 189 | 190 | - (CGFloat)lineWidth { 191 | return self.progressLayer.lineWidth; 192 | } 193 | 194 | - (void)setLineWidth:(CGFloat)lineWidth { 195 | self.progressLayer.lineWidth = lineWidth; 196 | [self updatePath]; 197 | } 198 | 199 | - (void)setHidesWhenStopped:(BOOL)hidesWhenStopped { 200 | _hidesWhenStopped = hidesWhenStopped; 201 | self.hidden = !self.isAnimating && hidesWhenStopped; 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /WSProgressHUD/Classes/WSIndefiniteAnimationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WSIndefiniteAnimationView.h 3 | // WSProgressHUD 4 | // 5 | // Created by Wilson-Yuan on 15/7/19. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WSIndefiniteAnimationView : UIView 12 | 13 | @property (nonatomic, assign) CGFloat strokeThickness; 14 | @property (nonatomic, assign) CGFloat radius; 15 | @property (nonatomic, strong) UIColor *strokeColor; 16 | 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /WSProgressHUD/Classes/WSIndefiniteAnimationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WSIndefiniteAnimationView.m 3 | // WSProgressHUD 4 | // 5 | // Created by Wilson-Yuan on 15/7/19. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import "WSIndefiniteAnimationView.h" 10 | 11 | @interface WSIndefiniteAnimationView () 12 | 13 | @property (strong, nonatomic) CAShapeLayer *indefiniteAnimatedLayer; 14 | 15 | @end 16 | 17 | 18 | @implementation WSIndefiniteAnimationView 19 | 20 | - (void)willMoveToSuperview:(UIView *)newSuperview 21 | { 22 | if (newSuperview) { 23 | [self layoutAnimationLayer]; 24 | } else { 25 | [_indefiniteAnimatedLayer removeFromSuperlayer]; 26 | _indefiniteAnimatedLayer = nil; 27 | } 28 | } 29 | 30 | - (void)layoutAnimationLayer { 31 | CALayer *layer = self._indefiniteAnimatedLayer; 32 | [self.layer addSublayer:layer]; 33 | 34 | layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds)/2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2); 35 | } 36 | 37 | - (CAShapeLayer *)_indefiniteAnimatedLayer 38 | { 39 | if(!_indefiniteAnimatedLayer) { 40 | CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); 41 | CGRect rect = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); 42 | 43 | UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter 44 | radius:self.radius 45 | startAngle:M_PI*3/2 46 | endAngle:M_PI/2+M_PI*5 47 | clockwise:YES]; 48 | 49 | _indefiniteAnimatedLayer = [CAShapeLayer layer]; 50 | _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; 51 | _indefiniteAnimatedLayer.frame = rect; 52 | _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor; 53 | _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor; 54 | _indefiniteAnimatedLayer.lineWidth = self.strokeThickness; 55 | _indefiniteAnimatedLayer.lineCap = kCALineCapRound; 56 | _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel; 57 | _indefiniteAnimatedLayer.path = smoothedPath.CGPath; 58 | 59 | CALayer *maskLayer = [CALayer layer]; 60 | 61 | NSBundle *bundle = [NSBundle bundleForClass:self.class]; 62 | NSURL *url = [bundle URLForResource:@"WSProgressHUD" withExtension:@"bundle"]; 63 | NSBundle *imageBundle = [NSBundle bundleWithURL:url]; 64 | NSString *path = [imageBundle pathForResource:@"angle-mask@3x" ofType:@"png"]; 65 | maskLayer.contents = (id)[[UIImage imageWithContentsOfFile:path] CGImage]; 66 | 67 | maskLayer.frame = _indefiniteAnimatedLayer.bounds; 68 | _indefiniteAnimatedLayer.mask = maskLayer; 69 | 70 | NSTimeInterval animationDuration = 1; 71 | CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 72 | 73 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 74 | animation.fromValue = 0; 75 | animation.toValue = @(M_PI*2); 76 | animation.duration = animationDuration; 77 | animation.timingFunction = linearCurve; 78 | animation.removedOnCompletion = NO; 79 | animation.repeatCount = INFINITY; 80 | animation.fillMode = kCAFillModeForwards; 81 | animation.autoreverses = NO; 82 | [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"]; 83 | 84 | CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 85 | animationGroup.duration = animationDuration; 86 | animationGroup.repeatCount = INFINITY; 87 | animationGroup.removedOnCompletion = NO; 88 | animationGroup.timingFunction = linearCurve; 89 | 90 | CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; 91 | strokeStartAnimation.fromValue = @0.015; 92 | strokeStartAnimation.toValue = @0.515; 93 | 94 | CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 95 | strokeEndAnimation.fromValue = @0.485; 96 | strokeEndAnimation.toValue = @0.985; 97 | 98 | animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation]; 99 | [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"]; 100 | 101 | } 102 | return _indefiniteAnimatedLayer; 103 | } 104 | 105 | 106 | - (void)setFrame:(CGRect)frame { 107 | if(!CGRectEqualToRect(frame, super.frame)){ 108 | [super setFrame:frame]; 109 | 110 | if (self.superview) { 111 | [self layoutAnimationLayer]; 112 | } 113 | } 114 | 115 | } 116 | 117 | - (void)setRadius:(CGFloat)radius { 118 | if(radius != _radius){ 119 | _radius = radius; 120 | 121 | [_indefiniteAnimatedLayer removeFromSuperlayer]; 122 | _indefiniteAnimatedLayer = nil; 123 | 124 | if (self.superview) { 125 | [self layoutAnimationLayer]; 126 | } 127 | } 128 | } 129 | 130 | - (void)setStrokeColor:(UIColor *)strokeColor { 131 | _strokeColor = strokeColor; 132 | _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor; 133 | } 134 | 135 | - (void)setStrokeThickness:(CGFloat)strokeThickness { 136 | _strokeThickness = strokeThickness; 137 | _indefiniteAnimatedLayer.lineWidth = _strokeThickness; 138 | } 139 | 140 | - (CGSize)sizeThatFits:(CGSize)size { 141 | return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); 142 | } 143 | 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /WSProgressHUD/Classes/WSProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // WSProgressHUD.h 3 | // WSProgressHUD 4 | // 5 | // Created by Wilson-Yuan on 15/7/17. 6 | // Copyright (c) 2015年 wilson-yuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, WSProgressHUDMaskType) { 12 | WSProgressHUDMaskTypeDefault, //allow user touch when hud display 13 | WSProgressHUDMaskTypeClear, //dont allowed user touch 14 | WSProgressHUDMaskTypeBlack, //dont allowed user touch 15 | WSProgressHUDMaskTypeGradient //dont allowed user touch 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, WSProgressHUDMaskWithoutType) { // 19 | WSProgressHUDMaskWithoutDefault, // default mask all 20 | WSProgressHUDMaskWithoutNavigation, //show mask without navigation 21 | WSProgressHUDMaskWithoutTabbar, //show mask without tabbar 22 | WSProgressHUDMaskWithoutNavAndTabbar, //show mask without tabbar and navigation 23 | }; 24 | 25 | typedef NS_ENUM(NSInteger, WSProgressHUDIndicatorStyle) { 26 | WSProgressHUDIndicatorCustom, 27 | WSProgressHUDIndicatorMMSpinner, 28 | WSProgressHUDIndicatorSmallLight, 29 | WSProgressHUDIndicatorGray, 30 | WSProgressHUDIndicatorBigGray, 31 | }; 32 | 33 | 34 | @interface WSProgressHUD : UIView 35 | 36 | /*----------------------Show On the Window------------------------------*/ 37 | + (void)show; 38 | + (void)showWithMaskType:(WSProgressHUDMaskType)maskType; 39 | + (void)showWithMaskType:(WSProgressHUDMaskType)maskType maskWithout:(WSProgressHUDMaskWithoutType)withoutType; 40 | 41 | 42 | + (void)showWithStatus:(nullable NSString *)string; 43 | + (void)showWithStatus:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType; 44 | + (void)showWithStatus:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType maskWithout:(WSProgressHUDMaskWithoutType)withoutType; 45 | 46 | 47 | + (void)showShimmeringString:(nullable NSString *)string; 48 | + (void)showShimmeringString:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType; 49 | + (void)showShimmeringString:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType maskWithout:(WSProgressHUDMaskWithoutType)withoutType; 50 | 51 | + (void)showProgress:(CGFloat)progress; 52 | + (void)showProgress:(CGFloat)progress maskType:(WSProgressHUDMaskType)maskType; 53 | + (void)showProgress:(CGFloat)progress maskType:(WSProgressHUDMaskType)maskType maskWithout:(WSProgressHUDMaskWithoutType)withoutType; 54 | 55 | + (void)showProgress:(CGFloat)progress status:(nullable NSString *)string; 56 | + (void)showProgress:(CGFloat)progress status:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType; 57 | + (void)showProgress:(CGFloat)progress status:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType maskWithout:(WSProgressHUDMaskWithoutType)withoutType; 58 | 59 | //imageSize is 28*28 60 | + (void)showImage:(nullable UIImage *)image status:(nullable NSString *)title; 61 | + (void)showImage:(nullable UIImage *)image status:(nullable NSString *)title maskType:(WSProgressHUDMaskType)maskType; 62 | + (void)showImage:(nullable UIImage *)image status:(nullable NSString *)title maskType:(WSProgressHUDMaskType)maskType maskWithout:(WSProgressHUDMaskWithoutType)withoutType; 63 | 64 | + (void)showSuccessWithStatus:(nullable NSString *)string; 65 | + (void)showErrorWithStatus:(nullable NSString *)string; 66 | + (void)dismiss; 67 | 68 | /*----------------------------Custom---------------------------------*/ 69 | 70 | + (void)setProgressHUDIndicatorStyle:(WSProgressHUDIndicatorStyle)style; 71 | 72 | /// if you set WSProgressHUDIndicatorBigGray style you should set second prority indicator Style 73 | + (void)setSecondProrityIndicatorStyle:(WSProgressHUDIndicatorStyle)style; //Default is small SmallLight 74 | 75 | + (void)setProgressHUDFont:(nonnull UIFont *)font; 76 | 77 | /*----------------------Show On the view------------------------------*/ 78 | 79 | - (WSProgressHUD *_Nonnull)initWithView:(nonnull UIView *)view; 80 | - (WSProgressHUD *_Nonnull)initWithFrame:(CGRect)frame; 81 | 82 | - (void)show; 83 | - (void)showWithMaskType:(WSProgressHUDMaskType)maskType; 84 | 85 | - (void)showWithString:(nullable NSString *)string; 86 | - (void)showWithString:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType; 87 | 88 | 89 | - (void)showShimmeringString:(nullable NSString *)string; 90 | - (void)showShimmeringString:(nullable NSString *)string maskType:(WSProgressHUDMaskType)maskType; 91 | 92 | - (void)showProgress:(CGFloat)progress; 93 | - (void)showProgress:(CGFloat)progress maskType:(WSProgressHUDMaskType)maskType; 94 | 95 | - (void)showProgress:(CGFloat)progress status:(nullable NSString *)status; 96 | - (void)showProgress:(CGFloat)progress status:(nullable NSString *)status maskType:(WSProgressHUDMaskType)maskType; 97 | 98 | 99 | 100 | - (void)showImage:(nullable UIImage *)image status:(nullable NSString *)title; 101 | - (void)showImage:(nullable UIImage *)image status:(nullable NSString *)title maskType:(WSProgressHUDMaskType)maskType; 102 | 103 | - (void)showSuccessWithString:(nullable NSString *)string; 104 | - (void)showErrorWithString:(nullable NSString *)string; 105 | 106 | - (void)dismiss; 107 | 108 | /*----------------------------Custom---------------------------------*/ 109 | - (void)setProgressHUDIndicatorStyle:(WSProgressHUDIndicatorStyle)style; 110 | 111 | /// if you set WSProgressHUDIndicatorBigGray style you should set second prority indicator Style 112 | - (void)setSecondProrityIndicatorStyle:(WSProgressHUDIndicatorStyle)style; //Default is small SmallLight 113 | 114 | - (void)setProgressHUDFont:(nonnull UIFont *)font; 115 | 116 | @end 117 | --------------------------------------------------------------------------------