ceshi
Showing
62 changed files
with
2371 additions
and
20 deletions
| ... | @@ -208,7 +208,7 @@ | ... | @@ -208,7 +208,7 @@ |
| 208 | 6003F586195388D20070C39A /* Sources */, | 208 | 6003F586195388D20070C39A /* Sources */, |
| 209 | 6003F587195388D20070C39A /* Frameworks */, | 209 | 6003F587195388D20070C39A /* Frameworks */, |
| 210 | 6003F588195388D20070C39A /* Resources */, | 210 | 6003F588195388D20070C39A /* Resources */, |
| 211 | D64742FE184E91E0FBAA866F /* [CP] Embed Pods Frameworks */, | 211 | 5ABB5B4107E1A8D5114A0BE8 /* [CP] Embed Pods Frameworks */, |
| 212 | ); | 212 | ); |
| 213 | buildRules = ( | 213 | buildRules = ( |
| 214 | ); | 214 | ); |
| ... | @@ -318,44 +318,44 @@ | ... | @@ -318,44 +318,44 @@ |
| 318 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; | 318 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; |
| 319 | showEnvVarsInLog = 0; | 319 | showEnvVarsInLog = 0; |
| 320 | }; | 320 | }; |
| 321 | A3A9A2FA91267A67620EFAA0 /* [CP] Check Pods Manifest.lock */ = { | 321 | 5ABB5B4107E1A8D5114A0BE8 /* [CP] Embed Pods Frameworks */ = { |
| 322 | isa = PBXShellScriptBuildPhase; | 322 | isa = PBXShellScriptBuildPhase; |
| 323 | buildActionMask = 2147483647; | 323 | buildActionMask = 2147483647; |
| 324 | files = ( | 324 | files = ( |
| 325 | ); | 325 | ); |
| 326 | inputFileListPaths = ( | ||
| 327 | ); | ||
| 328 | inputPaths = ( | 326 | inputPaths = ( |
| 329 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", | 327 | "${PODS_ROOT}/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-frameworks.sh", |
| 330 | "${PODS_ROOT}/Manifest.lock", | 328 | "${BUILT_PRODUCTS_DIR}/JCategoryKit/JCategoryKit.framework", |
| 331 | ); | ||
| 332 | name = "[CP] Check Pods Manifest.lock"; | ||
| 333 | outputFileListPaths = ( | ||
| 334 | ); | 329 | ); |
| 330 | name = "[CP] Embed Pods Frameworks"; | ||
| 335 | outputPaths = ( | 331 | outputPaths = ( |
| 336 | "$(DERIVED_FILE_DIR)/Pods-JCategoryKit_Example-checkManifestLockResult.txt", | 332 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JCategoryKit.framework", |
| 337 | ); | 333 | ); |
| 338 | runOnlyForDeploymentPostprocessing = 0; | 334 | runOnlyForDeploymentPostprocessing = 0; |
| 339 | shellPath = /bin/sh; | 335 | shellPath = /bin/sh; |
| 340 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; | 336 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-frameworks.sh\"\n"; |
| 341 | showEnvVarsInLog = 0; | 337 | showEnvVarsInLog = 0; |
| 342 | }; | 338 | }; |
| 343 | D64742FE184E91E0FBAA866F /* [CP] Embed Pods Frameworks */ = { | 339 | A3A9A2FA91267A67620EFAA0 /* [CP] Check Pods Manifest.lock */ = { |
| 344 | isa = PBXShellScriptBuildPhase; | 340 | isa = PBXShellScriptBuildPhase; |
| 345 | buildActionMask = 2147483647; | 341 | buildActionMask = 2147483647; |
| 346 | files = ( | 342 | files = ( |
| 347 | ); | 343 | ); |
| 344 | inputFileListPaths = ( | ||
| 345 | ); | ||
| 348 | inputPaths = ( | 346 | inputPaths = ( |
| 349 | "${PODS_ROOT}/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-frameworks.sh", | 347 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", |
| 350 | "${BUILT_PRODUCTS_DIR}/JCategoryKit/JCategoryKit.framework", | 348 | "${PODS_ROOT}/Manifest.lock", |
| 349 | ); | ||
| 350 | name = "[CP] Check Pods Manifest.lock"; | ||
| 351 | outputFileListPaths = ( | ||
| 351 | ); | 352 | ); |
| 352 | name = "[CP] Embed Pods Frameworks"; | ||
| 353 | outputPaths = ( | 353 | outputPaths = ( |
| 354 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JCategoryKit.framework", | 354 | "$(DERIVED_FILE_DIR)/Pods-JCategoryKit_Example-checkManifestLockResult.txt", |
| 355 | ); | 355 | ); |
| 356 | runOnlyForDeploymentPostprocessing = 0; | 356 | runOnlyForDeploymentPostprocessing = 0; |
| 357 | shellPath = /bin/sh; | 357 | shellPath = /bin/sh; |
| 358 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-frameworks.sh\"\n"; | 358 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; |
| 359 | showEnvVarsInLog = 0; | 359 | showEnvVarsInLog = 0; |
| 360 | }; | 360 | }; |
| 361 | E7B9F2BB3382B44E49A9CEEE /* [CP] Embed Pods Frameworks */ = { | 361 | E7B9F2BB3382B44E49A9CEEE /* [CP] Embed Pods Frameworks */ = { | ... | ... |
| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | // | 7 | // |
| 8 | 8 | ||
| 9 | #import "STViewController.h" | 9 | #import "STViewController.h" |
| 10 | #import <Person.h> | ||
| 10 | 11 | ||
| 11 | @interface STViewController () | 12 | @interface STViewController () |
| 12 | 13 | ||
| ... | @@ -17,7 +18,8 @@ | ... | @@ -17,7 +18,8 @@ |
| 17 | - (void)viewDidLoad | 18 | - (void)viewDidLoad |
| 18 | { | 19 | { |
| 19 | [super viewDidLoad]; | 20 | [super viewDidLoad]; |
| 20 | // Do any additional setup after loading the view, typically from a nib. | 21 | Person *p = [[Person alloc] init]; |
| 22 | [p eat]; | ||
| 21 | } | 23 | } |
| 22 | 24 | ||
| 23 | - (void)didReceiveMemoryWarning | 25 | - (void)didReceiveMemoryWarning | ... | ... |
Example/Podfile.lock
0 → 100644
| 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 | - JCategoryKit (1.0.0) | ||
| 8 | |||
| 9 | DEPENDENCIES: | ||
| 10 | - FBSnapshotTestCase | ||
| 11 | - JCategoryKit (from `../`) | ||
| 12 | |||
| 13 | SPEC REPOS: | ||
| 14 | trunk: | ||
| 15 | - FBSnapshotTestCase | ||
| 16 | |||
| 17 | EXTERNAL SOURCES: | ||
| 18 | JCategoryKit: | ||
| 19 | :path: "../" | ||
| 20 | |||
| 21 | SPEC CHECKSUMS: | ||
| 22 | FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a | ||
| 23 | JCategoryKit: 1ee089cd5593b2515c06f8b99e9eb02fdac4eecd | ||
| 24 | |||
| 25 | PODFILE CHECKSUM: 7301f47448ac58a307221e0e73e2a910d76a70ab | ||
| 26 | |||
| 27 | COCOAPODS: 1.11.2 |
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h
0 → 100644
| 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 <UIKit/UIKit.h> | ||
| 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 |
Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m
0 → 100644
| 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 <FBSnapshotTestCase/UIApplication+StrictKeyWindow.h> | ||
| 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 |
| 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 <UIKit/UIKit.h> | ||
| 32 | |||
| 33 | @interface UIImage (Compare) | ||
| 34 | |||
| 35 | - (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance; | ||
| 36 | |||
| 37 | @end |
| 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 <FBSnapshotTestCase/UIImage+Compare.h> | ||
| 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 |
| 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 <UIKit/UIKit.h> | ||
| 32 | |||
| 33 | @interface UIImage (Diff) | ||
| 34 | |||
| 35 | - (UIImage *)fb_diffWithImage:(UIImage *)image; | ||
| 36 | |||
| 37 | @end |
| 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 <FBSnapshotTestCase/UIImage+Diff.h> | ||
| 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 |
| 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 <UIKit/UIKit.h> | ||
| 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 |
| 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 <FBSnapshotTestCase/UIImage+Snapshot.h> | ||
| 12 | #import <FBSnapshotTestCase/UIApplication+StrictKeyWindow.h> | ||
| 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 |
| 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 <FBSnapshotTestCase/FBSnapshotTestCasePlatform.h> | ||
| 12 | #import <FBSnapshotTestCase/FBSnapshotTestController.h> | ||
| 13 | |||
| 14 | #import <QuartzCore/QuartzCore.h> | ||
| 15 | |||
| 16 | #import <UIKit/UIKit.h> | ||
| 17 | |||
| 18 | #import <XCTest/XCTest.h> | ||
| 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 |
| 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 <FBSnapshotTestCase/FBSnapshotTestCase.h> | ||
| 12 | #import <FBSnapshotTestCase/FBSnapshotTestController.h> | ||
| 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 |
| 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 <Foundation/Foundation.h> | ||
| 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 |
| 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 <FBSnapshotTestCase/FBSnapshotTestCasePlatform.h> | ||
| 12 | #import <FBSnapshotTestCase/UIApplication+StrictKeyWindow.h> | ||
| 13 | #import <UIKit/UIKit.h> | ||
| 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 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 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 <Foundation/Foundation.h> | ||
| 12 | #import <UIKit/UIKit.h> | ||
| 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 |
This diff is collapsed.
Click to expand it.
| 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 |
Example/Pods/FBSnapshotTestCase/LICENSE
0 → 100644
| 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. |
Example/Pods/FBSnapshotTestCase/README.md
0 → 100644
| 1 | FBSnapshotTestCase | ||
| 2 | ====================== | ||
| 3 | |||
| 4 | [](https://travis-ci.org/facebook/ios-snapshot-test-case) [](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 |  | ||
| 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`. |
| 1 | { | ||
| 2 | "name": "JCategoryKit", | ||
| 3 | "version": "1.0.0", | ||
| 4 | "summary": "A short description of JCategoryKit.", | ||
| 5 | "description": "TODO: Add long description of the pod here.", | ||
| 6 | "homepage": "https://github.com/weixq/JCategoryKit", | ||
| 7 | "license": { | ||
| 8 | "type": "MIT", | ||
| 9 | "file": "LICENSE" | ||
| 10 | }, | ||
| 11 | "authors": { | ||
| 12 | "weixq": "weixiaoqiang@situdata.com" | ||
| 13 | }, | ||
| 14 | "source": { | ||
| 15 | "git": "http://gitlab.situdata.com/weixiaoqiang/JCategoryKit.git", | ||
| 16 | "tag": "1.0.0" | ||
| 17 | }, | ||
| 18 | "platforms": { | ||
| 19 | "ios": "9.0" | ||
| 20 | }, | ||
| 21 | "source_files": "JCategoryKit/Classes/**/*" | ||
| 22 | } |
Example/Pods/Manifest.lock
0 → 100644
| 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 | - JCategoryKit (1.0.0) | ||
| 8 | |||
| 9 | DEPENDENCIES: | ||
| 10 | - FBSnapshotTestCase | ||
| 11 | - JCategoryKit (from `../`) | ||
| 12 | |||
| 13 | SPEC REPOS: | ||
| 14 | trunk: | ||
| 15 | - FBSnapshotTestCase | ||
| 16 | |||
| 17 | EXTERNAL SOURCES: | ||
| 18 | JCategoryKit: | ||
| 19 | :path: "../" | ||
| 20 | |||
| 21 | SPEC CHECKSUMS: | ||
| 22 | FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a | ||
| 23 | JCategoryKit: 1ee089cd5593b2515c06f8b99e9eb02fdac4eecd | ||
| 24 | |||
| 25 | PODFILE CHECKSUM: 7301f47448ac58a307221e0e73e2a910d76a70ab | ||
| 26 | |||
| 27 | COCOAPODS: 1.11.2 |
Example/Pods/Pods.xcodeproj/project.pbxproj
0 → 100644
This diff is collapsed.
Click to expand it.
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 3 | <plist version="1.0"> | ||
| 4 | <dict> | ||
| 5 | <key>CFBundleDevelopmentRegion</key> | ||
| 6 | <string>en</string> | ||
| 7 | <key>CFBundleExecutable</key> | ||
| 8 | <string>${EXECUTABLE_NAME}</string> | ||
| 9 | <key>CFBundleIdentifier</key> | ||
| 10 | <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> | ||
| 11 | <key>CFBundleInfoDictionaryVersion</key> | ||
| 12 | <string>6.0</string> | ||
| 13 | <key>CFBundleName</key> | ||
| 14 | <string>${PRODUCT_NAME}</string> | ||
| 15 | <key>CFBundlePackageType</key> | ||
| 16 | <string>FMWK</string> | ||
| 17 | <key>CFBundleShortVersionString</key> | ||
| 18 | <string>2.1.4</string> | ||
| 19 | <key>CFBundleSignature</key> | ||
| 20 | <string>????</string> | ||
| 21 | <key>CFBundleVersion</key> | ||
| 22 | <string>${CURRENT_PROJECT_VERSION}</string> | ||
| 23 | <key>NSPrincipalClass</key> | ||
| 24 | <string></string> | ||
| 25 | </dict> | ||
| 26 | </plist> |
| 1 | #ifdef __OBJC__ | ||
| 2 | #import <UIKit/UIKit.h> | ||
| 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 |
| 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase | ||
| 3 | ENABLE_BITCODE = NO | ||
| 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" | ||
| 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 6 | LIBRARY_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift | ||
| 7 | OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" | ||
| 8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS | ||
| 9 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 11 | PODS_ROOT = ${SRCROOT} | ||
| 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSnapshotTestCase | ||
| 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} | ||
| 15 | SKIP_INSTALL = YES | ||
| 16 | SWIFT_INCLUDE_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" | ||
| 17 | SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" | ||
| 18 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
| 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase | ||
| 3 | ENABLE_BITCODE = NO | ||
| 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" | ||
| 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 6 | LIBRARY_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift | ||
| 7 | OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" | ||
| 8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS | ||
| 9 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 11 | PODS_ROOT = ${SRCROOT} | ||
| 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSnapshotTestCase | ||
| 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} | ||
| 15 | SKIP_INSTALL = YES | ||
| 16 | SWIFT_INCLUDE_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" | ||
| 17 | SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" | ||
| 18 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 3 | <plist version="1.0"> | ||
| 4 | <dict> | ||
| 5 | <key>CFBundleDevelopmentRegion</key> | ||
| 6 | <string>en</string> | ||
| 7 | <key>CFBundleExecutable</key> | ||
| 8 | <string>${EXECUTABLE_NAME}</string> | ||
| 9 | <key>CFBundleIdentifier</key> | ||
| 10 | <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> | ||
| 11 | <key>CFBundleInfoDictionaryVersion</key> | ||
| 12 | <string>6.0</string> | ||
| 13 | <key>CFBundleName</key> | ||
| 14 | <string>${PRODUCT_NAME}</string> | ||
| 15 | <key>CFBundlePackageType</key> | ||
| 16 | <string>FMWK</string> | ||
| 17 | <key>CFBundleShortVersionString</key> | ||
| 18 | <string>1.0.0</string> | ||
| 19 | <key>CFBundleSignature</key> | ||
| 20 | <string>????</string> | ||
| 21 | <key>CFBundleVersion</key> | ||
| 22 | <string>${CURRENT_PROJECT_VERSION}</string> | ||
| 23 | <key>NSPrincipalClass</key> | ||
| 24 | <string></string> | ||
| 25 | </dict> | ||
| 26 | </plist> |
| 1 | #ifdef __OBJC__ | ||
| 2 | #import <UIKit/UIKit.h> | ||
| 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 "Person.h" | ||
| 14 | |||
| 15 | FOUNDATION_EXPORT double JCategoryKitVersionNumber; | ||
| 16 | FOUNDATION_EXPORT const unsigned char JCategoryKitVersionString[]; | ||
| 17 |
| 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit | ||
| 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 4 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 6 | PODS_ROOT = ${SRCROOT} | ||
| 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. | ||
| 8 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} | ||
| 10 | SKIP_INSTALL = YES | ||
| 11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
| 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit | ||
| 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 4 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 6 | PODS_ROOT = ${SRCROOT} | ||
| 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. | ||
| 8 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} | ||
| 10 | SKIP_INSTALL = YES | ||
| 11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
Example/Pods/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-Info.plist
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 3 | <plist version="1.0"> | ||
| 4 | <dict> | ||
| 5 | <key>CFBundleDevelopmentRegion</key> | ||
| 6 | <string>en</string> | ||
| 7 | <key>CFBundleExecutable</key> | ||
| 8 | <string>${EXECUTABLE_NAME}</string> | ||
| 9 | <key>CFBundleIdentifier</key> | ||
| 10 | <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> | ||
| 11 | <key>CFBundleInfoDictionaryVersion</key> | ||
| 12 | <string>6.0</string> | ||
| 13 | <key>CFBundleName</key> | ||
| 14 | <string>${PRODUCT_NAME}</string> | ||
| 15 | <key>CFBundlePackageType</key> | ||
| 16 | <string>FMWK</string> | ||
| 17 | <key>CFBundleShortVersionString</key> | ||
| 18 | <string>1.0.0</string> | ||
| 19 | <key>CFBundleSignature</key> | ||
| 20 | <string>????</string> | ||
| 21 | <key>CFBundleVersion</key> | ||
| 22 | <string>${CURRENT_PROJECT_VERSION}</string> | ||
| 23 | <key>NSPrincipalClass</key> | ||
| 24 | <string></string> | ||
| 25 | </dict> | ||
| 26 | </plist> |
| 1 | # Acknowledgements | ||
| 2 | This application makes use of the following third party libraries: | ||
| 3 | |||
| 4 | ## JCategoryKit | ||
| 5 | |||
| 6 | Copyright (c) 2021 weixq <weixiaoqiang@situdata.com> | ||
| 7 | |||
| 8 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 9 | of this software and associated documentation files (the "Software"), to deal | ||
| 10 | in the Software without restriction, including without limitation the rights | ||
| 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 12 | copies of the Software, and to permit persons to whom the Software is | ||
| 13 | furnished to do so, subject to the following conditions: | ||
| 14 | |||
| 15 | The above copyright notice and this permission notice shall be included in | ||
| 16 | all copies or substantial portions of the Software. | ||
| 17 | |||
| 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 24 | THE SOFTWARE. | ||
| 25 | |||
| 26 | Generated by CocoaPods - https://cocoapods.org |
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 3 | <plist version="1.0"> | ||
| 4 | <dict> | ||
| 5 | <key>PreferenceSpecifiers</key> | ||
| 6 | <array> | ||
| 7 | <dict> | ||
| 8 | <key>FooterText</key> | ||
| 9 | <string>This application makes use of the following third party libraries:</string> | ||
| 10 | <key>Title</key> | ||
| 11 | <string>Acknowledgements</string> | ||
| 12 | <key>Type</key> | ||
| 13 | <string>PSGroupSpecifier</string> | ||
| 14 | </dict> | ||
| 15 | <dict> | ||
| 16 | <key>FooterText</key> | ||
| 17 | <string>Copyright (c) 2021 weixq <weixiaoqiang@situdata.com> | ||
| 18 | |||
| 19 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 20 | of this software and associated documentation files (the "Software"), to deal | ||
| 21 | in the Software without restriction, including without limitation the rights | ||
| 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 23 | copies of the Software, and to permit persons to whom the Software is | ||
| 24 | furnished to do so, subject to the following conditions: | ||
| 25 | |||
| 26 | The above copyright notice and this permission notice shall be included in | ||
| 27 | all copies or substantial portions of the Software. | ||
| 28 | |||
| 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 35 | THE SOFTWARE. | ||
| 36 | </string> | ||
| 37 | <key>License</key> | ||
| 38 | <string>MIT</string> | ||
| 39 | <key>Title</key> | ||
| 40 | <string>JCategoryKit</string> | ||
| 41 | <key>Type</key> | ||
| 42 | <string>PSGroupSpecifier</string> | ||
| 43 | </dict> | ||
| 44 | <dict> | ||
| 45 | <key>FooterText</key> | ||
| 46 | <string>Generated by CocoaPods - https://cocoapods.org</string> | ||
| 47 | <key>Title</key> | ||
| 48 | <string></string> | ||
| 49 | <key>Type</key> | ||
| 50 | <string>PSGroupSpecifier</string> | ||
| 51 | </dict> | ||
| 52 | </array> | ||
| 53 | <key>StringsTable</key> | ||
| 54 | <string>Acknowledgements</string> | ||
| 55 | <key>Title</key> | ||
| 56 | <string>Acknowledgements</string> | ||
| 57 | </dict> | ||
| 58 | </plist> |
Example/Pods/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-frameworks.sh
0 → 100755
| 1 | #!/bin/sh | ||
| 2 | set -e | ||
| 3 | set -u | ||
| 4 | set -o pipefail | ||
| 5 | |||
| 6 | function on_error { | ||
| 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" | ||
| 8 | } | ||
| 9 | trap 'on_error $LINENO' ERR | ||
| 10 | |||
| 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then | ||
| 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy | ||
| 13 | # frameworks to, so exit 0 (signalling the script phase was successful). | ||
| 14 | exit 0 | ||
| 15 | fi | ||
| 16 | |||
| 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" | ||
| 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" | ||
| 19 | |||
| 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" | ||
| 21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" | ||
| 22 | BCSYMBOLMAP_DIR="BCSymbolMaps" | ||
| 23 | |||
| 24 | |||
| 25 | # This protects against multiple targets copying the same framework dependency at the same time. The solution | ||
| 26 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html | ||
| 27 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") | ||
| 28 | |||
| 29 | # Copies and strips a vendored framework | ||
| 30 | install_framework() | ||
| 31 | { | ||
| 32 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then | ||
| 33 | local source="${BUILT_PRODUCTS_DIR}/$1" | ||
| 34 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then | ||
| 35 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" | ||
| 36 | elif [ -r "$1" ]; then | ||
| 37 | local source="$1" | ||
| 38 | fi | ||
| 39 | |||
| 40 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" | ||
| 41 | |||
| 42 | if [ -L "${source}" ]; then | ||
| 43 | echo "Symlinked..." | ||
| 44 | source="$(readlink "${source}")" | ||
| 45 | fi | ||
| 46 | |||
| 47 | if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then | ||
| 48 | # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied | ||
| 49 | find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do | ||
| 50 | echo "Installing $f" | ||
| 51 | install_bcsymbolmap "$f" "$destination" | ||
| 52 | rm "$f" | ||
| 53 | done | ||
| 54 | rmdir "${source}/${BCSYMBOLMAP_DIR}" | ||
| 55 | fi | ||
| 56 | |||
| 57 | # Use filter instead of exclude so missing patterns don't throw errors. | ||
| 58 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" | ||
| 59 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" | ||
| 60 | |||
| 61 | local basename | ||
| 62 | basename="$(basename -s .framework "$1")" | ||
| 63 | binary="${destination}/${basename}.framework/${basename}" | ||
| 64 | |||
| 65 | if ! [ -r "$binary" ]; then | ||
| 66 | binary="${destination}/${basename}" | ||
| 67 | elif [ -L "${binary}" ]; then | ||
| 68 | echo "Destination binary is symlinked..." | ||
| 69 | dirname="$(dirname "${binary}")" | ||
| 70 | binary="${dirname}/$(readlink "${binary}")" | ||
| 71 | fi | ||
| 72 | |||
| 73 | # Strip invalid architectures so "fat" simulator / device frameworks work on device | ||
| 74 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then | ||
| 75 | strip_invalid_archs "$binary" | ||
| 76 | fi | ||
| 77 | |||
| 78 | # Resign the code if required by the build settings to avoid unstable apps | ||
| 79 | code_sign_if_enabled "${destination}/$(basename "$1")" | ||
| 80 | |||
| 81 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. | ||
| 82 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then | ||
| 83 | local swift_runtime_libs | ||
| 84 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) | ||
| 85 | for lib in $swift_runtime_libs; do | ||
| 86 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" | ||
| 87 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" | ||
| 88 | code_sign_if_enabled "${destination}/${lib}" | ||
| 89 | done | ||
| 90 | fi | ||
| 91 | } | ||
| 92 | # Copies and strips a vendored dSYM | ||
| 93 | install_dsym() { | ||
| 94 | local source="$1" | ||
| 95 | warn_missing_arch=${2:-true} | ||
| 96 | if [ -r "$source" ]; then | ||
| 97 | # Copy the dSYM into the targets temp dir. | ||
| 98 | 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}\"" | ||
| 99 | 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}" | ||
| 100 | |||
| 101 | local basename | ||
| 102 | basename="$(basename -s .dSYM "$source")" | ||
| 103 | binary_name="$(ls "$source/Contents/Resources/DWARF")" | ||
| 104 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" | ||
| 105 | |||
| 106 | # Strip invalid architectures from the dSYM. | ||
| 107 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then | ||
| 108 | strip_invalid_archs "$binary" "$warn_missing_arch" | ||
| 109 | fi | ||
| 110 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then | ||
| 111 | # Move the stripped file into its final destination. | ||
| 112 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" | ||
| 113 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" | ||
| 114 | else | ||
| 115 | # 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. | ||
| 116 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}" | ||
| 117 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" | ||
| 118 | fi | ||
| 119 | fi | ||
| 120 | } | ||
| 121 | |||
| 122 | # Used as a return value for each invocation of `strip_invalid_archs` function. | ||
| 123 | STRIP_BINARY_RETVAL=0 | ||
| 124 | |||
| 125 | # Strip invalid architectures | ||
| 126 | strip_invalid_archs() { | ||
| 127 | binary="$1" | ||
| 128 | warn_missing_arch=${2:-true} | ||
| 129 | # Get architectures for current target binary | ||
| 130 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" | ||
| 131 | # Intersect them with the architectures we are building for | ||
| 132 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" | ||
| 133 | # If there are no archs supported by this binary then warn the user | ||
| 134 | if [[ -z "$intersected_archs" ]]; then | ||
| 135 | if [[ "$warn_missing_arch" == "true" ]]; then | ||
| 136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." | ||
| 137 | fi | ||
| 138 | STRIP_BINARY_RETVAL=1 | ||
| 139 | return | ||
| 140 | fi | ||
| 141 | stripped="" | ||
| 142 | for arch in $binary_archs; do | ||
| 143 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then | ||
| 144 | # Strip non-valid architectures in-place | ||
| 145 | lipo -remove "$arch" -output "$binary" "$binary" | ||
| 146 | stripped="$stripped $arch" | ||
| 147 | fi | ||
| 148 | done | ||
| 149 | if [[ "$stripped" ]]; then | ||
| 150 | echo "Stripped $binary of architectures:$stripped" | ||
| 151 | fi | ||
| 152 | STRIP_BINARY_RETVAL=0 | ||
| 153 | } | ||
| 154 | |||
| 155 | # Copies the bcsymbolmap files of a vendored framework | ||
| 156 | install_bcsymbolmap() { | ||
| 157 | local bcsymbolmap_path="$1" | ||
| 158 | local destination="${BUILT_PRODUCTS_DIR}" | ||
| 159 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" | ||
| 160 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" | ||
| 161 | } | ||
| 162 | |||
| 163 | # Signs a framework with the provided identity | ||
| 164 | code_sign_if_enabled() { | ||
| 165 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then | ||
| 166 | # Use the current code_sign_identity | ||
| 167 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" | ||
| 168 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" | ||
| 169 | |||
| 170 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then | ||
| 171 | code_sign_cmd="$code_sign_cmd &" | ||
| 172 | fi | ||
| 173 | echo "$code_sign_cmd" | ||
| 174 | eval "$code_sign_cmd" | ||
| 175 | fi | ||
| 176 | } | ||
| 177 | |||
| 178 | if [[ "$CONFIGURATION" == "Debug" ]]; then | ||
| 179 | install_framework "${BUILT_PRODUCTS_DIR}/JCategoryKit/JCategoryKit.framework" | ||
| 180 | fi | ||
| 181 | if [[ "$CONFIGURATION" == "Release" ]]; then | ||
| 182 | install_framework "${BUILT_PRODUCTS_DIR}/JCategoryKit/JCategoryKit.framework" | ||
| 183 | fi | ||
| 184 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then | ||
| 185 | wait | ||
| 186 | fi |
Example/Pods/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example-umbrella.h
0 → 100644
| 1 | #ifdef __OBJC__ | ||
| 2 | #import <UIKit/UIKit.h> | ||
| 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_JCategoryKit_ExampleVersionNumber; | ||
| 15 | FOUNDATION_EXPORT const unsigned char Pods_JCategoryKit_ExampleVersionString[]; | ||
| 16 |
Example/Pods/Target Support Files/Pods-JCategoryKit_Example/Pods-JCategoryKit_Example.debug.xcconfig
0 → 100644
| 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit" | ||
| 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit/JCategoryKit.framework/Headers" | ||
| 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' | ||
| 6 | OTHER_LDFLAGS = $(inherited) -framework "JCategoryKit" | ||
| 7 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 9 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. | ||
| 10 | PODS_ROOT = ${SRCROOT}/Pods | ||
| 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
| 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit" | ||
| 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit/JCategoryKit.framework/Headers" | ||
| 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' | ||
| 6 | OTHER_LDFLAGS = $(inherited) -framework "JCategoryKit" | ||
| 7 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 9 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. | ||
| 10 | PODS_ROOT = ${SRCROOT}/Pods | ||
| 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
Example/Pods/Target Support Files/Pods-JCategoryKit_Tests/Pods-JCategoryKit_Tests-Info.plist
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 3 | <plist version="1.0"> | ||
| 4 | <dict> | ||
| 5 | <key>CFBundleDevelopmentRegion</key> | ||
| 6 | <string>en</string> | ||
| 7 | <key>CFBundleExecutable</key> | ||
| 8 | <string>${EXECUTABLE_NAME}</string> | ||
| 9 | <key>CFBundleIdentifier</key> | ||
| 10 | <string>${PRODUCT_BUNDLE_IDENTIFIER}</string> | ||
| 11 | <key>CFBundleInfoDictionaryVersion</key> | ||
| 12 | <string>6.0</string> | ||
| 13 | <key>CFBundleName</key> | ||
| 14 | <string>${PRODUCT_NAME}</string> | ||
| 15 | <key>CFBundlePackageType</key> | ||
| 16 | <string>FMWK</string> | ||
| 17 | <key>CFBundleShortVersionString</key> | ||
| 18 | <string>1.0.0</string> | ||
| 19 | <key>CFBundleSignature</key> | ||
| 20 | <string>????</string> | ||
| 21 | <key>CFBundleVersion</key> | ||
| 22 | <string>${CURRENT_PROJECT_VERSION}</string> | ||
| 23 | <key>NSPrincipalClass</key> | ||
| 24 | <string></string> | ||
| 25 | </dict> | ||
| 26 | </plist> |
| 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 |
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| 3 | <plist version="1.0"> | ||
| 4 | <dict> | ||
| 5 | <key>PreferenceSpecifiers</key> | ||
| 6 | <array> | ||
| 7 | <dict> | ||
| 8 | <key>FooterText</key> | ||
| 9 | <string>This application makes use of the following third party libraries:</string> | ||
| 10 | <key>Title</key> | ||
| 11 | <string>Acknowledgements</string> | ||
| 12 | <key>Type</key> | ||
| 13 | <string>PSGroupSpecifier</string> | ||
| 14 | </dict> | ||
| 15 | <dict> | ||
| 16 | <key>FooterText</key> | ||
| 17 | <string>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 | </string> | ||
| 47 | <key>License</key> | ||
| 48 | <string>BSD</string> | ||
| 49 | <key>Title</key> | ||
| 50 | <string>FBSnapshotTestCase</string> | ||
| 51 | <key>Type</key> | ||
| 52 | <string>PSGroupSpecifier</string> | ||
| 53 | </dict> | ||
| 54 | <dict> | ||
| 55 | <key>FooterText</key> | ||
| 56 | <string>Generated by CocoaPods - https://cocoapods.org</string> | ||
| 57 | <key>Title</key> | ||
| 58 | <string></string> | ||
| 59 | <key>Type</key> | ||
| 60 | <string>PSGroupSpecifier</string> | ||
| 61 | </dict> | ||
| 62 | </array> | ||
| 63 | <key>StringsTable</key> | ||
| 64 | <string>Acknowledgements</string> | ||
| 65 | <key>Title</key> | ||
| 66 | <string>Acknowledgements</string> | ||
| 67 | </dict> | ||
| 68 | </plist> |
Example/Pods/Target Support Files/Pods-JCategoryKit_Tests/Pods-JCategoryKit_Tests-frameworks.sh
0 → 100755
| 1 | #!/bin/sh | ||
| 2 | set -e | ||
| 3 | set -u | ||
| 4 | set -o pipefail | ||
| 5 | |||
| 6 | function on_error { | ||
| 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" | ||
| 8 | } | ||
| 9 | trap 'on_error $LINENO' ERR | ||
| 10 | |||
| 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then | ||
| 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy | ||
| 13 | # frameworks to, so exit 0 (signalling the script phase was successful). | ||
| 14 | exit 0 | ||
| 15 | fi | ||
| 16 | |||
| 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" | ||
| 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" | ||
| 19 | |||
| 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" | ||
| 21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" | ||
| 22 | BCSYMBOLMAP_DIR="BCSymbolMaps" | ||
| 23 | |||
| 24 | |||
| 25 | # This protects against multiple targets copying the same framework dependency at the same time. The solution | ||
| 26 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html | ||
| 27 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") | ||
| 28 | |||
| 29 | # Copies and strips a vendored framework | ||
| 30 | install_framework() | ||
| 31 | { | ||
| 32 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then | ||
| 33 | local source="${BUILT_PRODUCTS_DIR}/$1" | ||
| 34 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then | ||
| 35 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" | ||
| 36 | elif [ -r "$1" ]; then | ||
| 37 | local source="$1" | ||
| 38 | fi | ||
| 39 | |||
| 40 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" | ||
| 41 | |||
| 42 | if [ -L "${source}" ]; then | ||
| 43 | echo "Symlinked..." | ||
| 44 | source="$(readlink "${source}")" | ||
| 45 | fi | ||
| 46 | |||
| 47 | if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then | ||
| 48 | # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied | ||
| 49 | find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do | ||
| 50 | echo "Installing $f" | ||
| 51 | install_bcsymbolmap "$f" "$destination" | ||
| 52 | rm "$f" | ||
| 53 | done | ||
| 54 | rmdir "${source}/${BCSYMBOLMAP_DIR}" | ||
| 55 | fi | ||
| 56 | |||
| 57 | # Use filter instead of exclude so missing patterns don't throw errors. | ||
| 58 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" | ||
| 59 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" | ||
| 60 | |||
| 61 | local basename | ||
| 62 | basename="$(basename -s .framework "$1")" | ||
| 63 | binary="${destination}/${basename}.framework/${basename}" | ||
| 64 | |||
| 65 | if ! [ -r "$binary" ]; then | ||
| 66 | binary="${destination}/${basename}" | ||
| 67 | elif [ -L "${binary}" ]; then | ||
| 68 | echo "Destination binary is symlinked..." | ||
| 69 | dirname="$(dirname "${binary}")" | ||
| 70 | binary="${dirname}/$(readlink "${binary}")" | ||
| 71 | fi | ||
| 72 | |||
| 73 | # Strip invalid architectures so "fat" simulator / device frameworks work on device | ||
| 74 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then | ||
| 75 | strip_invalid_archs "$binary" | ||
| 76 | fi | ||
| 77 | |||
| 78 | # Resign the code if required by the build settings to avoid unstable apps | ||
| 79 | code_sign_if_enabled "${destination}/$(basename "$1")" | ||
| 80 | |||
| 81 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. | ||
| 82 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then | ||
| 83 | local swift_runtime_libs | ||
| 84 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) | ||
| 85 | for lib in $swift_runtime_libs; do | ||
| 86 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" | ||
| 87 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" | ||
| 88 | code_sign_if_enabled "${destination}/${lib}" | ||
| 89 | done | ||
| 90 | fi | ||
| 91 | } | ||
| 92 | # Copies and strips a vendored dSYM | ||
| 93 | install_dsym() { | ||
| 94 | local source="$1" | ||
| 95 | warn_missing_arch=${2:-true} | ||
| 96 | if [ -r "$source" ]; then | ||
| 97 | # Copy the dSYM into the targets temp dir. | ||
| 98 | 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}\"" | ||
| 99 | 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}" | ||
| 100 | |||
| 101 | local basename | ||
| 102 | basename="$(basename -s .dSYM "$source")" | ||
| 103 | binary_name="$(ls "$source/Contents/Resources/DWARF")" | ||
| 104 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" | ||
| 105 | |||
| 106 | # Strip invalid architectures from the dSYM. | ||
| 107 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then | ||
| 108 | strip_invalid_archs "$binary" "$warn_missing_arch" | ||
| 109 | fi | ||
| 110 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then | ||
| 111 | # Move the stripped file into its final destination. | ||
| 112 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" | ||
| 113 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" | ||
| 114 | else | ||
| 115 | # 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. | ||
| 116 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}" | ||
| 117 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" | ||
| 118 | fi | ||
| 119 | fi | ||
| 120 | } | ||
| 121 | |||
| 122 | # Used as a return value for each invocation of `strip_invalid_archs` function. | ||
| 123 | STRIP_BINARY_RETVAL=0 | ||
| 124 | |||
| 125 | # Strip invalid architectures | ||
| 126 | strip_invalid_archs() { | ||
| 127 | binary="$1" | ||
| 128 | warn_missing_arch=${2:-true} | ||
| 129 | # Get architectures for current target binary | ||
| 130 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" | ||
| 131 | # Intersect them with the architectures we are building for | ||
| 132 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" | ||
| 133 | # If there are no archs supported by this binary then warn the user | ||
| 134 | if [[ -z "$intersected_archs" ]]; then | ||
| 135 | if [[ "$warn_missing_arch" == "true" ]]; then | ||
| 136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." | ||
| 137 | fi | ||
| 138 | STRIP_BINARY_RETVAL=1 | ||
| 139 | return | ||
| 140 | fi | ||
| 141 | stripped="" | ||
| 142 | for arch in $binary_archs; do | ||
| 143 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then | ||
| 144 | # Strip non-valid architectures in-place | ||
| 145 | lipo -remove "$arch" -output "$binary" "$binary" | ||
| 146 | stripped="$stripped $arch" | ||
| 147 | fi | ||
| 148 | done | ||
| 149 | if [[ "$stripped" ]]; then | ||
| 150 | echo "Stripped $binary of architectures:$stripped" | ||
| 151 | fi | ||
| 152 | STRIP_BINARY_RETVAL=0 | ||
| 153 | } | ||
| 154 | |||
| 155 | # Copies the bcsymbolmap files of a vendored framework | ||
| 156 | install_bcsymbolmap() { | ||
| 157 | local bcsymbolmap_path="$1" | ||
| 158 | local destination="${BUILT_PRODUCTS_DIR}" | ||
| 159 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" | ||
| 160 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" | ||
| 161 | } | ||
| 162 | |||
| 163 | # Signs a framework with the provided identity | ||
| 164 | code_sign_if_enabled() { | ||
| 165 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then | ||
| 166 | # Use the current code_sign_identity | ||
| 167 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" | ||
| 168 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" | ||
| 169 | |||
| 170 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then | ||
| 171 | code_sign_cmd="$code_sign_cmd &" | ||
| 172 | fi | ||
| 173 | echo "$code_sign_cmd" | ||
| 174 | eval "$code_sign_cmd" | ||
| 175 | fi | ||
| 176 | } | ||
| 177 | |||
| 178 | if [[ "$CONFIGURATION" == "Debug" ]]; then | ||
| 179 | install_framework "${BUILT_PRODUCTS_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework" | ||
| 180 | fi | ||
| 181 | if [[ "$CONFIGURATION" == "Release" ]]; then | ||
| 182 | install_framework "${BUILT_PRODUCTS_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework" | ||
| 183 | fi | ||
| 184 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then | ||
| 185 | wait | ||
| 186 | fi |
Example/Pods/Target Support Files/Pods-JCategoryKit_Tests/Pods-JCategoryKit_Tests-umbrella.h
0 → 100644
| 1 | #ifdef __OBJC__ | ||
| 2 | #import <UIKit/UIKit.h> | ||
| 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_JCategoryKit_TestsVersionNumber; | ||
| 15 | FOUNDATION_EXPORT const unsigned char Pods_JCategoryKit_TestsVersionString[]; | ||
| 16 |
Example/Pods/Target Support Files/Pods-JCategoryKit_Tests/Pods-JCategoryKit_Tests.debug.xcconfig
0 → 100644
| 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES | ||
| 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit" | ||
| 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit/JCategoryKit.framework/Headers" | ||
| 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift "$(PLATFORM_DIR)/Developer/Library/Frameworks" '@executable_path/Frameworks' '@loader_path/Frameworks' | ||
| 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift | ||
| 8 | OTHER_LDFLAGS = $(inherited) -framework "FBSnapshotTestCase" -framework "Foundation" -framework "JCategoryKit" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" | ||
| 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS | ||
| 10 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. | ||
| 13 | PODS_ROOT = ${SRCROOT}/Pods | ||
| 14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
Example/Pods/Target Support Files/Pods-JCategoryKit_Tests/Pods-JCategoryKit_Tests.release.xcconfig
0 → 100644
| 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES | ||
| 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO | ||
| 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit" | ||
| 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 | ||
| 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JCategoryKit/JCategoryKit.framework/Headers" | ||
| 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift "$(PLATFORM_DIR)/Developer/Library/Frameworks" '@executable_path/Frameworks' '@loader_path/Frameworks' | ||
| 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift | ||
| 8 | OTHER_LDFLAGS = $(inherited) -framework "FBSnapshotTestCase" -framework "Foundation" -framework "JCategoryKit" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" | ||
| 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS | ||
| 10 | PODS_BUILD_DIR = ${BUILD_DIR} | ||
| 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) | ||
| 12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. | ||
| 13 | PODS_ROOT = ${SRCROOT}/Pods | ||
| 14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates | ||
| 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES |
| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | ||
| 9 | Pod::Spec.new do |s| | 9 | Pod::Spec.new do |s| |
| 10 | s.name = 'JCategoryKit' | 10 | s.name = 'JCategoryKit' |
| 11 | s.version = '0.1.0' | 11 | s.version = '1.0.0' |
| 12 | s.summary = 'A short description of JCategoryKit.' | 12 | s.summary = 'A short description of JCategoryKit.' |
| 13 | 13 | ||
| 14 | # This description is used to generate tags and improve search results. | 14 | # This description is used to generate tags and improve search results. |
| ... | @@ -25,7 +25,7 @@ TODO: Add long description of the pod here. | ... | @@ -25,7 +25,7 @@ TODO: Add long description of the pod here. |
| 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' | 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' |
| 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } | 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } |
| 27 | s.author = { 'weixq' => 'weixiaoqiang@situdata.com' } | 27 | s.author = { 'weixq' => 'weixiaoqiang@situdata.com' } |
| 28 | s.source = { :git => 'https://github.com/weixq/JCategoryKit.git', :tag => s.version.to_s } | 28 | s.source = { :git => 'http://gitlab.situdata.com/weixiaoqiang/JCategoryKit.git', :tag => s.version.to_s } |
| 29 | # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>' | 29 | # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>' |
| 30 | 30 | ||
| 31 | s.ios.deployment_target = '9.0' | 31 | s.ios.deployment_target = '9.0' | ... | ... |
JCategoryKit/Classes/Person.h
0 → 100644
JCategoryKit/Classes/Person.m
0 → 100644
JCategoryKit/Classes/ReplaceMe.m
deleted
100644 → 0
File mode changed
LICENSE 2
0 → 100644
| 1 | This project is licensed under the MIT license. | ||
| 2 | |||
| 3 | Copyright (c) 2013 - 2014 CocoaPods Dev Team | ||
| 4 | |||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | of this software and associated documentation files (the "Software"), to deal | ||
| 7 | in the Software without restriction, including without limitation the rights | ||
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | copies of the Software, and to permit persons to whom the Software is | ||
| 10 | furnished to do so, subject to the following conditions: | ||
| 11 | |||
| 12 | The above copyright notice and this permission notice shall be included in | ||
| 13 | all copies or substantial portions of the Software. | ||
| 14 | |||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 21 | THE SOFTWARE. |
-
Please register or sign in to post a comment