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