├── .gitignore ├── .travis.yml ├── CY ├── CYWebViewController.h ├── CYWebViewController.m ├── Category │ ├── UIButton+WHE.h │ ├── UIButton+WHE.m │ ├── UIColor+WHE.h │ ├── UIColor+WHE.m │ ├── UIImage+CYButtonIcon.h │ └── UIImage+CYButtonIcon.m ├── NJKWebViewProgress │ ├── NJKWebViewProgress.h │ ├── NJKWebViewProgress.m │ ├── NJKWebViewProgressView.h │ └── NJKWebViewProgressView.m ├── UINavigationBar+Awesome.h ├── UINavigationBar+Awesome.m └── img │ ├── backBtn.png │ ├── backBtn@2x.png │ └── backBtn@3x.png ├── CYWebviewController.podspec ├── CYWebviewController ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── CYWebViewController.h │ ├── CYWebViewController.m │ ├── Category │ ├── UIButton+WHE.h │ ├── UIButton+WHE.m │ ├── UIColor+WHE.h │ ├── UIColor+WHE.m │ ├── UIImage+CYButtonIcon.h │ └── UIImage+CYButtonIcon.m │ ├── NJKWebViewProgress │ ├── NJKWebViewProgress.h │ ├── NJKWebViewProgress.m │ ├── NJKWebViewProgressView.h │ └── NJKWebViewProgressView.m │ ├── UINavigationBar+Awesome.h │ └── UINavigationBar+Awesome.m ├── Example ├── CYWebviewController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── CYWebviewController-Example.xcscheme ├── CYWebviewController.xcworkspace │ └── contents.xcworkspacedata ├── CYWebviewController │ ├── CYAppDelegate.h │ ├── CYAppDelegate.m │ ├── CYViewController.h │ ├── CYViewController.m │ ├── CYWebviewController-Info.plist │ ├── CYWebviewController-Prefix.pch │ ├── Main.storyboard │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m ├── Launch Screen.storyboard ├── Podfile ├── Podfile.lock ├── Pods │ ├── FBSnapshotTestCase │ │ ├── FBSnapshotTestCase.modulemap │ │ ├── FBSnapshotTestCase │ │ │ ├── Categories │ │ │ │ ├── UIApplication+StrictKeyWindow.h │ │ │ │ ├── UIApplication+StrictKeyWindow.m │ │ │ │ ├── UIImage+Compare.h │ │ │ │ ├── UIImage+Compare.m │ │ │ │ ├── UIImage+Diff.h │ │ │ │ ├── UIImage+Diff.m │ │ │ │ ├── UIImage+Snapshot.h │ │ │ │ └── UIImage+Snapshot.m │ │ │ ├── FBSnapshotTestCase.h │ │ │ ├── FBSnapshotTestCase.m │ │ │ ├── FBSnapshotTestCasePlatform.h │ │ │ ├── FBSnapshotTestCasePlatform.m │ │ │ ├── FBSnapshotTestController.h │ │ │ ├── FBSnapshotTestController.m │ │ │ └── SwiftSupport.swift │ │ ├── LICENSE │ │ └── README.md │ ├── Local Podspecs │ │ └── CYWebviewController.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── CYWebviewController │ │ ├── CYWebviewController-dummy.m │ │ ├── CYWebviewController-prefix.pch │ │ ├── CYWebviewController-umbrella.h │ │ ├── CYWebviewController.modulemap │ │ ├── CYWebviewController.xcconfig │ │ ├── Info.plist │ │ └── ResourceBundle-CYWebviewController-Info.plist │ │ ├── FBSnapshotTestCase │ │ ├── FBSnapshotTestCase-dummy.m │ │ ├── FBSnapshotTestCase-prefix.pch │ │ ├── FBSnapshotTestCase.modulemap │ │ ├── FBSnapshotTestCase.xcconfig │ │ └── Info.plist │ │ ├── Pods-CYWebviewController_Example │ │ ├── Info.plist │ │ ├── Pods-CYWebviewController_Example-acknowledgements.markdown │ │ ├── Pods-CYWebviewController_Example-acknowledgements.plist │ │ ├── Pods-CYWebviewController_Example-dummy.m │ │ ├── Pods-CYWebviewController_Example-frameworks.sh │ │ ├── Pods-CYWebviewController_Example-resources.sh │ │ ├── Pods-CYWebviewController_Example-umbrella.h │ │ ├── Pods-CYWebviewController_Example.debug.xcconfig │ │ ├── Pods-CYWebviewController_Example.modulemap │ │ └── Pods-CYWebviewController_Example.release.xcconfig │ │ └── Pods-CYWebviewController_Tests │ │ ├── Info.plist │ │ ├── Pods-CYWebviewController_Tests-acknowledgements.markdown │ │ ├── Pods-CYWebviewController_Tests-acknowledgements.plist │ │ ├── Pods-CYWebviewController_Tests-dummy.m │ │ ├── Pods-CYWebviewController_Tests-frameworks.sh │ │ ├── Pods-CYWebviewController_Tests-resources.sh │ │ ├── Pods-CYWebviewController_Tests-umbrella.h │ │ ├── Pods-CYWebviewController_Tests.debug.xcconfig │ │ ├── Pods-CYWebviewController_Tests.modulemap │ │ └── Pods-CYWebviewController_Tests.release.xcconfig └── Tests │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj │ └── InfoPlist.strings ├── LICENSE ├── README.md ├── Screenshot ├── 1.PNG ├── 2.PNG ├── 3.PNG ├── 4.PNG ├── 5.PNG └── 6.PNG └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Note: if you ignore the Pods directory, make sure to uncomment 31 | # `pod install` in .travis.yml 32 | # 33 | # Pods/ 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -workspace Example/CYWebviewController.xcworkspace -scheme CYWebviewController-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /CY/CYWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CYWebViewController.h 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/30. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | 13 | /* Detect if we're running iOS 7.0 or higher (With the new minimal UI) */ 14 | #define MINIMAL_UI ([[UIViewController class] instancesRespondToSelector:@selector(edgesForExtendedLayout)]) 15 | 16 | 17 | /** 18 | * 返回系统语言对应的文字 19 | * 20 | * @param key 关键字 21 | */ 22 | #define CYLocalize(key) NSLocalizedString(key, nil) 23 | 24 | 25 | @interface CYWebViewController : UIViewController 26 | /** 27 | * url string 28 | */ 29 | @property (nonatomic, strong) NSString *urlString; 30 | 31 | 32 | 33 | /** 34 | * website url 35 | */ 36 | @property (nonatomic,strong) NSURL *url; 37 | 38 | 39 | 40 | /** 41 | * The tint colour of the page loading progress bar. 42 | * If not set on iOS 7 and above, the loading bar will defer to the app's global UIView tint color. 43 | * If not set on iOS 6 or below, it will default to the standard system blue tint color. 44 | * 45 | * Default value is nil. 46 | */ 47 | @property (nonatomic,copy) UIColor *loadingBarTintColor; 48 | 49 | 50 | 51 | /** 52 | * webview bg color 53 | */ 54 | @property (nonatomic,copy) NSString *bgcolor; 55 | 56 | 57 | /** 58 | Hides all of the page navigation buttons, and on iPhone, hides the bottom toolbar. 59 | 60 | Default value is Yes. 61 | */ 62 | @property (nonatomic,assign) BOOL navigationButtonsHidden; 63 | 64 | 65 | /** 66 | * show URL while web loading. 67 | * Default value is NO. 68 | */ 69 | @property (nonatomic,assign) BOOL showURLWhileLoading; 70 | 71 | /** 72 | * Show web page title. 73 | * Default value is Yes. 74 | */ 75 | @property (nonatomic,assign) BOOL showWebPageTitle; 76 | 77 | 78 | 79 | /** 80 | * Show action button. 81 | * Default value is Yes. 82 | */ 83 | @property (nonatomic,assign) BOOL showActionButton; 84 | 85 | 86 | 87 | /** 88 | Shows the Done button when presented modally. When tapped, it dismisses the view controller. 89 | 90 | Default value is YES. 91 | */ 92 | @property (nonatomic,assign) BOOL showDoneButton; 93 | 94 | 95 | /** 96 | * If desired, override the title of the system 'Done' button to this string. 97 | * Default value is nil. 98 | */ 99 | @property (nonatomic,copy) NSString *doneBtnTitle; 100 | 101 | 102 | /** 103 | * Wechat Mode, back button icon. If no set, has default image 104 | */ 105 | @property (nonatomic,strong) UIImage *backIcon; 106 | 107 | 108 | 109 | /** 110 | * Initializes object with url 111 | * 112 | * @param url webpage url 113 | * 114 | * @return CYWebViewController object 115 | */ 116 | - (id)initWithURL:(NSURL *)url; 117 | 118 | 119 | /** 120 | * Initializes object with url string 121 | * 122 | * @param urlString webpage url string 123 | * 124 | * @return CYWebViewController object 125 | */ 126 | - (id)initWithURLString:(NSString *)urlString; 127 | 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /CY/Category/UIButton+WHE.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+WHE.h 3 | // DoctorApp 4 | // 5 | // Created by 万鸿恩 on 16/1/15. 6 | // Copyright © 2016年 Horus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIButton (WHE) 12 | +(UIButton *)buttonBackWithImage:(UIImage *)image buttontitle:(NSString *)title target:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; 13 | @end 14 | -------------------------------------------------------------------------------- /CY/Category/UIButton+WHE.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+WHE.m 3 | // DoctorApp 4 | // 5 | // Created by 万鸿恩 on 16/1/15. 6 | // Copyright © 2016年 Horus. All rights reserved. 7 | // 8 | 9 | #import "UIButton+WHE.h" 10 | 11 | @implementation UIButton (WHE) 12 | +(UIButton *)buttonBackWithImage:(UIImage *)image buttontitle:(NSString *)title target:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents{ 13 | // btn 14 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 15 | 16 | [btn setImage:image forState:UIControlStateNormal]; 17 | [btn sizeToFit]; 18 | CGFloat btnX = 0; 19 | CGFloat btnY = 0; 20 | CGFloat btnW = 80; 21 | CGFloat btnH = 44; 22 | btn.frame = CGRectMake(btnX, btnY, btnW, btnH); 23 | [btn setTitle:title forState:UIControlStateNormal]; 24 | [btn setTitle:title forState:UIControlStateHighlighted]; 25 | [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 26 | [btn setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted]; 27 | [btn addTarget:target action:action forControlEvents:controlEvents]; 28 | [btn.titleLabel setFont:[UIFont systemFontOfSize:16]]; 29 | 30 | btn.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0); 31 | btn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); 32 | return btn; 33 | } 34 | @end 35 | -------------------------------------------------------------------------------- /CY/Category/UIColor+WHE.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+WHE.h 3 | // DoctorApp 4 | // 5 | // Created by 万鸿恩 on 15/10/29. 6 | // Copyright © 2015年 Horus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (WHE) 12 | /** 13 | * hex color to rgd color, where hexString, such as: #FF00FF 14 | **/ 15 | + (UIColor *) colorFromHexString:(NSString *)hexString; 16 | @end 17 | -------------------------------------------------------------------------------- /CY/Category/UIColor+WHE.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+WHE.m 3 | // Horus 4 | // 5 | // Created by 万鸿恩 on 15/9/17. 6 | // Copyright (c) 2015年 Cybersys. All rights reserved. 7 | // 8 | 9 | #import "UIColor+WHE.h" 10 | 11 | @implementation UIColor (WHE) 12 | 13 | 14 | 15 | +(UIColor*)colorFromHexString:(NSString *)hexString{ 16 | NSString *cleanString = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]; 17 | if([cleanString length] == 3) { 18 | cleanString = [NSString stringWithFormat:@"%@%@%@%@%@%@", 19 | [cleanString substringWithRange:NSMakeRange(0, 1)],[cleanString substringWithRange:NSMakeRange(0, 1)], 20 | [cleanString substringWithRange:NSMakeRange(1, 1)],[cleanString substringWithRange:NSMakeRange(1, 1)], 21 | [cleanString substringWithRange:NSMakeRange(2, 1)],[cleanString substringWithRange:NSMakeRange(2, 1)]]; 22 | } 23 | if([cleanString length] == 6) { 24 | cleanString = [cleanString stringByAppendingString:@"ff"]; 25 | } 26 | 27 | unsigned int baseValue; 28 | [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue]; 29 | 30 | float red = ((baseValue >> 24) & 0xFF)/255.0f; 31 | float green = ((baseValue >> 16) & 0xFF)/255.0f; 32 | float blue = ((baseValue >> 8) & 0xFF)/255.0f; 33 | float alpha = ((baseValue >> 0) & 0xFF)/255.0f; 34 | 35 | 36 | //NSLog(@"alpha equals to %f r:%f g:%f b:%f",alpha,red*255,green*255,blue*255); 37 | 38 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 39 | } 40 | 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CY/Category/UIImage+CYButtonIcon.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+CYButtonIcon.h 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/31. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (CYButtonIcon) 12 | 13 | /* Navigation Buttons */ 14 | 15 | /** 16 | * creat back button icon 17 | * 18 | * @return UIImage 19 | */ 20 | + (id)cy_backButtonIcon:(UIColor*)color; 21 | 22 | /** 23 | * creat forward button icon 24 | * 25 | * @return UIImage 26 | */ 27 | + (id)cy_forwardButtonIcon; 28 | 29 | 30 | /** 31 | * creat refresh button icon 32 | * 33 | * @return UIImage 34 | */ 35 | + (id)cy_refreshButtonIcon; 36 | 37 | 38 | /** 39 | * creat stop button icon 40 | * 41 | * @return UIImage 42 | */ 43 | + (id)cy_stopButtonIcon; 44 | 45 | /** 46 | * creat action button icon 47 | * 48 | * @return UIImage 49 | */ 50 | + (id)cy_actionButtonIcon; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /CY/Category/UIImage+CYButtonIcon.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+CYButtonIcon.m 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/31. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import "UIImage+CYButtonIcon.h" 10 | 11 | @implementation UIImage (CYButtonIcon) 12 | 13 | #pragma mark -Navigation Button 14 | 15 | + (id)cy_backButtonIcon:(UIColor*)color{ 16 | UIImage *backImage = nil; 17 | UIGraphicsBeginImageContextWithOptions((CGSize){12,21}, NO, [[UIScreen mainScreen] scale]); 18 | //color 19 | UIColor *backColor = [UIColor blackColor]; 20 | if (color) { 21 | backColor = color; 22 | } 23 | 24 | 25 | //利用贝塞尔曲线,把后退按钮分为上下两部分,上面一个小矩形,下面一个小矩形 26 | UIBezierPath *backPath = [UIBezierPath bezierPath]; 27 | [backPath moveToPoint:CGPointMake(10.9, 0)]; 28 | [backPath addLineToPoint:CGPointMake(12, 1.1)]; 29 | [backPath addLineToPoint:CGPointMake(1.1, 11.75)]; 30 | [backPath addLineToPoint:CGPointMake(0, 10.7)]; 31 | [backPath addLineToPoint:CGPointMake(10.9, 0)]; 32 | [backPath closePath]; 33 | 34 | //下部分 35 | [backPath moveToPoint:CGPointMake(11.98, 19.9)]; 36 | [backPath addLineToPoint:CGPointMake(10.88, 21)]; 37 | [backPath addLineToPoint:CGPointMake(0.54, 11.21)]; 38 | [backPath addLineToPoint:CGPointMake(1.64, 10.11)]; 39 | [backPath addLineToPoint:CGPointMake(11.98, 19.9)]; 40 | [backPath closePath]; 41 | 42 | [backColor setFill]; 43 | [backPath fill]; 44 | 45 | backImage = UIGraphicsGetImageFromCurrentImageContext(); 46 | 47 | UIGraphicsEndImageContext(); 48 | 49 | return backImage; 50 | } 51 | 52 | 53 | + (id)cy_forwardButtonIcon{ 54 | 55 | UIImage *forwardButtonImage = nil; 56 | 57 | UIGraphicsBeginImageContextWithOptions((CGSize){12,21}, NO, [[UIScreen mainScreen] scale]); 58 | 59 | //Color Declarations 60 | UIColor* forwardColor = [UIColor blackColor]; 61 | 62 | //利用贝塞尔曲线,把前进按钮分为上下两部分,上面一个小矩形,下面一个小矩形 63 | UIBezierPath* forwardPath = [UIBezierPath bezierPath]; 64 | 65 | [forwardPath moveToPoint: CGPointMake(1.1, 0)]; 66 | [forwardPath addLineToPoint: CGPointMake(0, 1.1)]; 67 | [forwardPath addLineToPoint: CGPointMake(10.9, 11.75)]; 68 | [forwardPath addLineToPoint: CGPointMake(12, 10.7)]; 69 | [forwardPath addLineToPoint: CGPointMake(1.1, 0)]; 70 | [forwardPath closePath]; 71 | 72 | 73 | [forwardPath moveToPoint: CGPointMake(0.02, 19.9)]; 74 | [forwardPath addLineToPoint: CGPointMake(1.12, 21)]; 75 | [forwardPath addLineToPoint: CGPointMake(11.46, 11.21)]; 76 | [forwardPath addLineToPoint: CGPointMake(10.36, 10.11)]; 77 | [forwardPath addLineToPoint: CGPointMake(0.02, 19.9)]; 78 | [forwardPath closePath]; 79 | 80 | 81 | [forwardColor setFill]; 82 | [forwardPath fill]; 83 | 84 | forwardButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 85 | 86 | 87 | UIGraphicsEndImageContext(); 88 | 89 | return forwardButtonImage; 90 | } 91 | 92 | 93 | + (id)cy_refreshButtonIcon{ 94 | UIImage *refreshButtonImage = nil; 95 | UIGraphicsBeginImageContextWithOptions((CGSize){19,22}, NO, [[UIScreen mainScreen] scale]); 96 | UIColor* refreshColor = [UIColor blackColor]; 97 | 98 | // RefreshButton Drawing 99 | UIBezierPath* refreshIconPath = [UIBezierPath bezierPath]; 100 | 101 | [refreshIconPath moveToPoint: CGPointMake(18.98, 12)]; 102 | [refreshIconPath addCurveToPoint: CGPointMake(19, 12.8) controlPoint1: CGPointMake(18.99, 12.11) controlPoint2: CGPointMake(19, 12.69)]; 103 | [refreshIconPath addCurveToPoint: CGPointMake(9.5, 22) controlPoint1: CGPointMake(19, 17.88) controlPoint2: CGPointMake(14.75, 22)]; 104 | [refreshIconPath addCurveToPoint: CGPointMake(0, 12.8) controlPoint1: CGPointMake(4.25, 22) controlPoint2: CGPointMake(0, 17.88)]; 105 | [refreshIconPath addCurveToPoint: CGPointMake(10, 3.5) controlPoint1: CGPointMake(0, 7.72) controlPoint2: CGPointMake(4.75, 3.5)]; 106 | [refreshIconPath addCurveToPoint: CGPointMake(10, 5) controlPoint1: CGPointMake(10.02, 3.5) controlPoint2: CGPointMake(10.02, 5)]; 107 | [refreshIconPath addCurveToPoint: CGPointMake(1.69, 12.8) controlPoint1: CGPointMake(5.69, 5) controlPoint2: CGPointMake(1.69, 8.63)]; 108 | [refreshIconPath addCurveToPoint: CGPointMake(9.5, 20.36) controlPoint1: CGPointMake(1.69, 16.98) controlPoint2: CGPointMake(5.19, 20.36)]; 109 | [refreshIconPath addCurveToPoint: CGPointMake(17.31, 12) controlPoint1: CGPointMake(13.81, 20.36) controlPoint2: CGPointMake(17.31, 16.18)]; 110 | [refreshIconPath addCurveToPoint: CGPointMake(17.28, 12) controlPoint1: CGPointMake(17.31, 11.89) controlPoint2: CGPointMake(17.28, 12.11)]; 111 | [refreshIconPath addLineToPoint: CGPointMake(18.98, 12)]; 112 | [refreshIconPath closePath]; 113 | [refreshIconPath moveToPoint: CGPointMake(10, 0)]; 114 | [refreshIconPath addLineToPoint: CGPointMake(17.35, 4.62)]; 115 | [refreshIconPath addLineToPoint: CGPointMake(10, 9.13)]; 116 | [refreshIconPath addLineToPoint: CGPointMake(10, 0)]; 117 | [refreshIconPath closePath]; 118 | [refreshColor setFill]; 119 | [refreshIconPath fill]; 120 | 121 | refreshButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 122 | UIGraphicsEndImageContext(); 123 | 124 | return refreshButtonImage; 125 | } 126 | 127 | + (id)cy_stopButtonIcon{ 128 | 129 | UIImage *stopButtonImage = nil; 130 | 131 | UIGraphicsBeginImageContextWithOptions((CGSize){19,19}, NO, [[UIScreen mainScreen] scale]); 132 | //// Color Declarations 133 | UIColor* stopColor = [UIColor blackColor]; 134 | 135 | //错号按钮 StopButton Drawing 136 | 137 | UIBezierPath* stopPath = [UIBezierPath bezierPath]; 138 | 139 | [stopPath moveToPoint: CGPointMake(19, 17.82)]; 140 | [stopPath addLineToPoint: CGPointMake(17.82, 19)]; 141 | [stopPath addLineToPoint: CGPointMake(9.5, 10.68)]; 142 | [stopPath addLineToPoint: CGPointMake(1.18, 19)]; 143 | [stopPath addLineToPoint: CGPointMake(0, 17.82)]; 144 | [stopPath addLineToPoint: CGPointMake(8.32, 9.5)]; 145 | [stopPath addLineToPoint: CGPointMake(0, 1.18)]; 146 | [stopPath addLineToPoint: CGPointMake(1.18, 0)]; 147 | [stopPath addLineToPoint: CGPointMake(9.5, 8.32)]; 148 | [stopPath addLineToPoint: CGPointMake(17.82, 0)]; 149 | [stopPath addLineToPoint: CGPointMake(19, 1.18)]; 150 | [stopPath addLineToPoint: CGPointMake(10.68, 9.5)]; 151 | [stopPath addLineToPoint: CGPointMake(19, 17.82)]; 152 | [stopPath closePath]; 153 | [stopColor setFill]; 154 | [stopPath fill]; 155 | 156 | stopButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 157 | 158 | UIGraphicsEndImageContext(); 159 | 160 | return stopButtonImage; 161 | } 162 | 163 | 164 | + (id)cy_actionButtonIcon{ 165 | UIImage *actionButtonImage = nil; 166 | UIGraphicsBeginImageContextWithOptions((CGSize){19,30}, NO, [[UIScreen mainScreen] scale]); 167 | //// Color Declarations 168 | UIColor* actionColor = [UIColor blackColor]; 169 | 170 | //// ActionButton Drawing 171 | UIBezierPath* actionButtonPath = [UIBezierPath bezierPath]; 172 | [actionButtonPath moveToPoint: CGPointMake(1, 9)]; 173 | [actionButtonPath addLineToPoint: CGPointMake(1, 26.02)]; 174 | [actionButtonPath addLineToPoint: CGPointMake(18, 26.02)]; 175 | [actionButtonPath addLineToPoint: CGPointMake(18, 9)]; 176 | [actionButtonPath addLineToPoint: CGPointMake(12, 9)]; 177 | [actionButtonPath addLineToPoint: CGPointMake(12, 8)]; 178 | [actionButtonPath addLineToPoint: CGPointMake(19, 8)]; 179 | [actionButtonPath addLineToPoint: CGPointMake(19, 27)]; 180 | [actionButtonPath addLineToPoint: CGPointMake(0, 27)]; 181 | [actionButtonPath addLineToPoint: CGPointMake(0, 8)]; 182 | [actionButtonPath addLineToPoint: CGPointMake(7, 8)]; 183 | [actionButtonPath addLineToPoint: CGPointMake(7, 9)]; 184 | [actionButtonPath addLineToPoint: CGPointMake(1, 9)]; 185 | [actionButtonPath closePath]; 186 | 187 | 188 | [actionButtonPath moveToPoint: CGPointMake(9, 0.98)]; 189 | [actionButtonPath addLineToPoint: CGPointMake(10, 0.98)]; 190 | [actionButtonPath addLineToPoint: CGPointMake(10, 17)]; 191 | [actionButtonPath addLineToPoint: CGPointMake(9, 17)]; 192 | [actionButtonPath addLineToPoint: CGPointMake(9, 0.98)]; 193 | [actionButtonPath closePath]; 194 | [actionButtonPath moveToPoint: CGPointMake(13.99, 4.62)]; 195 | [actionButtonPath addLineToPoint: CGPointMake(13.58, 5.01)]; 196 | [actionButtonPath addCurveToPoint: CGPointMake(13.25, 5.02) controlPoint1: CGPointMake(13.49, 5.1) controlPoint2: CGPointMake(13.34, 5.11)]; 197 | [actionButtonPath addLineToPoint: CGPointMake(9.43, 1.27)]; 198 | [actionButtonPath addCurveToPoint: CGPointMake(9.44, 0.94) controlPoint1: CGPointMake(9.34, 1.18) controlPoint2: CGPointMake(9.35, 1.04)]; 199 | [actionButtonPath addLineToPoint: CGPointMake(9.85, 0.56)]; 200 | [actionButtonPath addCurveToPoint: CGPointMake(10.18, 0.55) controlPoint1: CGPointMake(9.94, 0.46) controlPoint2: CGPointMake(10.09, 0.46)]; 201 | [actionButtonPath addLineToPoint: CGPointMake(14, 4.29)]; 202 | [actionButtonPath addCurveToPoint: CGPointMake(13.99, 4.62) controlPoint1: CGPointMake(14.09, 4.38) controlPoint2: CGPointMake(14.08, 4.53)]; 203 | [actionButtonPath closePath]; 204 | [actionButtonPath moveToPoint: CGPointMake(5.64, 4.95)]; 205 | [actionButtonPath addLineToPoint: CGPointMake(5.27, 4.56)]; 206 | [actionButtonPath addCurveToPoint: CGPointMake(5.26, 4.23) controlPoint1: CGPointMake(5.18, 4.47) controlPoint2: CGPointMake(5.17, 4.32)]; 207 | [actionButtonPath addLineToPoint: CGPointMake(9.46, 0.07)]; 208 | [actionButtonPath addCurveToPoint: CGPointMake(9.79, 0.07) controlPoint1: CGPointMake(9.55, -0.02) controlPoint2: CGPointMake(9.69, -0.02)]; 209 | [actionButtonPath addLineToPoint: CGPointMake(10.16, 0.47)]; 210 | [actionButtonPath addCurveToPoint: CGPointMake(10.17, 0.8) controlPoint1: CGPointMake(10.25, 0.56) controlPoint2: CGPointMake(10.26, 0.71)]; 211 | [actionButtonPath addLineToPoint: CGPointMake(5.97, 4.96)]; 212 | [actionButtonPath addCurveToPoint: CGPointMake(5.64, 4.95) controlPoint1: CGPointMake(5.88, 5.05) controlPoint2: CGPointMake(5.74, 5.05)]; 213 | [actionButtonPath closePath]; 214 | [actionColor setFill]; 215 | [actionButtonPath fill]; 216 | 217 | actionButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 218 | 219 | 220 | UIGraphicsEndImageContext(); 221 | 222 | return actionButtonImage; 223 | } 224 | 225 | 226 | 227 | @end 228 | -------------------------------------------------------------------------------- /CY/NJKWebViewProgress/NJKWebViewProgress.h: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgress.h 3 | // 4 | // Created by Satoshi Aasano on 4/20/13. 5 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | #undef njk_weak 12 | #if __has_feature(objc_arc_weak) 13 | #define njk_weak weak 14 | #else 15 | #define njk_weak unsafe_unretained 16 | #endif 17 | 18 | extern const float NJKInitialProgressValue; 19 | extern const float NJKInteractiveProgressValue; 20 | extern const float NJKFinalProgressValue; 21 | 22 | typedef void (^NJKWebViewProgressBlock)(float progress); 23 | @protocol NJKWebViewProgressDelegate; 24 | @interface NJKWebViewProgress : NSObject 25 | @property (nonatomic, njk_weak) idprogressDelegate; 26 | @property (nonatomic, njk_weak) idwebViewProxyDelegate; 27 | @property (nonatomic, copy) NJKWebViewProgressBlock progressBlock; 28 | @property (nonatomic, readonly) float progress; // 0.0..1.0 29 | 30 | - (void)reset; 31 | @end 32 | 33 | @protocol NJKWebViewProgressDelegate 34 | - (void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress; 35 | @end 36 | 37 | -------------------------------------------------------------------------------- /CY/NJKWebViewProgress/NJKWebViewProgress.m: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgress.m 3 | // 4 | // Created by Satoshi Aasano on 4/20/13. 5 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 6 | // 7 | 8 | #import "NJKWebViewProgress.h" 9 | 10 | NSString *completeRPCURLPath = @"/njkwebviewprogressproxy/complete"; 11 | 12 | const float NJKInitialProgressValue = 0.1f; 13 | const float NJKInteractiveProgressValue = 0.5f; 14 | const float NJKFinalProgressValue = 0.9f; 15 | 16 | @implementation NJKWebViewProgress 17 | { 18 | NSUInteger _loadingCount; 19 | NSUInteger _maxLoadCount; 20 | NSURL *_currentURL; 21 | BOOL _interactive; 22 | } 23 | 24 | - (id)init 25 | { 26 | self = [super init]; 27 | if (self) { 28 | _maxLoadCount = _loadingCount = 0; 29 | _interactive = NO; 30 | } 31 | return self; 32 | } 33 | 34 | - (void)startProgress 35 | { 36 | if (_progress < NJKInitialProgressValue) { 37 | [self setProgress:NJKInitialProgressValue]; 38 | } 39 | } 40 | 41 | - (void)incrementProgress 42 | { 43 | float progress = self.progress; 44 | float maxProgress = _interactive ? NJKFinalProgressValue : NJKInteractiveProgressValue; 45 | float remainPercent = (float)_loadingCount / (float)_maxLoadCount; 46 | float increment = (maxProgress - progress) * remainPercent; 47 | progress += increment; 48 | progress = fmin(progress, maxProgress); 49 | [self setProgress:progress]; 50 | } 51 | 52 | - (void)completeProgress 53 | { 54 | [self setProgress:1.0]; 55 | } 56 | 57 | - (void)setProgress:(float)progress 58 | { 59 | // progress should be incremental only 60 | if (progress > _progress || progress == 0) { 61 | _progress = progress; 62 | if ([_progressDelegate respondsToSelector:@selector(webViewProgress:updateProgress:)]) { 63 | [_progressDelegate webViewProgress:self updateProgress:progress]; 64 | } 65 | if (_progressBlock) { 66 | _progressBlock(progress); 67 | } 68 | } 69 | } 70 | 71 | - (void)reset 72 | { 73 | _maxLoadCount = _loadingCount = 0; 74 | _interactive = NO; 75 | [self setProgress:0.0]; 76 | } 77 | 78 | #pragma mark - 79 | #pragma mark UIWebViewDelegate 80 | 81 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 82 | { 83 | if ([request.URL.path isEqualToString:completeRPCURLPath]) { 84 | [self completeProgress]; 85 | return NO; 86 | } 87 | 88 | BOOL ret = YES; 89 | if ([_webViewProxyDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { 90 | ret = [_webViewProxyDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; 91 | } 92 | 93 | BOOL isFragmentJump = NO; 94 | if (request.URL.fragment) { 95 | NSString *nonFragmentURL = [request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:request.URL.fragment] withString:@""]; 96 | isFragmentJump = [nonFragmentURL isEqualToString:webView.request.URL.absoluteString]; 97 | } 98 | 99 | BOOL isTopLevelNavigation = [request.mainDocumentURL isEqual:request.URL]; 100 | 101 | BOOL isHTTPOrLocalFile = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"] || [request.URL.scheme isEqualToString:@"file"]; 102 | if (ret && !isFragmentJump && isHTTPOrLocalFile && isTopLevelNavigation) { 103 | _currentURL = request.URL; 104 | [self reset]; 105 | } 106 | return ret; 107 | } 108 | 109 | - (void)webViewDidStartLoad:(UIWebView *)webView 110 | { 111 | if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { 112 | [_webViewProxyDelegate webViewDidStartLoad:webView]; 113 | } 114 | 115 | _loadingCount++; 116 | _maxLoadCount = fmax(_maxLoadCount, _loadingCount); 117 | 118 | [self startProgress]; 119 | } 120 | 121 | - (void)webViewDidFinishLoad:(UIWebView *)webView 122 | { 123 | if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { 124 | [_webViewProxyDelegate webViewDidFinishLoad:webView]; 125 | } 126 | 127 | _loadingCount--; 128 | [self incrementProgress]; 129 | 130 | NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; 131 | 132 | BOOL interactive = [readyState isEqualToString:@"interactive"]; 133 | if (interactive) { 134 | _interactive = YES; 135 | NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@://%@%@'; document.body.appendChild(iframe); }, false);", webView.request.mainDocumentURL.scheme, webView.request.mainDocumentURL.host, completeRPCURLPath]; 136 | [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS]; 137 | } 138 | 139 | BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL]; 140 | BOOL complete = [readyState isEqualToString:@"complete"]; 141 | if (complete && isNotRedirect) { 142 | [self completeProgress]; 143 | } 144 | } 145 | 146 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 147 | { 148 | if ([_webViewProxyDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { 149 | [_webViewProxyDelegate webView:webView didFailLoadWithError:error]; 150 | } 151 | 152 | _loadingCount--; 153 | [self incrementProgress]; 154 | 155 | NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; 156 | 157 | BOOL interactive = [readyState isEqualToString:@"interactive"]; 158 | if (interactive) { 159 | _interactive = YES; 160 | NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@://%@%@'; document.body.appendChild(iframe); }, false);", webView.request.mainDocumentURL.scheme, webView.request.mainDocumentURL.host, completeRPCURLPath]; 161 | [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS]; 162 | } 163 | 164 | BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL]; 165 | BOOL complete = [readyState isEqualToString:@"complete"]; 166 | if ((complete && isNotRedirect) || error) { 167 | [self completeProgress]; 168 | } 169 | } 170 | 171 | #pragma mark - 172 | #pragma mark Method Forwarding 173 | // for future UIWebViewDelegate impl 174 | 175 | - (BOOL)respondsToSelector:(SEL)aSelector 176 | { 177 | if ( [super respondsToSelector:aSelector] ) 178 | return YES; 179 | 180 | if ([self.webViewProxyDelegate respondsToSelector:aSelector]) 181 | return YES; 182 | 183 | return NO; 184 | } 185 | 186 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 187 | { 188 | NSMethodSignature *signature = [super methodSignatureForSelector:selector]; 189 | if(!signature) { 190 | if([_webViewProxyDelegate respondsToSelector:selector]) { 191 | return [(NSObject *)_webViewProxyDelegate methodSignatureForSelector:selector]; 192 | } 193 | } 194 | return signature; 195 | } 196 | 197 | - (void)forwardInvocation:(NSInvocation*)invocation 198 | { 199 | if ([_webViewProxyDelegate respondsToSelector:[invocation selector]]) { 200 | [invocation invokeWithTarget:_webViewProxyDelegate]; 201 | } 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /CY/NJKWebViewProgress/NJKWebViewProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgressView.h 3 | // iOS 7 Style WebView Progress Bar 4 | // 5 | // Created by Satoshi Aasano on 11/16/13. 6 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NJKWebViewProgressView : UIView 12 | @property (nonatomic) float progress; 13 | 14 | @property (nonatomic) UIView *progressBarView; 15 | @property (nonatomic) NSTimeInterval barAnimationDuration; // default 0.1 16 | @property (nonatomic) NSTimeInterval fadeAnimationDuration; // default 0.27 17 | @property (nonatomic) NSTimeInterval fadeOutDelay; // default 0.1 18 | 19 | - (void)setProgress:(float)progress animated:(BOOL)animated; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CY/NJKWebViewProgress/NJKWebViewProgressView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgressView.m 3 | // 4 | // Created by Satoshi Aasanoon 11/16/13. 5 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 6 | // 7 | 8 | #import "NJKWebViewProgressView.h" 9 | 10 | @implementation NJKWebViewProgressView 11 | 12 | - (id)initWithFrame:(CGRect)frame 13 | { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | [self configureViews]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)awakeFromNib 22 | { 23 | [super awakeFromNib]; 24 | [self configureViews]; 25 | } 26 | 27 | -(void)configureViews 28 | { 29 | self.userInteractionEnabled = NO; 30 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth; 31 | _progressBarView = [[UIView alloc] initWithFrame:self.bounds]; 32 | _progressBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 33 | UIColor *tintColor = [UIColor colorWithRed:22.f / 255.f green:126.f / 255.f blue:251.f / 255.f alpha:1.0]; // iOS7 Safari bar color 34 | if ([UIApplication.sharedApplication.delegate.window respondsToSelector:@selector(setTintColor:)] && UIApplication.sharedApplication.delegate.window.tintColor) { 35 | tintColor = UIApplication.sharedApplication.delegate.window.tintColor; 36 | } 37 | _progressBarView.backgroundColor = tintColor; 38 | [self addSubview:_progressBarView]; 39 | 40 | _barAnimationDuration = 0.27f; 41 | _fadeAnimationDuration = 0.27f; 42 | _fadeOutDelay = 0.1f; 43 | } 44 | 45 | -(void)setProgress:(float)progress 46 | { 47 | [self setProgress:progress animated:NO]; 48 | } 49 | 50 | - (void)setProgress:(float)progress animated:(BOOL)animated 51 | { 52 | BOOL isGrowing = progress > 0.0; 53 | [UIView animateWithDuration:(isGrowing && animated) ? _barAnimationDuration : 0.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 54 | CGRect frame = _progressBarView.frame; 55 | frame.size.width = progress * self.bounds.size.width; 56 | _progressBarView.frame = frame; 57 | } completion:nil]; 58 | 59 | if (progress >= 1.0) { 60 | [UIView animateWithDuration:animated ? _fadeAnimationDuration : 0.0 delay:_fadeOutDelay options:UIViewAnimationOptionCurveEaseInOut animations:^{ 61 | _progressBarView.alpha = 0.0; 62 | } completion:^(BOOL completed){ 63 | CGRect frame = _progressBarView.frame; 64 | frame.size.width = 0; 65 | _progressBarView.frame = frame; 66 | }]; 67 | } 68 | else { 69 | [UIView animateWithDuration:animated ? _fadeAnimationDuration : 0.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 70 | _progressBarView.alpha = 1.0; 71 | } completion:nil]; 72 | } 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /CY/UINavigationBar+Awesome.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationBar+Awesome.h 3 | // LTNavigationBar 4 | // 5 | // Created by ltebean on 15-2-15. 6 | // Copyright (c) 2015 ltebean. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UINavigationBar (Awesome) 12 | - (void)lt_setBackgroundColor:(UIColor *)backgroundColor; 13 | - (void)lt_setElementsAlpha:(CGFloat)alpha; 14 | - (void)lt_setTranslationY:(CGFloat)translationY; 15 | - (void)lt_reset; 16 | @end 17 | -------------------------------------------------------------------------------- /CY/UINavigationBar+Awesome.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationBar+Awesome.m 3 | // LTNavigationBar 4 | // 5 | // Created by ltebean on 15-2-15. 6 | // Copyright (c) 2015 ltebean. All rights reserved. 7 | // 8 | 9 | #import "UINavigationBar+Awesome.h" 10 | #import 11 | 12 | @implementation UINavigationBar (Awesome) 13 | static char overlayKey; 14 | 15 | - (UIView *)overlay 16 | { 17 | return objc_getAssociatedObject(self, &overlayKey); 18 | } 19 | 20 | - (void)setOverlay:(UIView *)overlay 21 | { 22 | objc_setAssociatedObject(self, &overlayKey, overlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | } 24 | 25 | - (void)lt_setBackgroundColor:(UIColor *)backgroundColor 26 | { 27 | if (!self.overlay) { 28 | [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; 29 | self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width, CGRectGetHeight(self.bounds) + 20)]; 30 | self.overlay.userInteractionEnabled = NO; 31 | self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 32 | [self insertSubview:self.overlay atIndex:0]; 33 | } 34 | self.overlay.backgroundColor = backgroundColor; 35 | } 36 | 37 | - (void)lt_setTranslationY:(CGFloat)translationY 38 | { 39 | self.transform = CGAffineTransformMakeTranslation(0, translationY); 40 | } 41 | 42 | - (void)lt_setElementsAlpha:(CGFloat)alpha 43 | { 44 | [[self valueForKey:@"_leftViews"] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger i, BOOL *stop) { 45 | view.alpha = alpha; 46 | }]; 47 | 48 | [[self valueForKey:@"_rightViews"] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger i, BOOL *stop) { 49 | view.alpha = alpha; 50 | }]; 51 | 52 | UIView *titleView = [self valueForKey:@"_titleView"]; 53 | titleView.alpha = alpha; 54 | } 55 | 56 | - (void)lt_reset 57 | { 58 | [self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; 59 | [self.overlay removeFromSuperview]; 60 | self.overlay = nil; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /CY/img/backBtn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/CY/img/backBtn.png -------------------------------------------------------------------------------- /CY/img/backBtn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/CY/img/backBtn@2x.png -------------------------------------------------------------------------------- /CY/img/backBtn@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/CY/img/backBtn@3x.png -------------------------------------------------------------------------------- /CYWebviewController.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint CYWebviewController.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'CYWebviewController' 11 | s.version = '1.1.1' 12 | s.summary = 'CYWebviewController is a webview view controller.' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | "CYWebviewController,a UIWebview controller, contains goBack, goForward, refresh and share functions. Also has Wechat mode." 22 | DESC 23 | 24 | s.homepage = 'https://github.com/wheying/CYWebViewController' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { '万鸿恩' => '1396855545@qq.com' } 28 | s.source = { :git => 'https://github.com/wheying/CYWebViewController.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '8.0' 32 | 33 | s.source_files = 'CYWebviewController/Classes/**/*' 34 | 35 | s.resource_bundles = { 36 | 'CYWebviewController' => ['CYWebviewController/Assets/*.png'] 37 | } 38 | 39 | s.public_header_files = 'Pod/Classes/**/*.h' 40 | s.frameworks = 'UIKit' 41 | # s.dependency 'AFNetworking', '~> 2.3' 42 | end 43 | -------------------------------------------------------------------------------- /CYWebviewController/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/CYWebviewController/Assets/.gitkeep -------------------------------------------------------------------------------- /CYWebviewController/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/CYWebviewController/Classes/.gitkeep -------------------------------------------------------------------------------- /CYWebviewController/Classes/CYWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CYWebViewController.h 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/30. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | 13 | /* Detect if we're running iOS 7.0 or higher (With the new minimal UI) */ 14 | #define MINIMAL_UI ([[UIViewController class] instancesRespondToSelector:@selector(edgesForExtendedLayout)]) 15 | 16 | 17 | /** 18 | * 返回系统语言对应的文字 19 | * 20 | * @param key 关键字 21 | */ 22 | #define CYLocalize(key) NSLocalizedString(key, nil) 23 | 24 | 25 | @interface CYWebViewController : UIViewController 26 | /** 27 | * url string 28 | */ 29 | @property (nonatomic, strong) NSString *urlString; 30 | 31 | 32 | 33 | /** 34 | * website url 35 | */ 36 | @property (nonatomic,strong) NSURL *url; 37 | 38 | 39 | 40 | /** 41 | * The tint colour of the page loading progress bar. 42 | * If not set on iOS 7 and above, the loading bar will defer to the app's global UIView tint color. 43 | * If not set on iOS 6 or below, it will default to the standard system blue tint color. 44 | * 45 | * Default value is nil. 46 | */ 47 | @property (nonatomic,copy) UIColor *loadingBarTintColor; 48 | 49 | 50 | 51 | /** 52 | * webview bg color 53 | */ 54 | @property (nonatomic,copy) NSString *bgcolor; 55 | 56 | 57 | /** 58 | Hides all of the page navigation buttons, and on iPhone, hides the bottom toolbar. 59 | 60 | Default value is Yes. 61 | */ 62 | @property (nonatomic,assign) BOOL navigationButtonsHidden; 63 | 64 | 65 | /** 66 | * show URL while web loading. 67 | * Default value is NO. 68 | */ 69 | @property (nonatomic,assign) BOOL showURLWhileLoading; 70 | 71 | /** 72 | * Show web page title. 73 | * Default value is Yes. 74 | */ 75 | @property (nonatomic,assign) BOOL showWebPageTitle; 76 | 77 | 78 | 79 | /** 80 | * Show action button. 81 | * Default value is Yes. 82 | */ 83 | @property (nonatomic,assign) BOOL showActionButton; 84 | 85 | 86 | 87 | /** 88 | Shows the Done button when presented modally. When tapped, it dismisses the view controller. 89 | 90 | Default value is YES. 91 | */ 92 | @property (nonatomic,assign) BOOL showDoneButton; 93 | 94 | 95 | /** 96 | * If desired, override the title of the system 'Done' button to this string. 97 | * Default value is nil. 98 | */ 99 | @property (nonatomic,copy) NSString *doneBtnTitle; 100 | 101 | 102 | /** 103 | * Wechat Mode, back button icon. If no set, has default image 104 | */ 105 | @property (nonatomic,strong) UIImage *backIcon; 106 | 107 | 108 | 109 | /** 110 | * Initializes object with url 111 | * 112 | * @param url webpage url 113 | * 114 | * @return CYWebViewController object 115 | */ 116 | - (id)initWithURL:(NSURL *)url; 117 | 118 | 119 | /** 120 | * Initializes object with url string 121 | * 122 | * @param urlString webpage url string 123 | * 124 | * @return CYWebViewController object 125 | */ 126 | - (id)initWithURLString:(NSString *)urlString; 127 | 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/Category/UIButton+WHE.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+WHE.h 3 | // DoctorApp 4 | // 5 | // Created by 万鸿恩 on 16/1/15. 6 | // Copyright © 2016年 Horus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIButton (WHE) 12 | +(UIButton *)buttonBackWithImage:(UIImage *)image buttontitle:(NSString *)title target:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; 13 | @end 14 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/Category/UIButton+WHE.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+WHE.m 3 | // DoctorApp 4 | // 5 | // Created by 万鸿恩 on 16/1/15. 6 | // Copyright © 2016年 Horus. All rights reserved. 7 | // 8 | 9 | #import "UIButton+WHE.h" 10 | 11 | @implementation UIButton (WHE) 12 | +(UIButton *)buttonBackWithImage:(UIImage *)image buttontitle:(NSString *)title target:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents{ 13 | // btn 14 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 15 | 16 | [btn setImage:image forState:UIControlStateNormal]; 17 | [btn sizeToFit]; 18 | CGFloat btnX = 0; 19 | CGFloat btnY = 0; 20 | CGFloat btnW = 80; 21 | CGFloat btnH = 44; 22 | btn.frame = CGRectMake(btnX, btnY, btnW, btnH); 23 | [btn setTitle:title forState:UIControlStateNormal]; 24 | [btn setTitle:title forState:UIControlStateHighlighted]; 25 | [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 26 | [btn setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted]; 27 | [btn addTarget:target action:action forControlEvents:controlEvents]; 28 | [btn.titleLabel setFont:[UIFont systemFontOfSize:16]]; 29 | 30 | btn.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0); 31 | btn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); 32 | return btn; 33 | } 34 | @end 35 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/Category/UIColor+WHE.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+WHE.h 3 | // DoctorApp 4 | // 5 | // Created by 万鸿恩 on 15/10/29. 6 | // Copyright © 2015年 Horus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (WHE) 12 | /** 13 | * hex color to rgd color, where hexString, such as: #FF00FF 14 | **/ 15 | + (UIColor *) colorFromHexString:(NSString *)hexString; 16 | @end 17 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/Category/UIColor+WHE.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+WHE.m 3 | // Horus 4 | // 5 | // Created by 万鸿恩 on 15/9/17. 6 | // Copyright (c) 2015年 Cybersys. All rights reserved. 7 | // 8 | 9 | #import "UIColor+WHE.h" 10 | 11 | @implementation UIColor (WHE) 12 | 13 | 14 | 15 | +(UIColor*)colorFromHexString:(NSString *)hexString{ 16 | NSString *cleanString = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]; 17 | if([cleanString length] == 3) { 18 | cleanString = [NSString stringWithFormat:@"%@%@%@%@%@%@", 19 | [cleanString substringWithRange:NSMakeRange(0, 1)],[cleanString substringWithRange:NSMakeRange(0, 1)], 20 | [cleanString substringWithRange:NSMakeRange(1, 1)],[cleanString substringWithRange:NSMakeRange(1, 1)], 21 | [cleanString substringWithRange:NSMakeRange(2, 1)],[cleanString substringWithRange:NSMakeRange(2, 1)]]; 22 | } 23 | if([cleanString length] == 6) { 24 | cleanString = [cleanString stringByAppendingString:@"ff"]; 25 | } 26 | 27 | unsigned int baseValue; 28 | [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue]; 29 | 30 | float red = ((baseValue >> 24) & 0xFF)/255.0f; 31 | float green = ((baseValue >> 16) & 0xFF)/255.0f; 32 | float blue = ((baseValue >> 8) & 0xFF)/255.0f; 33 | float alpha = ((baseValue >> 0) & 0xFF)/255.0f; 34 | 35 | 36 | //NSLog(@"alpha equals to %f r:%f g:%f b:%f",alpha,red*255,green*255,blue*255); 37 | 38 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 39 | } 40 | 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/Category/UIImage+CYButtonIcon.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+CYButtonIcon.h 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/31. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (CYButtonIcon) 12 | 13 | /* Navigation Buttons */ 14 | 15 | /** 16 | * creat back button icon 17 | * 18 | * @return UIImage 19 | */ 20 | + (id)cy_backButtonIcon:(UIColor*)color; 21 | 22 | /** 23 | * creat forward button icon 24 | * 25 | * @return UIImage 26 | */ 27 | + (id)cy_forwardButtonIcon; 28 | 29 | 30 | /** 31 | * creat refresh button icon 32 | * 33 | * @return UIImage 34 | */ 35 | + (id)cy_refreshButtonIcon; 36 | 37 | 38 | /** 39 | * creat stop button icon 40 | * 41 | * @return UIImage 42 | */ 43 | + (id)cy_stopButtonIcon; 44 | 45 | /** 46 | * creat action button icon 47 | * 48 | * @return UIImage 49 | */ 50 | + (id)cy_actionButtonIcon; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/Category/UIImage+CYButtonIcon.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+CYButtonIcon.m 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/31. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import "UIImage+CYButtonIcon.h" 10 | 11 | @implementation UIImage (CYButtonIcon) 12 | 13 | #pragma mark -Navigation Button 14 | 15 | + (id)cy_backButtonIcon:(UIColor*)color{ 16 | UIImage *backImage = nil; 17 | UIGraphicsBeginImageContextWithOptions((CGSize){12,21}, NO, [[UIScreen mainScreen] scale]); 18 | //color 19 | UIColor *backColor = [UIColor blackColor]; 20 | if (color) { 21 | backColor = color; 22 | } 23 | 24 | 25 | //利用贝塞尔曲线,把后退按钮分为上下两部分,上面一个小矩形,下面一个小矩形 26 | UIBezierPath *backPath = [UIBezierPath bezierPath]; 27 | [backPath moveToPoint:CGPointMake(10.9, 0)]; 28 | [backPath addLineToPoint:CGPointMake(12, 1.1)]; 29 | [backPath addLineToPoint:CGPointMake(1.1, 11.75)]; 30 | [backPath addLineToPoint:CGPointMake(0, 10.7)]; 31 | [backPath addLineToPoint:CGPointMake(10.9, 0)]; 32 | [backPath closePath]; 33 | 34 | //下部分 35 | [backPath moveToPoint:CGPointMake(11.98, 19.9)]; 36 | [backPath addLineToPoint:CGPointMake(10.88, 21)]; 37 | [backPath addLineToPoint:CGPointMake(0.54, 11.21)]; 38 | [backPath addLineToPoint:CGPointMake(1.64, 10.11)]; 39 | [backPath addLineToPoint:CGPointMake(11.98, 19.9)]; 40 | [backPath closePath]; 41 | 42 | [backColor setFill]; 43 | [backPath fill]; 44 | 45 | backImage = UIGraphicsGetImageFromCurrentImageContext(); 46 | 47 | UIGraphicsEndImageContext(); 48 | 49 | return backImage; 50 | } 51 | 52 | 53 | + (id)cy_forwardButtonIcon{ 54 | 55 | UIImage *forwardButtonImage = nil; 56 | 57 | UIGraphicsBeginImageContextWithOptions((CGSize){12,21}, NO, [[UIScreen mainScreen] scale]); 58 | 59 | //Color Declarations 60 | UIColor* forwardColor = [UIColor blackColor]; 61 | 62 | //利用贝塞尔曲线,把前进按钮分为上下两部分,上面一个小矩形,下面一个小矩形 63 | UIBezierPath* forwardPath = [UIBezierPath bezierPath]; 64 | 65 | [forwardPath moveToPoint: CGPointMake(1.1, 0)]; 66 | [forwardPath addLineToPoint: CGPointMake(0, 1.1)]; 67 | [forwardPath addLineToPoint: CGPointMake(10.9, 11.75)]; 68 | [forwardPath addLineToPoint: CGPointMake(12, 10.7)]; 69 | [forwardPath addLineToPoint: CGPointMake(1.1, 0)]; 70 | [forwardPath closePath]; 71 | 72 | 73 | [forwardPath moveToPoint: CGPointMake(0.02, 19.9)]; 74 | [forwardPath addLineToPoint: CGPointMake(1.12, 21)]; 75 | [forwardPath addLineToPoint: CGPointMake(11.46, 11.21)]; 76 | [forwardPath addLineToPoint: CGPointMake(10.36, 10.11)]; 77 | [forwardPath addLineToPoint: CGPointMake(0.02, 19.9)]; 78 | [forwardPath closePath]; 79 | 80 | 81 | [forwardColor setFill]; 82 | [forwardPath fill]; 83 | 84 | forwardButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 85 | 86 | 87 | UIGraphicsEndImageContext(); 88 | 89 | return forwardButtonImage; 90 | } 91 | 92 | 93 | + (id)cy_refreshButtonIcon{ 94 | UIImage *refreshButtonImage = nil; 95 | UIGraphicsBeginImageContextWithOptions((CGSize){19,22}, NO, [[UIScreen mainScreen] scale]); 96 | UIColor* refreshColor = [UIColor blackColor]; 97 | 98 | // RefreshButton Drawing 99 | UIBezierPath* refreshIconPath = [UIBezierPath bezierPath]; 100 | 101 | [refreshIconPath moveToPoint: CGPointMake(18.98, 12)]; 102 | [refreshIconPath addCurveToPoint: CGPointMake(19, 12.8) controlPoint1: CGPointMake(18.99, 12.11) controlPoint2: CGPointMake(19, 12.69)]; 103 | [refreshIconPath addCurveToPoint: CGPointMake(9.5, 22) controlPoint1: CGPointMake(19, 17.88) controlPoint2: CGPointMake(14.75, 22)]; 104 | [refreshIconPath addCurveToPoint: CGPointMake(0, 12.8) controlPoint1: CGPointMake(4.25, 22) controlPoint2: CGPointMake(0, 17.88)]; 105 | [refreshIconPath addCurveToPoint: CGPointMake(10, 3.5) controlPoint1: CGPointMake(0, 7.72) controlPoint2: CGPointMake(4.75, 3.5)]; 106 | [refreshIconPath addCurveToPoint: CGPointMake(10, 5) controlPoint1: CGPointMake(10.02, 3.5) controlPoint2: CGPointMake(10.02, 5)]; 107 | [refreshIconPath addCurveToPoint: CGPointMake(1.69, 12.8) controlPoint1: CGPointMake(5.69, 5) controlPoint2: CGPointMake(1.69, 8.63)]; 108 | [refreshIconPath addCurveToPoint: CGPointMake(9.5, 20.36) controlPoint1: CGPointMake(1.69, 16.98) controlPoint2: CGPointMake(5.19, 20.36)]; 109 | [refreshIconPath addCurveToPoint: CGPointMake(17.31, 12) controlPoint1: CGPointMake(13.81, 20.36) controlPoint2: CGPointMake(17.31, 16.18)]; 110 | [refreshIconPath addCurveToPoint: CGPointMake(17.28, 12) controlPoint1: CGPointMake(17.31, 11.89) controlPoint2: CGPointMake(17.28, 12.11)]; 111 | [refreshIconPath addLineToPoint: CGPointMake(18.98, 12)]; 112 | [refreshIconPath closePath]; 113 | [refreshIconPath moveToPoint: CGPointMake(10, 0)]; 114 | [refreshIconPath addLineToPoint: CGPointMake(17.35, 4.62)]; 115 | [refreshIconPath addLineToPoint: CGPointMake(10, 9.13)]; 116 | [refreshIconPath addLineToPoint: CGPointMake(10, 0)]; 117 | [refreshIconPath closePath]; 118 | [refreshColor setFill]; 119 | [refreshIconPath fill]; 120 | 121 | refreshButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 122 | UIGraphicsEndImageContext(); 123 | 124 | return refreshButtonImage; 125 | } 126 | 127 | + (id)cy_stopButtonIcon{ 128 | 129 | UIImage *stopButtonImage = nil; 130 | 131 | UIGraphicsBeginImageContextWithOptions((CGSize){19,19}, NO, [[UIScreen mainScreen] scale]); 132 | //// Color Declarations 133 | UIColor* stopColor = [UIColor blackColor]; 134 | 135 | //错号按钮 StopButton Drawing 136 | 137 | UIBezierPath* stopPath = [UIBezierPath bezierPath]; 138 | 139 | [stopPath moveToPoint: CGPointMake(19, 17.82)]; 140 | [stopPath addLineToPoint: CGPointMake(17.82, 19)]; 141 | [stopPath addLineToPoint: CGPointMake(9.5, 10.68)]; 142 | [stopPath addLineToPoint: CGPointMake(1.18, 19)]; 143 | [stopPath addLineToPoint: CGPointMake(0, 17.82)]; 144 | [stopPath addLineToPoint: CGPointMake(8.32, 9.5)]; 145 | [stopPath addLineToPoint: CGPointMake(0, 1.18)]; 146 | [stopPath addLineToPoint: CGPointMake(1.18, 0)]; 147 | [stopPath addLineToPoint: CGPointMake(9.5, 8.32)]; 148 | [stopPath addLineToPoint: CGPointMake(17.82, 0)]; 149 | [stopPath addLineToPoint: CGPointMake(19, 1.18)]; 150 | [stopPath addLineToPoint: CGPointMake(10.68, 9.5)]; 151 | [stopPath addLineToPoint: CGPointMake(19, 17.82)]; 152 | [stopPath closePath]; 153 | [stopColor setFill]; 154 | [stopPath fill]; 155 | 156 | stopButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 157 | 158 | UIGraphicsEndImageContext(); 159 | 160 | return stopButtonImage; 161 | } 162 | 163 | 164 | + (id)cy_actionButtonIcon{ 165 | UIImage *actionButtonImage = nil; 166 | UIGraphicsBeginImageContextWithOptions((CGSize){19,30}, NO, [[UIScreen mainScreen] scale]); 167 | //// Color Declarations 168 | UIColor* actionColor = [UIColor blackColor]; 169 | 170 | //// ActionButton Drawing 171 | UIBezierPath* actionButtonPath = [UIBezierPath bezierPath]; 172 | [actionButtonPath moveToPoint: CGPointMake(1, 9)]; 173 | [actionButtonPath addLineToPoint: CGPointMake(1, 26.02)]; 174 | [actionButtonPath addLineToPoint: CGPointMake(18, 26.02)]; 175 | [actionButtonPath addLineToPoint: CGPointMake(18, 9)]; 176 | [actionButtonPath addLineToPoint: CGPointMake(12, 9)]; 177 | [actionButtonPath addLineToPoint: CGPointMake(12, 8)]; 178 | [actionButtonPath addLineToPoint: CGPointMake(19, 8)]; 179 | [actionButtonPath addLineToPoint: CGPointMake(19, 27)]; 180 | [actionButtonPath addLineToPoint: CGPointMake(0, 27)]; 181 | [actionButtonPath addLineToPoint: CGPointMake(0, 8)]; 182 | [actionButtonPath addLineToPoint: CGPointMake(7, 8)]; 183 | [actionButtonPath addLineToPoint: CGPointMake(7, 9)]; 184 | [actionButtonPath addLineToPoint: CGPointMake(1, 9)]; 185 | [actionButtonPath closePath]; 186 | 187 | 188 | [actionButtonPath moveToPoint: CGPointMake(9, 0.98)]; 189 | [actionButtonPath addLineToPoint: CGPointMake(10, 0.98)]; 190 | [actionButtonPath addLineToPoint: CGPointMake(10, 17)]; 191 | [actionButtonPath addLineToPoint: CGPointMake(9, 17)]; 192 | [actionButtonPath addLineToPoint: CGPointMake(9, 0.98)]; 193 | [actionButtonPath closePath]; 194 | [actionButtonPath moveToPoint: CGPointMake(13.99, 4.62)]; 195 | [actionButtonPath addLineToPoint: CGPointMake(13.58, 5.01)]; 196 | [actionButtonPath addCurveToPoint: CGPointMake(13.25, 5.02) controlPoint1: CGPointMake(13.49, 5.1) controlPoint2: CGPointMake(13.34, 5.11)]; 197 | [actionButtonPath addLineToPoint: CGPointMake(9.43, 1.27)]; 198 | [actionButtonPath addCurveToPoint: CGPointMake(9.44, 0.94) controlPoint1: CGPointMake(9.34, 1.18) controlPoint2: CGPointMake(9.35, 1.04)]; 199 | [actionButtonPath addLineToPoint: CGPointMake(9.85, 0.56)]; 200 | [actionButtonPath addCurveToPoint: CGPointMake(10.18, 0.55) controlPoint1: CGPointMake(9.94, 0.46) controlPoint2: CGPointMake(10.09, 0.46)]; 201 | [actionButtonPath addLineToPoint: CGPointMake(14, 4.29)]; 202 | [actionButtonPath addCurveToPoint: CGPointMake(13.99, 4.62) controlPoint1: CGPointMake(14.09, 4.38) controlPoint2: CGPointMake(14.08, 4.53)]; 203 | [actionButtonPath closePath]; 204 | [actionButtonPath moveToPoint: CGPointMake(5.64, 4.95)]; 205 | [actionButtonPath addLineToPoint: CGPointMake(5.27, 4.56)]; 206 | [actionButtonPath addCurveToPoint: CGPointMake(5.26, 4.23) controlPoint1: CGPointMake(5.18, 4.47) controlPoint2: CGPointMake(5.17, 4.32)]; 207 | [actionButtonPath addLineToPoint: CGPointMake(9.46, 0.07)]; 208 | [actionButtonPath addCurveToPoint: CGPointMake(9.79, 0.07) controlPoint1: CGPointMake(9.55, -0.02) controlPoint2: CGPointMake(9.69, -0.02)]; 209 | [actionButtonPath addLineToPoint: CGPointMake(10.16, 0.47)]; 210 | [actionButtonPath addCurveToPoint: CGPointMake(10.17, 0.8) controlPoint1: CGPointMake(10.25, 0.56) controlPoint2: CGPointMake(10.26, 0.71)]; 211 | [actionButtonPath addLineToPoint: CGPointMake(5.97, 4.96)]; 212 | [actionButtonPath addCurveToPoint: CGPointMake(5.64, 4.95) controlPoint1: CGPointMake(5.88, 5.05) controlPoint2: CGPointMake(5.74, 5.05)]; 213 | [actionButtonPath closePath]; 214 | [actionColor setFill]; 215 | [actionButtonPath fill]; 216 | 217 | actionButtonImage = UIGraphicsGetImageFromCurrentImageContext(); 218 | 219 | 220 | UIGraphicsEndImageContext(); 221 | 222 | return actionButtonImage; 223 | } 224 | 225 | 226 | 227 | @end 228 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/NJKWebViewProgress/NJKWebViewProgress.h: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgress.h 3 | // 4 | // Created by Satoshi Aasano on 4/20/13. 5 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | #undef njk_weak 12 | #if __has_feature(objc_arc_weak) 13 | #define njk_weak weak 14 | #else 15 | #define njk_weak unsafe_unretained 16 | #endif 17 | 18 | extern const float NJKInitialProgressValue; 19 | extern const float NJKInteractiveProgressValue; 20 | extern const float NJKFinalProgressValue; 21 | 22 | typedef void (^NJKWebViewProgressBlock)(float progress); 23 | @protocol NJKWebViewProgressDelegate; 24 | @interface NJKWebViewProgress : NSObject 25 | @property (nonatomic, njk_weak) idprogressDelegate; 26 | @property (nonatomic, njk_weak) idwebViewProxyDelegate; 27 | @property (nonatomic, copy) NJKWebViewProgressBlock progressBlock; 28 | @property (nonatomic, readonly) float progress; // 0.0..1.0 29 | 30 | - (void)reset; 31 | @end 32 | 33 | @protocol NJKWebViewProgressDelegate 34 | - (void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress; 35 | @end 36 | 37 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/NJKWebViewProgress/NJKWebViewProgress.m: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgress.m 3 | // 4 | // Created by Satoshi Aasano on 4/20/13. 5 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 6 | // 7 | 8 | #import "NJKWebViewProgress.h" 9 | 10 | NSString *completeRPCURLPath = @"/njkwebviewprogressproxy/complete"; 11 | 12 | const float NJKInitialProgressValue = 0.1f; 13 | const float NJKInteractiveProgressValue = 0.5f; 14 | const float NJKFinalProgressValue = 0.9f; 15 | 16 | @implementation NJKWebViewProgress 17 | { 18 | NSUInteger _loadingCount; 19 | NSUInteger _maxLoadCount; 20 | NSURL *_currentURL; 21 | BOOL _interactive; 22 | } 23 | 24 | - (id)init 25 | { 26 | self = [super init]; 27 | if (self) { 28 | _maxLoadCount = _loadingCount = 0; 29 | _interactive = NO; 30 | } 31 | return self; 32 | } 33 | 34 | - (void)startProgress 35 | { 36 | if (_progress < NJKInitialProgressValue) { 37 | [self setProgress:NJKInitialProgressValue]; 38 | } 39 | } 40 | 41 | - (void)incrementProgress 42 | { 43 | float progress = self.progress; 44 | float maxProgress = _interactive ? NJKFinalProgressValue : NJKInteractiveProgressValue; 45 | float remainPercent = (float)_loadingCount / (float)_maxLoadCount; 46 | float increment = (maxProgress - progress) * remainPercent; 47 | progress += increment; 48 | progress = fmin(progress, maxProgress); 49 | [self setProgress:progress]; 50 | } 51 | 52 | - (void)completeProgress 53 | { 54 | [self setProgress:1.0]; 55 | } 56 | 57 | - (void)setProgress:(float)progress 58 | { 59 | // progress should be incremental only 60 | if (progress > _progress || progress == 0) { 61 | _progress = progress; 62 | if ([_progressDelegate respondsToSelector:@selector(webViewProgress:updateProgress:)]) { 63 | [_progressDelegate webViewProgress:self updateProgress:progress]; 64 | } 65 | if (_progressBlock) { 66 | _progressBlock(progress); 67 | } 68 | } 69 | } 70 | 71 | - (void)reset 72 | { 73 | _maxLoadCount = _loadingCount = 0; 74 | _interactive = NO; 75 | [self setProgress:0.0]; 76 | } 77 | 78 | #pragma mark - 79 | #pragma mark UIWebViewDelegate 80 | 81 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 82 | { 83 | if ([request.URL.path isEqualToString:completeRPCURLPath]) { 84 | [self completeProgress]; 85 | return NO; 86 | } 87 | 88 | BOOL ret = YES; 89 | if ([_webViewProxyDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { 90 | ret = [_webViewProxyDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; 91 | } 92 | 93 | BOOL isFragmentJump = NO; 94 | if (request.URL.fragment) { 95 | NSString *nonFragmentURL = [request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:request.URL.fragment] withString:@""]; 96 | isFragmentJump = [nonFragmentURL isEqualToString:webView.request.URL.absoluteString]; 97 | } 98 | 99 | BOOL isTopLevelNavigation = [request.mainDocumentURL isEqual:request.URL]; 100 | 101 | BOOL isHTTPOrLocalFile = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"] || [request.URL.scheme isEqualToString:@"file"]; 102 | if (ret && !isFragmentJump && isHTTPOrLocalFile && isTopLevelNavigation) { 103 | _currentURL = request.URL; 104 | [self reset]; 105 | } 106 | return ret; 107 | } 108 | 109 | - (void)webViewDidStartLoad:(UIWebView *)webView 110 | { 111 | if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { 112 | [_webViewProxyDelegate webViewDidStartLoad:webView]; 113 | } 114 | 115 | _loadingCount++; 116 | _maxLoadCount = fmax(_maxLoadCount, _loadingCount); 117 | 118 | [self startProgress]; 119 | } 120 | 121 | - (void)webViewDidFinishLoad:(UIWebView *)webView 122 | { 123 | if ([_webViewProxyDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { 124 | [_webViewProxyDelegate webViewDidFinishLoad:webView]; 125 | } 126 | 127 | _loadingCount--; 128 | [self incrementProgress]; 129 | 130 | NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; 131 | 132 | BOOL interactive = [readyState isEqualToString:@"interactive"]; 133 | if (interactive) { 134 | _interactive = YES; 135 | NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@://%@%@'; document.body.appendChild(iframe); }, false);", webView.request.mainDocumentURL.scheme, webView.request.mainDocumentURL.host, completeRPCURLPath]; 136 | [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS]; 137 | } 138 | 139 | BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL]; 140 | BOOL complete = [readyState isEqualToString:@"complete"]; 141 | if (complete && isNotRedirect) { 142 | [self completeProgress]; 143 | } 144 | } 145 | 146 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 147 | { 148 | if ([_webViewProxyDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { 149 | [_webViewProxyDelegate webView:webView didFailLoadWithError:error]; 150 | } 151 | 152 | _loadingCount--; 153 | [self incrementProgress]; 154 | 155 | NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; 156 | 157 | BOOL interactive = [readyState isEqualToString:@"interactive"]; 158 | if (interactive) { 159 | _interactive = YES; 160 | NSString *waitForCompleteJS = [NSString stringWithFormat:@"window.addEventListener('load',function() { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = '%@://%@%@'; document.body.appendChild(iframe); }, false);", webView.request.mainDocumentURL.scheme, webView.request.mainDocumentURL.host, completeRPCURLPath]; 161 | [webView stringByEvaluatingJavaScriptFromString:waitForCompleteJS]; 162 | } 163 | 164 | BOOL isNotRedirect = _currentURL && [_currentURL isEqual:webView.request.mainDocumentURL]; 165 | BOOL complete = [readyState isEqualToString:@"complete"]; 166 | if ((complete && isNotRedirect) || error) { 167 | [self completeProgress]; 168 | } 169 | } 170 | 171 | #pragma mark - 172 | #pragma mark Method Forwarding 173 | // for future UIWebViewDelegate impl 174 | 175 | - (BOOL)respondsToSelector:(SEL)aSelector 176 | { 177 | if ( [super respondsToSelector:aSelector] ) 178 | return YES; 179 | 180 | if ([self.webViewProxyDelegate respondsToSelector:aSelector]) 181 | return YES; 182 | 183 | return NO; 184 | } 185 | 186 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 187 | { 188 | NSMethodSignature *signature = [super methodSignatureForSelector:selector]; 189 | if(!signature) { 190 | if([_webViewProxyDelegate respondsToSelector:selector]) { 191 | return [(NSObject *)_webViewProxyDelegate methodSignatureForSelector:selector]; 192 | } 193 | } 194 | return signature; 195 | } 196 | 197 | - (void)forwardInvocation:(NSInvocation*)invocation 198 | { 199 | if ([_webViewProxyDelegate respondsToSelector:[invocation selector]]) { 200 | [invocation invokeWithTarget:_webViewProxyDelegate]; 201 | } 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/NJKWebViewProgress/NJKWebViewProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgressView.h 3 | // iOS 7 Style WebView Progress Bar 4 | // 5 | // Created by Satoshi Aasano on 11/16/13. 6 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NJKWebViewProgressView : UIView 12 | @property (nonatomic) float progress; 13 | 14 | @property (nonatomic) UIView *progressBarView; 15 | @property (nonatomic) NSTimeInterval barAnimationDuration; // default 0.1 16 | @property (nonatomic) NSTimeInterval fadeAnimationDuration; // default 0.27 17 | @property (nonatomic) NSTimeInterval fadeOutDelay; // default 0.1 18 | 19 | - (void)setProgress:(float)progress animated:(BOOL)animated; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/NJKWebViewProgress/NJKWebViewProgressView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NJKWebViewProgressView.m 3 | // 4 | // Created by Satoshi Aasanoon 11/16/13. 5 | // Copyright (c) 2013 Satoshi Asano. All rights reserved. 6 | // 7 | 8 | #import "NJKWebViewProgressView.h" 9 | 10 | @implementation NJKWebViewProgressView 11 | 12 | - (id)initWithFrame:(CGRect)frame 13 | { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | [self configureViews]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)awakeFromNib 22 | { 23 | [super awakeFromNib]; 24 | [self configureViews]; 25 | } 26 | 27 | -(void)configureViews 28 | { 29 | self.userInteractionEnabled = NO; 30 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth; 31 | _progressBarView = [[UIView alloc] initWithFrame:self.bounds]; 32 | _progressBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 33 | UIColor *tintColor = [UIColor colorWithRed:22.f / 255.f green:126.f / 255.f blue:251.f / 255.f alpha:1.0]; // iOS7 Safari bar color 34 | if ([UIApplication.sharedApplication.delegate.window respondsToSelector:@selector(setTintColor:)] && UIApplication.sharedApplication.delegate.window.tintColor) { 35 | tintColor = UIApplication.sharedApplication.delegate.window.tintColor; 36 | } 37 | _progressBarView.backgroundColor = tintColor; 38 | [self addSubview:_progressBarView]; 39 | 40 | _barAnimationDuration = 0.27f; 41 | _fadeAnimationDuration = 0.27f; 42 | _fadeOutDelay = 0.1f; 43 | } 44 | 45 | -(void)setProgress:(float)progress 46 | { 47 | [self setProgress:progress animated:NO]; 48 | } 49 | 50 | - (void)setProgress:(float)progress animated:(BOOL)animated 51 | { 52 | BOOL isGrowing = progress > 0.0; 53 | [UIView animateWithDuration:(isGrowing && animated) ? _barAnimationDuration : 0.0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 54 | CGRect frame = _progressBarView.frame; 55 | frame.size.width = progress * self.bounds.size.width; 56 | _progressBarView.frame = frame; 57 | } completion:nil]; 58 | 59 | if (progress >= 1.0) { 60 | [UIView animateWithDuration:animated ? _fadeAnimationDuration : 0.0 delay:_fadeOutDelay options:UIViewAnimationOptionCurveEaseInOut animations:^{ 61 | _progressBarView.alpha = 0.0; 62 | } completion:^(BOOL completed){ 63 | CGRect frame = _progressBarView.frame; 64 | frame.size.width = 0; 65 | _progressBarView.frame = frame; 66 | }]; 67 | } 68 | else { 69 | [UIView animateWithDuration:animated ? _fadeAnimationDuration : 0.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 70 | _progressBarView.alpha = 1.0; 71 | } completion:nil]; 72 | } 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/UINavigationBar+Awesome.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationBar+Awesome.h 3 | // LTNavigationBar 4 | // 5 | // Created by ltebean on 15-2-15. 6 | // Copyright (c) 2015 ltebean. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UINavigationBar (Awesome) 12 | - (void)lt_setBackgroundColor:(UIColor *)backgroundColor; 13 | - (void)lt_setElementsAlpha:(CGFloat)alpha; 14 | - (void)lt_setTranslationY:(CGFloat)translationY; 15 | - (void)lt_reset; 16 | @end 17 | -------------------------------------------------------------------------------- /CYWebviewController/Classes/UINavigationBar+Awesome.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationBar+Awesome.m 3 | // LTNavigationBar 4 | // 5 | // Created by ltebean on 15-2-15. 6 | // Copyright (c) 2015 ltebean. All rights reserved. 7 | // 8 | 9 | #import "UINavigationBar+Awesome.h" 10 | #import 11 | 12 | @implementation UINavigationBar (Awesome) 13 | static char overlayKey; 14 | 15 | - (UIView *)overlay 16 | { 17 | return objc_getAssociatedObject(self, &overlayKey); 18 | } 19 | 20 | - (void)setOverlay:(UIView *)overlay 21 | { 22 | objc_setAssociatedObject(self, &overlayKey, overlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | } 24 | 25 | - (void)lt_setBackgroundColor:(UIColor *)backgroundColor 26 | { 27 | if (!self.overlay) { 28 | [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; 29 | self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width, CGRectGetHeight(self.bounds) + 20)]; 30 | self.overlay.userInteractionEnabled = NO; 31 | self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 32 | [self insertSubview:self.overlay atIndex:0]; 33 | } 34 | self.overlay.backgroundColor = backgroundColor; 35 | } 36 | 37 | - (void)lt_setTranslationY:(CGFloat)translationY 38 | { 39 | self.transform = CGAffineTransformMakeTranslation(0, translationY); 40 | } 41 | 42 | - (void)lt_setElementsAlpha:(CGFloat)alpha 43 | { 44 | [[self valueForKey:@"_leftViews"] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger i, BOOL *stop) { 45 | view.alpha = alpha; 46 | }]; 47 | 48 | [[self valueForKey:@"_rightViews"] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger i, BOOL *stop) { 49 | view.alpha = alpha; 50 | }]; 51 | 52 | UIView *titleView = [self valueForKey:@"_titleView"]; 53 | titleView.alpha = alpha; 54 | } 55 | 56 | - (void)lt_reset 57 | { 58 | [self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; 59 | [self.overlay removeFromSuperview]; 60 | self.overlay = nil; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Example/CYWebviewController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/CYWebviewController.xcodeproj/xcshareddata/xcschemes/CYWebviewController-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Example/CYWebviewController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/CYWebviewController/CYAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // CYAppDelegate.h 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 07/12/2016. 6 | // Copyright (c) 2016 万鸿恩. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface CYAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/CYWebviewController/CYAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // CYAppDelegate.m 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 07/12/2016. 6 | // Copyright (c) 2016 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import "CYAppDelegate.h" 10 | 11 | @implementation CYAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/CYWebviewController/CYViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CYViewController.h 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/30. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CYViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/CYWebviewController/CYViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CYViewController.m 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 16/5/30. 6 | // Copyright © 2016年 万鸿恩. All rights reserved. 7 | // 8 | 9 | #import "CYViewController.h" 10 | #import "UIColor+WHE.h" 11 | #import "UINavigationBar+Awesome.h" 12 | #import "CYWebViewController.h" 13 | 14 | 15 | 16 | @interface CYViewController () 17 | 18 | @property (nonatomic,strong) UITableView *tableView; 19 | 20 | @end 21 | 22 | @implementation CYViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view, typically from a nib. 27 | [self.view addSubview:self.tableView]; 28 | self.navigationItem.title = @"Demo"; 29 | 30 | [self setNavColor]; 31 | } 32 | 33 | /** 34 | * 设置导航栏的颜色,返回按钮和标题为白色 35 | */ 36 | -(void)setNavColor{ 37 | NSArray *ver = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; 38 | if ([[ver objectAtIndex:0] intValue] >= 7) { 39 | // iOS 7.0 or later 40 | [self.navigationController.navigationBar lt_setBackgroundColor:[UIColor colorFromHexString:@"12baaa"]]; 41 | 42 | self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; 43 | [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; 44 | 45 | 46 | self.navigationController.navigationBar.translucent = YES; 47 | 48 | 49 | }else { 50 | // iOS 6.1 or earlier 51 | self.navigationController.navigationBar.tintColor =[UIColor colorFromHexString:@"12baaa"]; 52 | 53 | } 54 | } 55 | 56 | 57 | -(UITableView*)tableView{ 58 | if (!_tableView) { 59 | _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; 60 | _tableView.dataSource = self; 61 | _tableView.delegate = self; 62 | _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; 63 | } 64 | return _tableView; 65 | } 66 | 67 | 68 | -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 69 | return 2; 70 | } 71 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 72 | if (section == 1) { 73 | return 1; 74 | } 75 | return 2; 76 | } 77 | 78 | -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 79 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tracy"]; 80 | if (cell==nil) { 81 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"tracy"]; 82 | } 83 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 84 | if (indexPath.section == 0) { 85 | if (indexPath.row == 0) { 86 | cell.textLabel.text = @"测试push"; 87 | }else{ 88 | cell.textLabel.text = @"测试"; 89 | } 90 | }else{ 91 | cell.textLabel.text = @"测试Wechat Mode"; 92 | } 93 | return cell; 94 | } 95 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 96 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 97 | 98 | if (indexPath.section == 0) { 99 | if (indexPath.row == 0) { 100 | CYWebViewController *controller = [[CYWebViewController alloc] init]; 101 | controller.url = [NSURL URLWithString:@"https://www.baidu.com/"]; 102 | controller.loadingBarTintColor = [UIColor redColor]; 103 | controller.navigationButtonsHidden = NO; 104 | [self.navigationController pushViewController:controller animated:YES]; 105 | }else{ 106 | CYWebViewController *controller = [[CYWebViewController alloc] init]; 107 | controller.url = [NSURL URLWithString:@"https://www.baidu.com/"]; 108 | controller.loadingBarTintColor = [UIColor redColor]; 109 | controller.navigationButtonsHidden = NO; 110 | [self presentViewController:[[UINavigationController alloc] initWithRootViewController:controller] animated:YES completion:nil]; 111 | } 112 | }else{ 113 | CYWebViewController *controller = [[CYWebViewController alloc] init]; 114 | controller.url = [NSURL URLWithString:@"https://www.baidu.com/"]; 115 | controller.loadingBarTintColor = [UIColor redColor]; 116 | [self.navigationController pushViewController:controller animated:YES]; 117 | } 118 | } 119 | 120 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 121 | return 40; 122 | } 123 | 124 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ 125 | if (section == 0) { 126 | UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 260, 40) ]; 127 | [header setBackgroundColor:[UIColor clearColor]]; 128 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 8, 200, 24)]; 129 | label.text = @"Safari Mode"; 130 | label.textColor = [UIColor grayColor]; 131 | label.font = [UIFont systemFontOfSize:16]; 132 | [header addSubview:label]; 133 | return header; 134 | }else{ 135 | UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 260, 40) ]; 136 | [header setBackgroundColor:[UIColor clearColor]]; 137 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 8, 200, 24)]; 138 | label.text = @"Wechat Mode"; 139 | label.textColor = [UIColor grayColor]; 140 | label.font = [UIFont systemFontOfSize:16]; 141 | [header addSubview:label]; 142 | return header; 143 | } 144 | } 145 | 146 | 147 | 148 | - (void)didReceiveMemoryWarning { 149 | [super didReceiveMemoryWarning]; 150 | // Dispose of any resources that can be recreated. 151 | } 152 | 153 | /* 154 | #pragma mark - Navigation 155 | 156 | // In a storyboard-based application, you will often want to do a little preparation before navigation 157 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 158 | // Get the new view controller using [segue destinationViewController]. 159 | // Pass the selected object to the new view controller. 160 | } 161 | */ 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /Example/CYWebviewController/CYWebviewController-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Launch Screen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | NSAppTransportSecurity 49 | 50 | NSAllowsArbitraryLoads 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Example/CYWebviewController/CYWebviewController-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/CYWebviewController/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/CYWebviewController/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/CYWebviewController/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CYWebviewController 4 | // 5 | // Created by 万鸿恩 on 07/12/2016. 6 | // Copyright (c) 2016 万鸿恩. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "CYAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([CYAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'CYWebviewController_Example' do 4 | pod 'CYWebviewController', :path => '../' 5 | 6 | target 'CYWebviewController_Tests' do 7 | inherit! :search_paths 8 | 9 | pod 'FBSnapshotTestCase' 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - CYWebviewController (1.1.0) 3 | - FBSnapshotTestCase (2.1.0): 4 | - FBSnapshotTestCase/SwiftSupport (= 2.1.0) 5 | - FBSnapshotTestCase/Core (2.1.0) 6 | - FBSnapshotTestCase/SwiftSupport (2.1.0): 7 | - FBSnapshotTestCase/Core 8 | 9 | DEPENDENCIES: 10 | - CYWebviewController (from `../`) 11 | - FBSnapshotTestCase 12 | 13 | EXTERNAL SOURCES: 14 | CYWebviewController: 15 | :path: ../ 16 | 17 | SPEC CHECKSUMS: 18 | CYWebviewController: 1ea34254b33d6a7262901eec50eafba9ac3ec745 19 | FBSnapshotTestCase: 366ecd378511d7716c79991cd8067d1eed23578d 20 | 21 | PODFILE CHECKSUM: 6bcf6250c2b2a3daf81480fb88976903b92806fa 22 | 23 | COCOAPODS: 1.0.1 24 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase.modulemap: -------------------------------------------------------------------------------- 1 | framework module FBSnapshotTestCase { 2 | umbrella header "FBSnapshotTestCase.h" 3 | 4 | export * 5 | module * { export * } 6 | 7 | header "FBSnapshotTestCase.h" 8 | header "FBSnapshotTestCasePlatform.h" 9 | header "FBSnapshotTestController.h" 10 | 11 | private header "UIImage+Compare.h" 12 | private header "UIImage+Diff.h" 13 | private header "UIImage+Snapshot.h" 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | @interface UIApplication (StrictKeyWindow) 14 | 15 | /** 16 | @return The receiver's @c keyWindow. Raises an assertion if @c nil. 17 | */ 18 | - (UIWindow *)fb_strictKeyWindow; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | @implementation UIApplication (StrictKeyWindow) 14 | 15 | - (UIWindow *)fb_strictKeyWindow 16 | { 17 | UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; 18 | if (!keyWindow) { 19 | [NSException raise:@"FBSnapshotTestCaseNilKeyWindowException" 20 | format:@"Snapshot tests must be hosted by an application with a key window. Please ensure your test" 21 | " host sets up a key window at launch (either via storyboards or programmatically) and doesn't" 22 | " do anything to remove it while snapshot tests are running."]; 23 | } 24 | return keyWindow; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | @interface UIImage (Compare) 34 | 35 | - (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | // This makes debugging much more fun 34 | typedef union { 35 | uint32_t raw; 36 | unsigned char bytes[4]; 37 | struct { 38 | char red; 39 | char green; 40 | char blue; 41 | char alpha; 42 | } __attribute__ ((packed)) pixels; 43 | } FBComparePixel; 44 | 45 | @implementation UIImage (Compare) 46 | 47 | - (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance 48 | { 49 | NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size."); 50 | 51 | CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)); 52 | CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); 53 | 54 | // The images have the equal size, so we could use the smallest amount of bytes because of byte padding 55 | size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage)); 56 | size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow; 57 | void *referenceImagePixels = calloc(1, referenceImageSizeBytes); 58 | void *imagePixels = calloc(1, referenceImageSizeBytes); 59 | 60 | if (!referenceImagePixels || !imagePixels) { 61 | free(referenceImagePixels); 62 | free(imagePixels); 63 | return NO; 64 | } 65 | 66 | CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels, 67 | referenceImageSize.width, 68 | referenceImageSize.height, 69 | CGImageGetBitsPerComponent(self.CGImage), 70 | minBytesPerRow, 71 | CGImageGetColorSpace(self.CGImage), 72 | (CGBitmapInfo)kCGImageAlphaPremultipliedLast 73 | ); 74 | CGContextRef imageContext = CGBitmapContextCreate(imagePixels, 75 | imageSize.width, 76 | imageSize.height, 77 | CGImageGetBitsPerComponent(image.CGImage), 78 | minBytesPerRow, 79 | CGImageGetColorSpace(image.CGImage), 80 | (CGBitmapInfo)kCGImageAlphaPremultipliedLast 81 | ); 82 | 83 | if (!referenceImageContext || !imageContext) { 84 | CGContextRelease(referenceImageContext); 85 | CGContextRelease(imageContext); 86 | free(referenceImagePixels); 87 | free(imagePixels); 88 | return NO; 89 | } 90 | 91 | CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage); 92 | CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage); 93 | 94 | CGContextRelease(referenceImageContext); 95 | CGContextRelease(imageContext); 96 | 97 | BOOL imageEqual = YES; 98 | 99 | // Do a fast compare if we can 100 | if (tolerance == 0) { 101 | imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0); 102 | } else { 103 | // Go through each pixel in turn and see if it is different 104 | const NSInteger pixelCount = referenceImageSize.width * referenceImageSize.height; 105 | 106 | FBComparePixel *p1 = referenceImagePixels; 107 | FBComparePixel *p2 = imagePixels; 108 | 109 | NSInteger numDiffPixels = 0; 110 | for (int n = 0; n < pixelCount; ++n) { 111 | // If this pixel is different, increment the pixel diff count and see 112 | // if we have hit our limit. 113 | if (p1->raw != p2->raw) { 114 | numDiffPixels ++; 115 | 116 | CGFloat percent = (CGFloat)numDiffPixels / pixelCount; 117 | if (percent > tolerance) { 118 | imageEqual = NO; 119 | break; 120 | } 121 | } 122 | 123 | p1++; 124 | p2++; 125 | } 126 | } 127 | 128 | free(referenceImagePixels); 129 | free(imagePixels); 130 | 131 | return imageEqual; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | @interface UIImage (Diff) 34 | 35 | - (UIImage *)fb_diffWithImage:(UIImage *)image; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Gabriel Handford on 3/1/09. 3 | // Copyright 2009-2013. All rights reserved. 4 | // Created by John Boiles on 10/20/11. 5 | // Copyright (c) 2011. All rights reserved 6 | // Modified by Felix Schulze on 2/11/13. 7 | // Copyright 2013. All rights reserved. 8 | // 9 | // Permission is hereby granted, free of charge, to any person 10 | // obtaining a copy of this software and associated documentation 11 | // files (the "Software"), to deal in the Software without 12 | // restriction, including without limitation the rights to use, 13 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the 15 | // Software is furnished to do so, subject to the following 16 | // conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | // OTHER DEALINGS IN THE SOFTWARE. 29 | // 30 | 31 | #import 32 | 33 | @implementation UIImage (Diff) 34 | 35 | - (UIImage *)fb_diffWithImage:(UIImage *)image 36 | { 37 | if (!image) { 38 | return nil; 39 | } 40 | CGSize imageSize = CGSizeMake(MAX(self.size.width, image.size.width), MAX(self.size.height, image.size.height)); 41 | UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0); 42 | CGContextRef context = UIGraphicsGetCurrentContext(); 43 | [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; 44 | CGContextSetAlpha(context, 0.5); 45 | CGContextBeginTransparencyLayer(context, NULL); 46 | [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; 47 | CGContextSetBlendMode(context, kCGBlendModeDifference); 48 | CGContextSetFillColorWithColor(context,[UIColor whiteColor].CGColor); 49 | CGContextFillRect(context, CGRectMake(0, 0, self.size.width, self.size.height)); 50 | CGContextEndTransparencyLayer(context); 51 | UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); 52 | UIGraphicsEndImageContext(); 53 | return returnImage; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | @interface UIImage (Snapshot) 14 | 15 | /// Uses renderInContext: to get a snapshot of the layer. 16 | + (UIImage *)fb_imageForLayer:(CALayer *)layer; 17 | 18 | /// Uses renderInContext: to get a snapshot of the view layer. 19 | + (UIImage *)fb_imageForViewLayer:(UIView *)view; 20 | 21 | /// Uses drawViewHierarchyInRect: to get a snapshot of the view and adds the view into a window if needed. 22 | + (UIImage *)fb_imageForView:(UIView *)view; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | @implementation UIImage (Snapshot) 15 | 16 | + (UIImage *)fb_imageForLayer:(CALayer *)layer 17 | { 18 | CGRect bounds = layer.bounds; 19 | NSAssert1(CGRectGetWidth(bounds), @"Zero width for layer %@", layer); 20 | NSAssert1(CGRectGetHeight(bounds), @"Zero height for layer %@", layer); 21 | 22 | UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); 23 | CGContextRef context = UIGraphicsGetCurrentContext(); 24 | NSAssert1(context, @"Could not generate context for layer %@", layer); 25 | CGContextSaveGState(context); 26 | [layer layoutIfNeeded]; 27 | [layer renderInContext:context]; 28 | CGContextRestoreGState(context); 29 | 30 | UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); 31 | UIGraphicsEndImageContext(); 32 | return snapshot; 33 | } 34 | 35 | + (UIImage *)fb_imageForViewLayer:(UIView *)view 36 | { 37 | [view layoutIfNeeded]; 38 | return [self fb_imageForLayer:view.layer]; 39 | } 40 | 41 | + (UIImage *)fb_imageForView:(UIView *)view 42 | { 43 | CGRect bounds = view.bounds; 44 | NSAssert1(CGRectGetWidth(bounds), @"Zero width for view %@", view); 45 | NSAssert1(CGRectGetHeight(bounds), @"Zero height for view %@", view); 46 | 47 | // If the input view is already a UIWindow, then just use that. Otherwise wrap in a window. 48 | UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *)view : view.window; 49 | BOOL removeFromSuperview = NO; 50 | if (!window) { 51 | window = [[UIApplication sharedApplication] fb_strictKeyWindow]; 52 | } 53 | 54 | if (!view.window && view != window) { 55 | [window addSubview:view]; 56 | removeFromSuperview = YES; 57 | } 58 | 59 | UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); 60 | [view layoutIfNeeded]; 61 | [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; 62 | 63 | UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); 64 | UIGraphicsEndImageContext(); 65 | 66 | if (removeFromSuperview) { 67 | [view removeFromSuperview]; 68 | } 69 | 70 | return snapshot; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | #import 15 | 16 | #import 17 | 18 | #import 19 | 20 | /* 21 | There are three ways of setting reference image directories. 22 | 23 | 1. Set the preprocessor macro FB_REFERENCE_IMAGE_DIR to a double quoted 24 | c-string with the path. 25 | 2. Set an environment variable named FB_REFERENCE_IMAGE_DIR with the path. This 26 | takes precedence over the preprocessor macro to allow for run-time override. 27 | 3. Keep everything unset, which will cause the reference images to be looked up 28 | inside the bundle holding the current test, in the 29 | Resources/ReferenceImages_* directories. 30 | */ 31 | #ifndef FB_REFERENCE_IMAGE_DIR 32 | #define FB_REFERENCE_IMAGE_DIR "" 33 | #endif 34 | 35 | /** 36 | Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though. 37 | @param view The view to snapshot 38 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 39 | @param suffixes An NSOrderedSet of strings for the different suffixes 40 | @param tolerance The percentage of pixels that can differ and still count as an 'identical' view 41 | */ 42 | #define FBSnapshotVerifyViewWithOptions(view__, identifier__, suffixes__, tolerance__) \ 43 | FBSnapshotVerifyViewOrLayerWithOptions(View, view__, identifier__, suffixes__, tolerance__) 44 | 45 | #define FBSnapshotVerifyView(view__, identifier__) \ 46 | FBSnapshotVerifyViewWithOptions(view__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0) 47 | 48 | 49 | /** 50 | Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though. 51 | @param layer The layer to snapshot 52 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 53 | @param suffixes An NSOrderedSet of strings for the different suffixes 54 | @param tolerance The percentage of pixels that can differ and still count as an 'identical' layer 55 | */ 56 | #define FBSnapshotVerifyLayerWithOptions(layer__, identifier__, suffixes__, tolerance__) \ 57 | FBSnapshotVerifyViewOrLayerWithOptions(Layer, layer__, identifier__, suffixes__, tolerance__) 58 | 59 | #define FBSnapshotVerifyLayer(layer__, identifier__) \ 60 | FBSnapshotVerifyLayerWithOptions(layer__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0) 61 | 62 | 63 | #define FBSnapshotVerifyViewOrLayerWithOptions(what__, viewOrLayer__, identifier__, suffixes__, tolerance__) \ 64 | { \ 65 | NSString *referenceImageDirectory = [self getReferenceImageDirectoryWithDefault:(@ FB_REFERENCE_IMAGE_DIR)]; \ 66 | XCTAssertNotNil(referenceImageDirectory, @"Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.");\ 67 | XCTAssertTrue((suffixes__.count > 0), @"Suffixes set cannot be empty %@", suffixes__); \ 68 | \ 69 | BOOL testSuccess__ = NO; \ 70 | NSError *error__ = nil; \ 71 | NSMutableArray *errors__ = [NSMutableArray array]; \ 72 | \ 73 | if (self.recordMode) { \ 74 | \ 75 | NSString *referenceImagesDirectory__ = [NSString stringWithFormat:@"%@%@", referenceImageDirectory, suffixes__.firstObject]; \ 76 | BOOL referenceImageSaved__ = [self compareSnapshotOf ## what__ :(viewOrLayer__) referenceImagesDirectory:referenceImagesDirectory__ identifier:(identifier__) tolerance:(tolerance__) error:&error__]; \ 77 | if (!referenceImageSaved__) { \ 78 | [errors__ addObject:error__]; \ 79 | } \ 80 | } else { \ 81 | \ 82 | for (NSString *suffix__ in suffixes__) { \ 83 | NSString *referenceImagesDirectory__ = [NSString stringWithFormat:@"%@%@", referenceImageDirectory, suffix__]; \ 84 | BOOL referenceImageAvailable = [self referenceImageRecordedInDirectory:referenceImagesDirectory__ identifier:(identifier__) error:&error__]; \ 85 | \ 86 | if (referenceImageAvailable) { \ 87 | BOOL comparisonSuccess__ = [self compareSnapshotOf ## what__ :(viewOrLayer__) referenceImagesDirectory:referenceImagesDirectory__ identifier:(identifier__) tolerance:(tolerance__) error:&error__]; \ 88 | [errors__ removeAllObjects]; \ 89 | if (comparisonSuccess__) { \ 90 | testSuccess__ = YES; \ 91 | break; \ 92 | } else { \ 93 | [errors__ addObject:error__]; \ 94 | } \ 95 | } else { \ 96 | [errors__ addObject:error__]; \ 97 | } \ 98 | } \ 99 | } \ 100 | XCTAssertTrue(testSuccess__, @"Snapshot comparison failed: %@", errors__.firstObject); \ 101 | XCTAssertFalse(self.recordMode, @"Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!"); \ 102 | } 103 | 104 | 105 | /** 106 | The base class of view snapshotting tests. If you have small UI component, it's often easier to configure it in a test 107 | and compare an image of the view to a reference image that write lots of complex layout-code tests. 108 | 109 | In order to flip the tests in your subclass to record the reference images set @c recordMode to @c YES. 110 | 111 | @attention When recording, the reference image directory should be explicitly 112 | set, otherwise the images may be written to somewhere inside the 113 | simulator directory. 114 | 115 | For example: 116 | @code 117 | - (void)setUp 118 | { 119 | [super setUp]; 120 | self.recordMode = YES; 121 | } 122 | @endcode 123 | */ 124 | @interface FBSnapshotTestCase : XCTestCase 125 | 126 | /** 127 | When YES, the test macros will save reference images, rather than performing an actual test. 128 | */ 129 | @property (readwrite, nonatomic, assign) BOOL recordMode; 130 | 131 | /** 132 | When @c YES appends the name of the device model and OS to the snapshot file name. 133 | The default value is @c NO. 134 | */ 135 | @property (readwrite, nonatomic, assign, getter=isDeviceAgnostic) BOOL deviceAgnostic; 136 | 137 | /** 138 | When YES, renders a snapshot of the complete view hierarchy as visible onscreen. 139 | There are several things that do not work if renderInContext: is used. 140 | - UIVisualEffect #70 141 | - UIAppearance #91 142 | - Size Classes #92 143 | 144 | @attention If the view does't belong to a UIWindow, it will create one and add the view as a subview. 145 | */ 146 | @property (readwrite, nonatomic, assign) BOOL usesDrawViewHierarchyInRect; 147 | 148 | - (void)setUp NS_REQUIRES_SUPER; 149 | - (void)tearDown NS_REQUIRES_SUPER; 150 | 151 | /** 152 | Performs the comparison or records a snapshot of the layer if recordMode is YES. 153 | @param layer The Layer to snapshot 154 | @param referenceImagesDirectory The directory in which reference images are stored. 155 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 156 | @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care 157 | @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 158 | @returns YES if the comparison (or saving of the reference image) succeeded. 159 | */ 160 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 161 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 162 | identifier:(NSString *)identifier 163 | tolerance:(CGFloat)tolerance 164 | error:(NSError **)errorPtr; 165 | 166 | /** 167 | Performs the comparison or records a snapshot of the view if recordMode is YES. 168 | @param view The view to snapshot 169 | @param referenceImagesDirectory The directory in which reference images are stored. 170 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 171 | @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care 172 | @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 173 | @returns YES if the comparison (or saving of the reference image) succeeded. 174 | */ 175 | - (BOOL)compareSnapshotOfView:(UIView *)view 176 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 177 | identifier:(NSString *)identifier 178 | tolerance:(CGFloat)tolerance 179 | error:(NSError **)errorPtr; 180 | 181 | /** 182 | Checks if reference image with identifier based name exists in the reference images directory. 183 | @param referenceImagesDirectory The directory in which reference images are stored. 184 | @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. 185 | @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 186 | @returns YES if reference image exists. 187 | */ 188 | - (BOOL)referenceImageRecordedInDirectory:(NSString *)referenceImagesDirectory 189 | identifier:(NSString *)identifier 190 | error:(NSError **)errorPtr; 191 | 192 | /** 193 | Returns the reference image directory. 194 | 195 | Helper function used to implement the assert macros. 196 | 197 | @param dir directory to use if environment variable not specified. Ignored if null or empty. 198 | */ 199 | - (NSString *)getReferenceImageDirectoryWithDefault:(NSString *)dir; 200 | 201 | @end 202 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | @implementation FBSnapshotTestCase 15 | { 16 | FBSnapshotTestController *_snapshotController; 17 | } 18 | 19 | #pragma mark - Overrides 20 | 21 | - (void)setUp 22 | { 23 | [super setUp]; 24 | _snapshotController = [[FBSnapshotTestController alloc] initWithTestName:NSStringFromClass([self class])]; 25 | } 26 | 27 | - (void)tearDown 28 | { 29 | _snapshotController = nil; 30 | [super tearDown]; 31 | } 32 | 33 | - (BOOL)recordMode 34 | { 35 | return _snapshotController.recordMode; 36 | } 37 | 38 | - (void)setRecordMode:(BOOL)recordMode 39 | { 40 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 41 | _snapshotController.recordMode = recordMode; 42 | } 43 | 44 | - (BOOL)isDeviceAgnostic 45 | { 46 | return _snapshotController.deviceAgnostic; 47 | } 48 | 49 | - (void)setDeviceAgnostic:(BOOL)deviceAgnostic 50 | { 51 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 52 | _snapshotController.deviceAgnostic = deviceAgnostic; 53 | } 54 | 55 | - (BOOL)usesDrawViewHierarchyInRect 56 | { 57 | return _snapshotController.usesDrawViewHierarchyInRect; 58 | } 59 | 60 | - (void)setUsesDrawViewHierarchyInRect:(BOOL)usesDrawViewHierarchyInRect 61 | { 62 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 63 | _snapshotController.usesDrawViewHierarchyInRect = usesDrawViewHierarchyInRect; 64 | } 65 | 66 | #pragma mark - Public API 67 | 68 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 69 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 70 | identifier:(NSString *)identifier 71 | tolerance:(CGFloat)tolerance 72 | error:(NSError **)errorPtr 73 | { 74 | return [self _compareSnapshotOfViewOrLayer:layer 75 | referenceImagesDirectory:referenceImagesDirectory 76 | identifier:identifier 77 | tolerance:tolerance 78 | error:errorPtr]; 79 | } 80 | 81 | - (BOOL)compareSnapshotOfView:(UIView *)view 82 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 83 | identifier:(NSString *)identifier 84 | tolerance:(CGFloat)tolerance 85 | error:(NSError **)errorPtr 86 | { 87 | return [self _compareSnapshotOfViewOrLayer:view 88 | referenceImagesDirectory:referenceImagesDirectory 89 | identifier:identifier 90 | tolerance:tolerance 91 | error:errorPtr]; 92 | } 93 | 94 | - (BOOL)referenceImageRecordedInDirectory:(NSString *)referenceImagesDirectory 95 | identifier:(NSString *)identifier 96 | error:(NSError **)errorPtr 97 | { 98 | NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); 99 | _snapshotController.referenceImagesDirectory = referenceImagesDirectory; 100 | UIImage *referenceImage = [_snapshotController referenceImageForSelector:self.invocation.selector 101 | identifier:identifier 102 | error:errorPtr]; 103 | 104 | return (referenceImage != nil); 105 | } 106 | 107 | - (NSString *)getReferenceImageDirectoryWithDefault:(NSString *)dir 108 | { 109 | NSString *envReferenceImageDirectory = [NSProcessInfo processInfo].environment[@"FB_REFERENCE_IMAGE_DIR"]; 110 | if (envReferenceImageDirectory) { 111 | return envReferenceImageDirectory; 112 | } 113 | if (dir && dir.length > 0) { 114 | return dir; 115 | } 116 | return [[NSBundle bundleForClass:self.class].resourcePath stringByAppendingPathComponent:@"ReferenceImages"]; 117 | } 118 | 119 | 120 | #pragma mark - Private API 121 | 122 | - (BOOL)_compareSnapshotOfViewOrLayer:(id)viewOrLayer 123 | referenceImagesDirectory:(NSString *)referenceImagesDirectory 124 | identifier:(NSString *)identifier 125 | tolerance:(CGFloat)tolerance 126 | error:(NSError **)errorPtr 127 | { 128 | _snapshotController.referenceImagesDirectory = referenceImagesDirectory; 129 | return [_snapshotController compareSnapshotOfViewOrLayer:viewOrLayer 130 | selector:self.invocation.selector 131 | identifier:identifier 132 | tolerance:tolerance 133 | error:errorPtr]; 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /** 18 | Returns a Boolean value that indicates whether the snapshot test is running in 64Bit. 19 | This method is a convenience for creating the suffixes set based on the architecture 20 | that the test is running. 21 | 22 | @returns @c YES if the test is running in 64bit, otherwise @c NO. 23 | */ 24 | BOOL FBSnapshotTestCaseIs64Bit(void); 25 | 26 | /** 27 | Returns a default set of strings that is used to append a suffix based on the architectures. 28 | @warning Do not modify this function, you can create your own and use it with @c FBSnapshotVerifyViewWithOptions() 29 | 30 | @returns An @c NSOrderedSet object containing strings that are appended to the reference images directory. 31 | */ 32 | NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void); 33 | 34 | /** 35 | Returns a fully «normalized» file name. 36 | Strips punctuation and spaces and replaces them with @c _. Also appends the device model, running OS and screen size to the file name. 37 | 38 | @returns An @c NSString object containing the passed @c fileName with the device model, OS and screen size appended at the end. 39 | */ 40 | NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | BOOL FBSnapshotTestCaseIs64Bit(void) 16 | { 17 | #if __LP64__ 18 | return YES; 19 | #else 20 | return NO; 21 | #endif 22 | } 23 | 24 | NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void) 25 | { 26 | NSMutableOrderedSet *suffixesSet = [[NSMutableOrderedSet alloc] init]; 27 | [suffixesSet addObject:@"_32"]; 28 | [suffixesSet addObject:@"_64"]; 29 | if (FBSnapshotTestCaseIs64Bit()) { 30 | return [suffixesSet reversedOrderedSet]; 31 | } 32 | return [suffixesSet copy]; 33 | } 34 | 35 | NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName) 36 | { 37 | UIDevice *device = [UIDevice currentDevice]; 38 | UIWindow *keyWindow = [[UIApplication sharedApplication] fb_strictKeyWindow]; 39 | CGSize screenSize = keyWindow.bounds.size; 40 | NSString *os = device.systemVersion; 41 | 42 | fileName = [NSString stringWithFormat:@"%@_%@%@_%.0fx%.0f", fileName, device.model, os, screenSize.width, screenSize.height]; 43 | 44 | NSMutableCharacterSet *invalidCharacters = [NSMutableCharacterSet new]; 45 | [invalidCharacters formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; 46 | [invalidCharacters formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; 47 | NSArray *validComponents = [fileName componentsSeparatedByCharactersInSet:invalidCharacters]; 48 | fileName = [validComponents componentsJoinedByString:@"_"]; 49 | 50 | return fileName; 51 | } -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | 14 | typedef NS_ENUM(NSInteger, FBSnapshotTestControllerErrorCode) { 15 | FBSnapshotTestControllerErrorCodeUnknown, 16 | FBSnapshotTestControllerErrorCodeNeedsRecord, 17 | FBSnapshotTestControllerErrorCodePNGCreationFailed, 18 | FBSnapshotTestControllerErrorCodeImagesDifferentSizes, 19 | FBSnapshotTestControllerErrorCodeImagesDifferent, 20 | }; 21 | /** 22 | Errors returned by the methods of FBSnapshotTestController use this domain. 23 | */ 24 | extern NSString *const FBSnapshotTestControllerErrorDomain; 25 | 26 | /** 27 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 28 | */ 29 | extern NSString *const FBReferenceImageFilePathKey; 30 | 31 | /** 32 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 33 | */ 34 | extern NSString *const FBReferenceImageKey; 35 | 36 | /** 37 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 38 | */ 39 | extern NSString *const FBCapturedImageKey; 40 | 41 | /** 42 | Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. 43 | */ 44 | extern NSString *const FBDiffedImageKey; 45 | 46 | /** 47 | Provides the heavy-lifting for FBSnapshotTestCase. It loads and saves images, along with performing the actual pixel- 48 | by-pixel comparison of images. 49 | Instances are initialized with the test class, and directories to read and write to. 50 | */ 51 | @interface FBSnapshotTestController : NSObject 52 | 53 | /** 54 | Record snapshots. 55 | */ 56 | @property (readwrite, nonatomic, assign) BOOL recordMode; 57 | 58 | /** 59 | When @c YES appends the name of the device model and OS to the snapshot file name. 60 | The default value is @c NO. 61 | */ 62 | @property (readwrite, nonatomic, assign, getter=isDeviceAgnostic) BOOL deviceAgnostic; 63 | 64 | /** 65 | Uses drawViewHierarchyInRect:afterScreenUpdates: to draw the image instead of renderInContext: 66 | */ 67 | @property (readwrite, nonatomic, assign) BOOL usesDrawViewHierarchyInRect; 68 | 69 | /** 70 | The directory in which referfence images are stored. 71 | */ 72 | @property (readwrite, nonatomic, copy) NSString *referenceImagesDirectory; 73 | 74 | /** 75 | @param testClass The subclass of FBSnapshotTestCase that is using this controller. 76 | @returns An instance of FBSnapshotTestController. 77 | */ 78 | - (instancetype)initWithTestClass:(Class)testClass; 79 | 80 | /** 81 | Designated initializer. 82 | @param testName The name of the tests. 83 | @returns An instance of FBSnapshotTestController. 84 | */ 85 | - (instancetype)initWithTestName:(NSString *)testName; 86 | 87 | /** 88 | Performs the comparison of the layer. 89 | @param layer The Layer to snapshot. 90 | @param selector The test method being run. 91 | @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. 92 | @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 93 | @returns YES if the comparison (or saving of the reference image) succeeded. 94 | */ 95 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 96 | selector:(SEL)selector 97 | identifier:(NSString *)identifier 98 | error:(NSError **)errorPtr; 99 | 100 | /** 101 | Performs the comparison of the view. 102 | @param view The view to snapshot. 103 | @param selector The test method being run. 104 | @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. 105 | @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 106 | @returns YES if the comparison (or saving of the reference image) succeeded. 107 | */ 108 | - (BOOL)compareSnapshotOfView:(UIView *)view 109 | selector:(SEL)selector 110 | identifier:(NSString *)identifier 111 | error:(NSError **)errorPtr; 112 | 113 | /** 114 | Performs the comparison of a view or layer. 115 | @param view The view or layer to snapshot. 116 | @param selector The test method being run. 117 | @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. 118 | @param tolerance The percentage of pixels that can differ and still be considered 'identical' 119 | @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). 120 | @returns YES if the comparison (or saving of the reference image) succeeded. 121 | */ 122 | - (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer 123 | selector:(SEL)selector 124 | identifier:(NSString *)identifier 125 | tolerance:(CGFloat)tolerance 126 | error:(NSError **)errorPtr; 127 | 128 | /** 129 | Loads a reference image. 130 | @param selector The test method being run. 131 | @param identifier The optional identifier, used when multiple images are tested in a single -test method. 132 | @param errorPtr An error, if this methods returns nil, the error will be something useful. 133 | @returns An image. 134 | */ 135 | - (UIImage *)referenceImageForSelector:(SEL)selector 136 | identifier:(NSString *)identifier 137 | error:(NSError **)errorPtr; 138 | 139 | /** 140 | Performs a pixel-by-pixel comparison of the two images with an allowable margin of error. 141 | @param referenceImage The reference (correct) image. 142 | @param image The image to test against the reference. 143 | @param tolerance The percentage of pixels that can differ and still be considered 'identical' 144 | @param errorPtr An error that indicates why the comparison failed if it does. 145 | @returns YES if the comparison succeeded and the images are the same(ish). 146 | */ 147 | - (BOOL)compareReferenceImage:(UIImage *)referenceImage 148 | toImage:(UIImage *)image 149 | tolerance:(CGFloat)tolerance 150 | error:(NSError **)errorPtr; 151 | 152 | /** 153 | Saves the reference image and the test image to `failedOutputDirectory`. 154 | @param referenceImage The reference (correct) image. 155 | @param testImage The image to test against the reference. 156 | @param selector The test method being run. 157 | @param identifier The optional identifier, used when multiple images are tested in a single -test method. 158 | @param errorPtr An error that indicates why the comparison failed if it does. 159 | @returns YES if the save succeeded. 160 | */ 161 | - (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage 162 | testImage:(UIImage *)testImage 163 | selector:(SEL)selector 164 | identifier:(NSString *)identifier 165 | error:(NSError **)errorPtr; 166 | @end 167 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | #import 18 | 19 | NSString *const FBSnapshotTestControllerErrorDomain = @"FBSnapshotTestControllerErrorDomain"; 20 | NSString *const FBReferenceImageFilePathKey = @"FBReferenceImageFilePathKey"; 21 | NSString *const FBReferenceImageKey = @"FBReferenceImageKey"; 22 | NSString *const FBCapturedImageKey = @"FBCapturedImageKey"; 23 | NSString *const FBDiffedImageKey = @"FBDiffedImageKey"; 24 | 25 | typedef NS_ENUM(NSUInteger, FBTestSnapshotFileNameType) { 26 | FBTestSnapshotFileNameTypeReference, 27 | FBTestSnapshotFileNameTypeFailedReference, 28 | FBTestSnapshotFileNameTypeFailedTest, 29 | FBTestSnapshotFileNameTypeFailedTestDiff, 30 | }; 31 | 32 | @implementation FBSnapshotTestController 33 | { 34 | NSString *_testName; 35 | NSFileManager *_fileManager; 36 | } 37 | 38 | #pragma mark - Initializers 39 | 40 | - (instancetype)initWithTestClass:(Class)testClass; 41 | { 42 | return [self initWithTestName:NSStringFromClass(testClass)]; 43 | } 44 | 45 | - (instancetype)initWithTestName:(NSString *)testName 46 | { 47 | if (self = [super init]) { 48 | _testName = [testName copy]; 49 | _deviceAgnostic = NO; 50 | 51 | _fileManager = [[NSFileManager alloc] init]; 52 | } 53 | return self; 54 | } 55 | 56 | #pragma mark - Overrides 57 | 58 | - (NSString *)description 59 | { 60 | return [NSString stringWithFormat:@"%@ %@", [super description], _referenceImagesDirectory]; 61 | } 62 | 63 | #pragma mark - Public API 64 | 65 | - (BOOL)compareSnapshotOfLayer:(CALayer *)layer 66 | selector:(SEL)selector 67 | identifier:(NSString *)identifier 68 | error:(NSError **)errorPtr 69 | { 70 | return [self compareSnapshotOfViewOrLayer:layer 71 | selector:selector 72 | identifier:identifier 73 | tolerance:0 74 | error:errorPtr]; 75 | } 76 | 77 | - (BOOL)compareSnapshotOfView:(UIView *)view 78 | selector:(SEL)selector 79 | identifier:(NSString *)identifier 80 | error:(NSError **)errorPtr 81 | { 82 | return [self compareSnapshotOfViewOrLayer:view 83 | selector:selector 84 | identifier:identifier 85 | tolerance:0 86 | error:errorPtr]; 87 | } 88 | 89 | - (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer 90 | selector:(SEL)selector 91 | identifier:(NSString *)identifier 92 | tolerance:(CGFloat)tolerance 93 | error:(NSError **)errorPtr 94 | { 95 | if (self.recordMode) { 96 | return [self _recordSnapshotOfViewOrLayer:viewOrLayer selector:selector identifier:identifier error:errorPtr]; 97 | } else { 98 | return [self _performPixelComparisonWithViewOrLayer:viewOrLayer selector:selector identifier:identifier tolerance:tolerance error:errorPtr]; 99 | } 100 | } 101 | 102 | - (UIImage *)referenceImageForSelector:(SEL)selector 103 | identifier:(NSString *)identifier 104 | error:(NSError **)errorPtr 105 | { 106 | NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier]; 107 | UIImage *image = [UIImage imageWithContentsOfFile:filePath]; 108 | if (nil == image && NULL != errorPtr) { 109 | BOOL exists = [_fileManager fileExistsAtPath:filePath]; 110 | if (!exists) { 111 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 112 | code:FBSnapshotTestControllerErrorCodeNeedsRecord 113 | userInfo:@{ 114 | FBReferenceImageFilePathKey: filePath, 115 | NSLocalizedDescriptionKey: @"Unable to load reference image.", 116 | NSLocalizedFailureReasonErrorKey: @"Reference image not found. You need to run the test in record mode", 117 | }]; 118 | } else { 119 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 120 | code:FBSnapshotTestControllerErrorCodeUnknown 121 | userInfo:nil]; 122 | } 123 | } 124 | return image; 125 | } 126 | 127 | - (BOOL)compareReferenceImage:(UIImage *)referenceImage 128 | toImage:(UIImage *)image 129 | tolerance:(CGFloat)tolerance 130 | error:(NSError **)errorPtr 131 | { 132 | BOOL sameImageDimensions = CGSizeEqualToSize(referenceImage.size, image.size); 133 | if (sameImageDimensions && [referenceImage fb_compareWithImage:image tolerance:tolerance]) { 134 | return YES; 135 | } 136 | 137 | if (NULL != errorPtr) { 138 | NSString *errorDescription = sameImageDimensions ? @"Images different" : @"Images different sizes"; 139 | NSString *errorReason = sameImageDimensions ? [NSString stringWithFormat:@"image pixels differed by more than %.2f%% from the reference image", tolerance * 100] 140 | : [NSString stringWithFormat:@"referenceImage:%@, image:%@", NSStringFromCGSize(referenceImage.size), NSStringFromCGSize(image.size)]; 141 | FBSnapshotTestControllerErrorCode errorCode = sameImageDimensions ? FBSnapshotTestControllerErrorCodeImagesDifferent : FBSnapshotTestControllerErrorCodeImagesDifferentSizes; 142 | 143 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 144 | code:errorCode 145 | userInfo:@{ 146 | NSLocalizedDescriptionKey: errorDescription, 147 | NSLocalizedFailureReasonErrorKey: errorReason, 148 | FBReferenceImageKey: referenceImage, 149 | FBCapturedImageKey: image, 150 | FBDiffedImageKey: [referenceImage fb_diffWithImage:image], 151 | }]; 152 | } 153 | return NO; 154 | } 155 | 156 | - (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage 157 | testImage:(UIImage *)testImage 158 | selector:(SEL)selector 159 | identifier:(NSString *)identifier 160 | error:(NSError **)errorPtr 161 | { 162 | NSData *referencePNGData = UIImagePNGRepresentation(referenceImage); 163 | NSData *testPNGData = UIImagePNGRepresentation(testImage); 164 | 165 | NSString *referencePath = [self _failedFilePathForSelector:selector 166 | identifier:identifier 167 | fileNameType:FBTestSnapshotFileNameTypeFailedReference]; 168 | 169 | NSError *creationError = nil; 170 | BOOL didCreateDir = [_fileManager createDirectoryAtPath:[referencePath stringByDeletingLastPathComponent] 171 | withIntermediateDirectories:YES 172 | attributes:nil 173 | error:&creationError]; 174 | if (!didCreateDir) { 175 | if (NULL != errorPtr) { 176 | *errorPtr = creationError; 177 | } 178 | return NO; 179 | } 180 | 181 | if (![referencePNGData writeToFile:referencePath options:NSDataWritingAtomic error:errorPtr]) { 182 | return NO; 183 | } 184 | 185 | NSString *testPath = [self _failedFilePathForSelector:selector 186 | identifier:identifier 187 | fileNameType:FBTestSnapshotFileNameTypeFailedTest]; 188 | 189 | if (![testPNGData writeToFile:testPath options:NSDataWritingAtomic error:errorPtr]) { 190 | return NO; 191 | } 192 | 193 | NSString *diffPath = [self _failedFilePathForSelector:selector 194 | identifier:identifier 195 | fileNameType:FBTestSnapshotFileNameTypeFailedTestDiff]; 196 | 197 | UIImage *diffImage = [referenceImage fb_diffWithImage:testImage]; 198 | NSData *diffImageData = UIImagePNGRepresentation(diffImage); 199 | 200 | if (![diffImageData writeToFile:diffPath options:NSDataWritingAtomic error:errorPtr]) { 201 | return NO; 202 | } 203 | 204 | NSLog(@"If you have Kaleidoscope installed you can run this command to see an image diff:\n" 205 | @"ksdiff \"%@\" \"%@\"", referencePath, testPath); 206 | 207 | return YES; 208 | } 209 | 210 | #pragma mark - Private API 211 | 212 | - (NSString *)_fileNameForSelector:(SEL)selector 213 | identifier:(NSString *)identifier 214 | fileNameType:(FBTestSnapshotFileNameType)fileNameType 215 | { 216 | NSString *fileName = nil; 217 | switch (fileNameType) { 218 | case FBTestSnapshotFileNameTypeFailedReference: 219 | fileName = @"reference_"; 220 | break; 221 | case FBTestSnapshotFileNameTypeFailedTest: 222 | fileName = @"failed_"; 223 | break; 224 | case FBTestSnapshotFileNameTypeFailedTestDiff: 225 | fileName = @"diff_"; 226 | break; 227 | default: 228 | fileName = @""; 229 | break; 230 | } 231 | fileName = [fileName stringByAppendingString:NSStringFromSelector(selector)]; 232 | if (0 < identifier.length) { 233 | fileName = [fileName stringByAppendingFormat:@"_%@", identifier]; 234 | } 235 | 236 | if (self.isDeviceAgnostic) { 237 | fileName = FBDeviceAgnosticNormalizedFileName(fileName); 238 | } 239 | 240 | if ([[UIScreen mainScreen] scale] > 1) { 241 | fileName = [fileName stringByAppendingFormat:@"@%.fx", [[UIScreen mainScreen] scale]]; 242 | } 243 | fileName = [fileName stringByAppendingPathExtension:@"png"]; 244 | return fileName; 245 | } 246 | 247 | - (NSString *)_referenceFilePathForSelector:(SEL)selector 248 | identifier:(NSString *)identifier 249 | { 250 | NSString *fileName = [self _fileNameForSelector:selector 251 | identifier:identifier 252 | fileNameType:FBTestSnapshotFileNameTypeReference]; 253 | NSString *filePath = [_referenceImagesDirectory stringByAppendingPathComponent:_testName]; 254 | filePath = [filePath stringByAppendingPathComponent:fileName]; 255 | return filePath; 256 | } 257 | 258 | - (NSString *)_failedFilePathForSelector:(SEL)selector 259 | identifier:(NSString *)identifier 260 | fileNameType:(FBTestSnapshotFileNameType)fileNameType 261 | { 262 | NSString *fileName = [self _fileNameForSelector:selector 263 | identifier:identifier 264 | fileNameType:fileNameType]; 265 | NSString *folderPath = NSTemporaryDirectory(); 266 | if (getenv("IMAGE_DIFF_DIR")) { 267 | folderPath = @(getenv("IMAGE_DIFF_DIR")); 268 | } 269 | NSString *filePath = [folderPath stringByAppendingPathComponent:_testName]; 270 | filePath = [filePath stringByAppendingPathComponent:fileName]; 271 | return filePath; 272 | } 273 | 274 | - (BOOL)_performPixelComparisonWithViewOrLayer:(id)viewOrLayer 275 | selector:(SEL)selector 276 | identifier:(NSString *)identifier 277 | tolerance:(CGFloat)tolerance 278 | error:(NSError **)errorPtr 279 | { 280 | UIImage *referenceImage = [self referenceImageForSelector:selector identifier:identifier error:errorPtr]; 281 | if (nil != referenceImage) { 282 | UIImage *snapshot = [self _imageForViewOrLayer:viewOrLayer]; 283 | BOOL imagesSame = [self compareReferenceImage:referenceImage toImage:snapshot tolerance:tolerance error:errorPtr]; 284 | if (!imagesSame) { 285 | NSError *saveError = nil; 286 | if ([self saveFailedReferenceImage:referenceImage testImage:snapshot selector:selector identifier:identifier error:&saveError] == NO) { 287 | NSLog(@"Error saving test images: %@", saveError); 288 | } 289 | } 290 | return imagesSame; 291 | } 292 | return NO; 293 | } 294 | 295 | - (BOOL)_recordSnapshotOfViewOrLayer:(id)viewOrLayer 296 | selector:(SEL)selector 297 | identifier:(NSString *)identifier 298 | error:(NSError **)errorPtr 299 | { 300 | UIImage *snapshot = [self _imageForViewOrLayer:viewOrLayer]; 301 | return [self _saveReferenceImage:snapshot selector:selector identifier:identifier error:errorPtr]; 302 | } 303 | 304 | - (BOOL)_saveReferenceImage:(UIImage *)image 305 | selector:(SEL)selector 306 | identifier:(NSString *)identifier 307 | error:(NSError **)errorPtr 308 | { 309 | BOOL didWrite = NO; 310 | if (nil != image) { 311 | NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier]; 312 | NSData *pngData = UIImagePNGRepresentation(image); 313 | if (nil != pngData) { 314 | NSError *creationError = nil; 315 | BOOL didCreateDir = [_fileManager createDirectoryAtPath:[filePath stringByDeletingLastPathComponent] 316 | withIntermediateDirectories:YES 317 | attributes:nil 318 | error:&creationError]; 319 | if (!didCreateDir) { 320 | if (NULL != errorPtr) { 321 | *errorPtr = creationError; 322 | } 323 | return NO; 324 | } 325 | didWrite = [pngData writeToFile:filePath options:NSDataWritingAtomic error:errorPtr]; 326 | if (didWrite) { 327 | NSLog(@"Reference image save at: %@", filePath); 328 | } 329 | } else { 330 | if (nil != errorPtr) { 331 | *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain 332 | code:FBSnapshotTestControllerErrorCodePNGCreationFailed 333 | userInfo:@{ 334 | FBReferenceImageFilePathKey: filePath, 335 | }]; 336 | } 337 | } 338 | } 339 | return didWrite; 340 | } 341 | 342 | - (UIImage *)_imageForViewOrLayer:(id)viewOrLayer 343 | { 344 | if ([viewOrLayer isKindOfClass:[UIView class]]) { 345 | if (_usesDrawViewHierarchyInRect) { 346 | return [UIImage fb_imageForView:viewOrLayer]; 347 | } else { 348 | return [UIImage fb_imageForViewLayer:viewOrLayer]; 349 | } 350 | } else if ([viewOrLayer isKindOfClass:[CALayer class]]) { 351 | return [UIImage fb_imageForLayer:viewOrLayer]; 352 | } else { 353 | [NSException raise:@"Only UIView and CALayer classes can be snapshotted" format:@"%@", viewOrLayer]; 354 | } 355 | return nil; 356 | } 357 | 358 | @end 359 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | * 9 | */ 10 | 11 | public extension FBSnapshotTestCase { 12 | public func FBSnapshotVerifyView(view: UIView, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 13 | FBSnapshotVerifyViewOrLayer(view, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) 14 | } 15 | 16 | public func FBSnapshotVerifyLayer(layer: CALayer, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 17 | FBSnapshotVerifyViewOrLayer(layer, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) 18 | } 19 | 20 | private func FBSnapshotVerifyViewOrLayer(viewOrLayer: AnyObject, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { 21 | let envReferenceImageDirectory = self.getReferenceImageDirectoryWithDefault(FB_REFERENCE_IMAGE_DIR) 22 | var error: NSError? 23 | var comparisonSuccess = false 24 | 25 | if let envReferenceImageDirectory = envReferenceImageDirectory { 26 | for suffix in suffixes { 27 | let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)" 28 | if viewOrLayer.isKindOfClass(UIView) { 29 | do { 30 | try compareSnapshotOfView(viewOrLayer as! UIView, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) 31 | comparisonSuccess = true 32 | } catch let error1 as NSError { 33 | error = error1 34 | comparisonSuccess = false 35 | } 36 | } else if viewOrLayer.isKindOfClass(CALayer) { 37 | do { 38 | try compareSnapshotOfLayer(viewOrLayer as! CALayer, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) 39 | comparisonSuccess = true 40 | } catch let error1 as NSError { 41 | error = error1 42 | comparisonSuccess = false 43 | } 44 | } else { 45 | assertionFailure("Only UIView and CALayer classes can be snapshotted") 46 | } 47 | 48 | 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) 49 | 50 | if comparisonSuccess || recordMode { 51 | break 52 | } 53 | 54 | assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line) 55 | } 56 | } else { 57 | XCTFail("Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.") 58 | } 59 | } 60 | 61 | func assert(assertion: Bool, message: String, file: StaticString, line: UInt) { 62 | if !assertion { 63 | XCTFail(message, file: file, line: line) 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For the FBSnapshotTestCase software 4 | 5 | Copyright (c) 2013, Facebook, Inc. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | * Neither the name Facebook nor the names of its contributors may be used to 17 | endorse or promote products derived from this software without specific 18 | prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Example/Pods/FBSnapshotTestCase/README.md: -------------------------------------------------------------------------------- 1 | FBSnapshotTestCase 2 | ====================== 3 | 4 | [![Build Status](https://travis-ci.org/facebook/ios-snapshot-test-case.svg)](https://travis-ci.org/facebook/ios-snapshot-test-case) [![Cocoa Pod Version](https://cocoapod-badges.herokuapp.com/v/FBSnapshotTestCase/badge.svg)](http://cocoadocs.org/docsets/FBSnapshotTestCase/) 5 | 6 | What it does 7 | ------------ 8 | 9 | A "snapshot test case" takes a configured `UIView` or `CALayer` and uses the 10 | `renderInContext:` method to get an image snapshot of its contents. It 11 | compares this snapshot to a "reference image" stored in your source code 12 | repository and fails the test if the two images don't match. 13 | 14 | Why? 15 | ---- 16 | 17 | At Facebook we write a lot of UI code. As you might imagine, each type of 18 | feed story is rendered using a subclass of `UIView`. There are a lot of edge 19 | cases that we want to handle correctly: 20 | 21 | - What if there is more text than can fit in the space available? 22 | - What if an image doesn't match the size of an image view? 23 | - What should the highlighted state look like? 24 | 25 | It's straightforward to test logic code, but less obvious how you should test 26 | views. You can do a lot of rectangle asserts, but these are hard to understand 27 | or visualize. Looking at an image diff shows you exactly what changed and how 28 | it will look to users. 29 | 30 | We developed `FBSnapshotTestCase` to make snapshot tests easy. 31 | 32 | Installation with CocoaPods 33 | --------------------------- 34 | 35 | 1. Add the following lines to your Podfile: 36 | 37 | ``` 38 | target "Tests" do 39 | pod 'FBSnapshotTestCase' 40 | end 41 | ``` 42 | 43 | If you support iOS 7 use `FBSnapshotTestCase/Core` instead, which doesn't contain Swift support. 44 | 45 | Replace "Tests" with the name of your test project. 46 | 47 | 2. There are [three ways](https://github.com/facebook/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/FBSnapshotTestCase.h#L19-L29) of setting reference image directories, the recommended one is to define `FB_REFERENCE_IMAGE_DIR` in your scheme. This should point to the directory where you want reference images to be stored. At Facebook, we normally use this: 48 | 49 | |Name|Value| 50 | |:---|:----| 51 | |`FB_REFERENCE_IMAGE_DIR`|`$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages`| 52 | 53 | 54 | ![](FBSnapshotTestCaseDemo/Scheme_FB_REFERENCE_IMAGE_DIR.png) 55 | 56 | Creating a snapshot test 57 | ------------------------ 58 | 59 | 1. Subclass `FBSnapshotTestCase` instead of `XCTestCase`. 60 | 2. From within your test, use `FBSnapshotVerifyView`. 61 | 3. Run the test once with `self.recordMode = YES;` in the test's `-setUp` 62 | method. (This creates the reference images on disk.) 63 | 4. Remove the line enabling record mode and run the test. 64 | 65 | Features 66 | -------- 67 | 68 | - Automatically names reference images on disk according to test class and 69 | selector. 70 | - Prints a descriptive error message to the console on failure. (Bonus: 71 | failure message includes a one-line command to see an image diff if 72 | you have [Kaleidoscope](http://www.kaleidoscopeapp.com) installed.) 73 | - Supply an optional "identifier" if you want to perform multiple snapshots 74 | in a single test method. 75 | - Support for `CALayer` via `FBSnapshotVerifyLayer`. 76 | - `usesDrawViewHierarchyInRect` to handle cases like `UIVisualEffect`, `UIAppearance` and Size Classes. 77 | - `isDeviceAgnostic` to allow appending the device model (`iPhone`, `iPad`, `iPod Touch`, etc), OS version and screen size to the images (allowing to have multiple tests for the same «snapshot» for different `OS`s and devices). 78 | 79 | Notes 80 | ----- 81 | 82 | Your unit test must be an "application test", not a "logic test." (That is, it 83 | must be run within the Simulator so that it has access to UIKit.) In Xcode 5 84 | and later new projects only offer application tests, but older projects will 85 | have separate targets for the two types. 86 | 87 | Authors 88 | ------- 89 | 90 | `FBSnapshotTestCase` was written at Facebook by 91 | [Jonathan Dann](https://facebook.com/j.p.dann) with significant contributions by 92 | [Todd Krabach](https://facebook.com/toddkrabach). 93 | 94 | License 95 | ------- 96 | 97 | `FBSnapshotTestCase` is BSD-licensed. See `LICENSE`. 98 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/CYWebviewController.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CYWebviewController", 3 | "version": "1.1.0", 4 | "summary": "CYWebviewController is a webview view controller.", 5 | "description": "\"CYWebviewController,a UIWebview controller, contains goBack, goForward, refresh and share functions. Also has Wechat mode.\"", 6 | "homepage": "https://github.com/wheying/CYWebViewController", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "万鸿恩": "1396855545@qq.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/wheying/CYWebViewController.git", 16 | "tag": "1.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "8.0" 20 | }, 21 | "source_files": "CYWebviewController/Classes/**/*", 22 | "resource_bundles": { 23 | "CYWebviewController": [ 24 | "CYWebviewController/Assets/*.png" 25 | ] 26 | }, 27 | "public_header_files": "Pod/Classes/**/*.h", 28 | "frameworks": "UIKit" 29 | } 30 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - CYWebviewController (1.1.0) 3 | - FBSnapshotTestCase (2.1.0): 4 | - FBSnapshotTestCase/SwiftSupport (= 2.1.0) 5 | - FBSnapshotTestCase/Core (2.1.0) 6 | - FBSnapshotTestCase/SwiftSupport (2.1.0): 7 | - FBSnapshotTestCase/Core 8 | 9 | DEPENDENCIES: 10 | - CYWebviewController (from `../`) 11 | - FBSnapshotTestCase 12 | 13 | EXTERNAL SOURCES: 14 | CYWebviewController: 15 | :path: ../ 16 | 17 | SPEC CHECKSUMS: 18 | CYWebviewController: 1ea34254b33d6a7262901eec50eafba9ac3ec745 19 | FBSnapshotTestCase: 366ecd378511d7716c79991cd8067d1eed23578d 20 | 21 | PODFILE CHECKSUM: 6bcf6250c2b2a3daf81480fb88976903b92806fa 22 | 23 | COCOAPODS: 1.0.1 24 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/CYWebviewController-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_CYWebviewController : NSObject 3 | @end 4 | @implementation PodsDummy_CYWebviewController 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/CYWebviewController-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/CYWebviewController-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "UIButton+WHE.h" 4 | #import "UIColor+WHE.h" 5 | #import "UIImage+CYButtonIcon.h" 6 | #import "CYWebViewController.h" 7 | #import "NJKWebViewProgress.h" 8 | #import "NJKWebViewProgressView.h" 9 | #import "UINavigationBar+Awesome.h" 10 | 11 | FOUNDATION_EXPORT double CYWebviewControllerVersionNumber; 12 | FOUNDATION_EXPORT const unsigned char CYWebviewControllerVersionString[]; 13 | 14 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/CYWebviewController.modulemap: -------------------------------------------------------------------------------- 1 | framework module CYWebviewController { 2 | umbrella header "CYWebviewController-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/CYWebviewController.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/CYWebviewController 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_LDFLAGS = -framework "UIKit" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/CYWebviewController/ResourceBundle-CYWebviewController-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_FBSnapshotTestCase : NSObject 3 | @end 4 | @implementation PodsDummy_FBSnapshotTestCase 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap: -------------------------------------------------------------------------------- 1 | framework module FBSnapshotTestCase { 2 | umbrella header "FBSnapshotTestCase.h" 3 | 4 | export * 5 | module * { export * } 6 | 7 | header "FBSnapshotTestCase.h" 8 | header "FBSnapshotTestCasePlatform.h" 9 | header "FBSnapshotTestController.h" 10 | 11 | private header "UIImage+Compare.h" 12 | private header "UIImage+Diff.h" 13 | private header "UIImage+Snapshot.h" 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/FBSnapshotTestCase 2 | ENABLE_BITCODE = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 6 | OTHER_LDFLAGS = -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT} 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FBSnapshotTestCase/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## CYWebviewController 5 | 6 | Copyright (c) 2016 万鸿恩 <1396855545@qq.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 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2016 万鸿恩 <1396855545@qq.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 | 37 | Title 38 | CYWebviewController 39 | Type 40 | PSGroupSpecifier 41 | 42 | 43 | FooterText 44 | Generated by CocoaPods - https://cocoapods.org 45 | Title 46 | 47 | Type 48 | PSGroupSpecifier 49 | 50 | 51 | StringsTable 52 | Acknowledgements 53 | Title 54 | Acknowledgements 55 | 56 | 57 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_CYWebviewController_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_CYWebviewController_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/CYWebviewController/CYWebviewController.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/CYWebviewController/CYWebviewController.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_CYWebviewController_ExampleVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_CYWebviewController_ExampleVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController/CYWebviewController.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "CYWebviewController" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_CYWebviewController_Example { 2 | umbrella header "Pods-CYWebviewController_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Example/Pods-CYWebviewController_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController/CYWebviewController.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "CYWebviewController" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## FBSnapshotTestCase 5 | 6 | BSD License 7 | 8 | For the FBSnapshotTestCase software 9 | 10 | Copyright (c) 2013, Facebook, Inc. 11 | All rights reserved. 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | * Redistributions of source code must retain the above copyright notice, 17 | this list of conditions and the following disclaimer. 18 | * Redistributions in binary form must reproduce the above copyright notice, 19 | this list of conditions and the following disclaimer in the documentation 20 | and/or other materials provided with the distribution. 21 | * Neither the name Facebook nor the names of its contributors may be used to 22 | endorse or promote products derived from this software without specific 23 | prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | Generated by CocoaPods - https://cocoapods.org 37 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | BSD License 18 | 19 | For the FBSnapshotTestCase software 20 | 21 | Copyright (c) 2013, Facebook, Inc. 22 | All rights reserved. 23 | 24 | Redistribution and use in source and binary forms, with or without 25 | modification, are permitted provided that the following conditions are met: 26 | 27 | * Redistributions of source code must retain the above copyright notice, 28 | this list of conditions and the following disclaimer. 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimer in the documentation 31 | and/or other materials provided with the distribution. 32 | * Neither the name Facebook nor the names of its contributors may be used to 33 | endorse or promote products derived from this software without specific 34 | prior written permission. 35 | 36 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 37 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 40 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 42 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 43 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | 47 | Title 48 | FBSnapshotTestCase 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | FooterText 54 | Generated by CocoaPods - https://cocoapods.org 55 | Title 56 | 57 | Type 58 | PSGroupSpecifier 59 | 60 | 61 | StringsTable 62 | Acknowledgements 63 | Title 64 | Acknowledgements 65 | 66 | 67 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_CYWebviewController_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_CYWebviewController_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/FBSnapshotTestCase/FBSnapshotTestCase.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/FBSnapshotTestCase/FBSnapshotTestCase.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_CYWebviewController_TestsVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_CYWebviewController_TestsVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FBSnapshotTestCase" "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController/CYWebviewController.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "FBSnapshotTestCase" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_CYWebviewController_Tests { 2 | umbrella header "Pods-CYWebviewController_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-CYWebviewController_Tests/Pods-CYWebviewController_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/FBSnapshotTestCase" "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/CYWebviewController/CYWebviewController.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "FBSnapshotTestCase" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | @import FBSnapshotTestCase; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CYWebviewControllerTests.m 3 | // CYWebviewControllerTests 4 | // 5 | // Created by 万鸿恩 on 07/12/2016. 6 | // Copyright (c) 2016 万鸿恩. All rights reserved. 7 | // 8 | 9 | @import XCTest; 10 | 11 | @interface Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Tests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 万鸿恩 <1396855545@qq.com> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CYWebViewController 2 | Contain two mode:wechat browser and Safari browser. A web view controller class for iOS that allows users to view web pages directly within an app similar as wechat.Using Safari mode, contains goBack,goForward,shareAction,refresh and stop function at toolbar
3 | 4 | 分为两种模式,一种是类似微信内置浏览器模式,一种是Safari浏览器模式。类似微信内置浏览器,顶部导航栏提供webview后退和关闭按钮.Safari模式,底部toolbar带有前进,后退,分享,刷新的功能。 5 | 6 | 效果: 7 | === 8 | ![image](https://github.com/wheying/CYWebViewController/blob/master/Screenshot/1.PNG) ![image](https://github.com/wheying/CYWebViewController/blob/master/Screenshot/2.PNG) ![image](https://github.com/wheying/CYWebViewController/blob/master/Screenshot/3.PNG) 9 | ![image](https://github.com/wheying/CYWebViewController/blob/master/Screenshot/4.PNG) 10 | ![image](https://github.com/wheying/CYWebViewController/blob/master/Screenshot/5.PNG) 11 | ![image](https://github.com/wheying/CYWebViewController/blob/master/Screenshot/6.PNG) 12 | 13 | 使用安装Install: 14 | === 15 | Cocoapods 16 | ``` 17 | pod 'CYWebviewController' 18 | ``` 19 | 20 | Manual
21 | 把项目中的CY文件夹拉近自己的项目就可以了
22 | Pull "CY" file to your project 23 |
24 | ``` 25 | #import "CYWebViewController.h" 26 | ``` 27 |
#import "UINavigationBar+Awesome.h"可以设置UINavigationBar 28 | ``` 29 | #import "UIButton+WHE.h" 30 | ``` 31 |
#import "UIButton+WHE.h"自定义返回按钮 32 | ``` 33 | #import "UIButton+WHE.h" 34 | ``` 35 |
#import "UIColor+WHE.h"HEX颜色转为RGB颜色 36 | ``` 37 | #import "UIColor+WHE.h" 38 | ``` 39 | 40 | 例子Example: 41 | ===== 42 |
import 43 | ``` 44 | #import "CYWebViewController.h" 45 | ``` 46 |
使用微信内置浏览器模式
47 | Using Wechat mode 48 | ``` 49 | CYWebViewController *controller = [[CYWebViewController alloc] init]; 50 | controller.url = @"https://www.baidu.com/"; 51 | controller.loadingBarTintColor = [UIColor redColor]; 52 | [self.navigationController pushViewController:controller animated:YES]; 53 | ``` 54 |
使用Safari 模式,底部toolbar带有前进,后退,分享,刷新的功能。
55 | Using Safari mode, contains goBack,goForward,shareAction,refresh and stop function at toolbar. Push ViewController 56 | ``` 57 | CYWebViewController *controller = [[CYWebViewController alloc] init]; 58 | controller.url = [NSURL URLWithString:@"https://www.baidu.com/"]; 59 | controller.loadingBarTintColor = [UIColor redColor]; 60 | controller.navigationButtonsHidden = NO; 61 | [self.navigationController pushViewController:controller animated:YES]; 62 | ``` 63 |
presentViewController 64 | ``` 65 | CYWebViewController *controller = [[CYWebViewController alloc] init]; 66 | controller.url = [NSURL URLWithString:@"https://www.baidu.com/"]; 67 | controller.loadingBarTintColor = [UIColor redColor]; 68 | controller.navigationButtonsHidden = NO; 69 | [self presentViewController:[[UINavigationController alloc] initWithRootViewController:controller] animated:YES completion:nil]; 70 | ``` 71 | -------------------------------------------------------------------------------- /Screenshot/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/Screenshot/1.PNG -------------------------------------------------------------------------------- /Screenshot/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/Screenshot/2.PNG -------------------------------------------------------------------------------- /Screenshot/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/Screenshot/3.PNG -------------------------------------------------------------------------------- /Screenshot/4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/Screenshot/4.PNG -------------------------------------------------------------------------------- /Screenshot/5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/Screenshot/5.PNG -------------------------------------------------------------------------------- /Screenshot/6.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericwan2019/CYWebViewController/c51a84dc7f158ef653f1c22ad251f415ea6fb448/Screenshot/6.PNG -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------