├── Demo ├── Default-568h@2x.png └── PhotoBrowserDemo │ ├── Photos │ ├── photo1l.jpg │ ├── photo1m.jpg │ ├── photo2l.jpg │ ├── photo2m.jpg │ ├── photo3l.jpg │ ├── photo3m.jpg │ ├── photo4l.jpg │ └── photo4m.jpg │ ├── CustomImages │ ├── IDMPhotoBrowser_customArrowLeft.png │ ├── IDMPhotoBrowser_customArrowLeft@2x.png │ ├── IDMPhotoBrowser_customArrowRight.png │ ├── IDMPhotoBrowser_customDoneButton.png │ ├── IDMPhotoBrowser_customArrowRight@2x.png │ ├── IDMPhotoBrowser_customDoneButton@2x.png │ ├── IDMPhotoBrowser_customArrowLeftSelected.png │ ├── IDMPhotoBrowser_customArrowRightSelected.png │ ├── IDMPhotoBrowser_customArrowLeftSelected@2x.png │ └── IDMPhotoBrowser_customArrowRightSelected@2x.png │ ├── Menu.h │ ├── main.m │ ├── AppDelegate.h │ ├── PhotoBrowserDemo-Prefix.pch │ ├── AppDelegate.m │ └── PhotoBrowserDemo-Info.plist ├── Screenshots ├── idmphotobrowser_ss1.png ├── idmphotobrowser_ss2.png ├── idmphotobrowser_ss3.png ├── idmphotobrowser_ss4.png ├── idmphotobrowser_ss5.png ├── idmphotobrowser_thumb1.png ├── idmphotobrowser_thumb2.png ├── idmphotobrowser_thumb3.png ├── idmphotobrowser_thumb4.png └── idmphotobrowser_thumb5.png ├── Classes ├── IDMPhotoBrowser.bundle │ ├── images │ │ ├── IDMPhotoBrowser_arrowLeft.png │ │ ├── IDMPhotoBrowser_arrowRight.png │ │ ├── IDMPhotoBrowser_arrowLeft@2x.png │ │ └── IDMPhotoBrowser_arrowRight@2x.png │ └── Localizations │ │ ├── en.lproj │ │ └── Localizable.strings │ │ └── pt.lproj │ │ └── Localizable.strings ├── ExternalLibraries │ ├── SVProgressHUD │ │ ├── SVProgressHUD.bundle │ │ │ ├── error.png │ │ │ ├── error@2x.png │ │ │ ├── success.png │ │ │ ├── success@2x.png │ │ │ ├── error-black.png │ │ │ ├── success-black.png │ │ │ ├── error-black@2x.png │ │ │ └── success-black@2x.png │ │ └── SVProgressHUD.h │ ├── DCIntrospect │ │ ├── DCCrossHairView.h │ │ ├── DCStatusBarOverlay.h │ │ ├── DCCrossHairView.m │ │ ├── DCFrameView.h │ │ ├── DCIntrospectSettings.h │ │ ├── DCStatusBarOverlay.m │ │ ├── DCIntrospect.h │ │ └── DCFrameView.m │ ├── DACircularProgress │ │ ├── DACircularProgressView.h │ │ └── DACircularProgressView.m │ └── AFNetworking │ │ ├── UIKit+AFNetworking │ │ ├── UIKit+AFNetworking.h │ │ ├── UIActivityIndicatorView+AFNetworking.h │ │ ├── AFNetworkActivityIndicatorManager.h │ │ ├── UIProgressView+AFNetworking.h │ │ ├── UIActivityIndicatorView+AFNetworking.m │ │ ├── UIAlertView+AFNetworking.h │ │ ├── UIWebView+AFNetworking.h │ │ ├── UIAlertView+AFNetworking.m │ │ ├── UIImageView+AFNetworking.h │ │ ├── UIWebView+AFNetworking.m │ │ ├── AFNetworkActivityIndicatorManager.m │ │ ├── UIImageView+AFNetworking.m │ │ ├── UIButton+AFNetworking.m │ │ ├── UIButton+AFNetworking.h │ │ └── UIProgressView+AFNetworking.m │ │ └── AFNetworking │ │ ├── AFNetworking.h │ │ ├── AFSecurityPolicy.h │ │ ├── AFHTTPRequestOperation.h │ │ ├── AFHTTPRequestOperation.m │ │ ├── AFNetworkReachabilityManager.h │ │ ├── AFNetworkReachabilityManager.m │ │ └── AFSecurityPolicy.m ├── IDMTapDetectingView.h ├── IDMTapDetectingImageView.h ├── IDMCaptionView.h ├── IDMPBConstants.h ├── IDMPhoto.h ├── IDMZoomingScrollView.h ├── IDMTapDetectingView.m ├── IDMTapDetectingImageView.m ├── IDMPhotoProtocol.h ├── IDMPhotoBrowser.h └── IDMCaptionView.m ├── .gitignore ├── IDMPhotoBrowser.podspec ├── LICENSE.txt └── README.markdown /Demo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/Default-568h@2x.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_ss1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss1.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_ss2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss2.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_ss3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss3.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_ss4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss4.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_ss5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss5.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_thumb1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb1.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_thumb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb2.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_thumb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb3.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_thumb4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb4.png -------------------------------------------------------------------------------- /Screenshots/idmphotobrowser_thumb5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb5.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo1l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo1l.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo1m.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo1m.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo2l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo2l.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo2m.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo2m.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo3l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo3l.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo3m.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo3m.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo4l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo4l.jpg -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Photos/photo4m.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/Photos/photo4m.jpg -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowLeft.png -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowRight.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error.png -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowLeft@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowLeft@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeft.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success.png -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.bundle/Localizations/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/IDMPhotoBrowser.bundle/Localizations/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/IDMPhotoBrowser.bundle/images/IDMPhotoBrowser_arrowRight@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeft@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeft@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRight.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customDoneButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customDoneButton.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRight@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customDoneButton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customDoneButton@2x.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error-black.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success-black.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeftSelected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeftSelected.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error-black@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/error-black@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRightSelected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRightSelected.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success-black@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.bundle/success-black@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeftSelected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowLeftSelected@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRightSelected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polydice/IDMPhotoBrowser/master/Demo/PhotoBrowserDemo/CustomImages/IDMPhotoBrowser_customArrowRightSelected@2x.png -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/Menu.h: -------------------------------------------------------------------------------- 1 | // 2 | // Menu.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 21/10/2010. 6 | // Copyright 2010 d3i. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "IDMPhotoBrowser.h" 11 | 12 | @interface Menu : UITableViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCCrossHairView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DCCrossHairView.h 3 | // 4 | // Created by Domestic Cat on 3/05/11. 5 | // 6 | 7 | 8 | @interface DCCrossHairView : UIView 9 | { 10 | } 11 | 12 | @property (nonatomic, retain) UIColor *color; 13 | 14 | - (id)initWithFrame:(CGRect)frame color:(UIColor *)aColor; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PhotoBrowserDemo 4 | // 5 | // Created by Michael Waterfall on 31/12/2011. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PhotoBrowserDemo 4 | // 5 | // Created by Michael Waterfall on 31/12/2011. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | @property (strong, nonatomic) UIViewController *viewController; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/PhotoBrowserDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PhotoBrowserDemo' target in the 'PhotoBrowserDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/ 3 | *~.nib/ 4 | *.moved-aside 5 | profile 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspective 13 | !default.perspective 14 | *.perspectivev3 15 | !default.perspectivev3 16 | *.xcworkspace 17 | !default.xcworkspace 18 | xcuserdata 19 | *.xcodeproj/project.xcworkspace/ 20 | *.xcodeproj/xcuserdata/ 21 | 22 | # OS X noise 23 | .DS_Store 24 | Icon 25 | .Spotlight-V100 26 | .Trashes 27 | 28 | # Misc 29 | *~ 30 | *.bak 31 | *.o 32 | *.pyc 33 | *.pyo 34 | 35 | # Tower 36 | /Icon.png -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCStatusBarOverlay.h: -------------------------------------------------------------------------------- 1 | // 2 | // DCStatusBarOverlay.h 3 | // 4 | // Copyright 2011 Domestic Cat. All rights reserved. 5 | // 6 | 7 | // Based mainly on @myellow's excellent MTStatusBarOverlay: https://github.com/myell0w/MTStatusBarOverlay 8 | 9 | 10 | #import "DCIntrospectSettings.h" 11 | 12 | #define kDCIntrospectNotificationStatusBarTapped @"kDCIntrospectNotificationStatusBarTapped" 13 | 14 | @interface DCStatusBarOverlay : UIWindow 15 | { 16 | } 17 | 18 | @property (nonatomic, retain) UILabel *leftLabel; 19 | @property (nonatomic, retain) UILabel *rightLabel; 20 | 21 | /////////// 22 | // Setup // 23 | /////////// 24 | 25 | - (id)init; 26 | - (void)updateBarFrame; 27 | 28 | ///////////// 29 | // Actions // 30 | ///////////// 31 | 32 | - (void)tapped; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/IDMTapDetectingView.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMTapDetectingView.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 04/11/2009. 6 | // Copyright 2009 d3i. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol IDMTapDetectingViewDelegate; 12 | 13 | @interface IDMTapDetectingView : UIView { 14 | id __weak tapDelegate; 15 | } 16 | @property (nonatomic, weak) id tapDelegate; 17 | - (void)handleSingleTap:(UITouch *)touch; 18 | - (void)handleDoubleTap:(UITouch *)touch; 19 | - (void)handleTripleTap:(UITouch *)touch; 20 | @end 21 | 22 | @protocol IDMTapDetectingViewDelegate 23 | @optional 24 | - (void)view:(UIView *)view singleTapDetected:(UITouch *)touch; 25 | - (void)view:(UIView *)view doubleTapDetected:(UITouch *)touch; 26 | - (void)view:(UIView *)view tripleTapDetected:(UITouch *)touch; 27 | @end -------------------------------------------------------------------------------- /Classes/IDMTapDetectingImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMTapDetectingImageView.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 04/11/2009. 6 | // Copyright 2009 d3i. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol IDMTapDetectingImageViewDelegate; 12 | 13 | @interface IDMTapDetectingImageView : UIImageView { 14 | id __weak tapDelegate; 15 | } 16 | @property (nonatomic, weak) id tapDelegate; 17 | - (void)handleSingleTap:(UITouch *)touch; 18 | - (void)handleDoubleTap:(UITouch *)touch; 19 | - (void)handleTripleTap:(UITouch *)touch; 20 | @end 21 | 22 | @protocol IDMTapDetectingImageViewDelegate 23 | @optional 24 | - (void)imageView:(UIImageView *)imageView singleTapDetected:(UITouch *)touch; 25 | - (void)imageView:(UIImageView *)imageView doubleTapDetected:(UITouch *)touch; 26 | - (void)imageView:(UIImageView *)imageView tripleTapDetected:(UITouch *)touch; 27 | @end -------------------------------------------------------------------------------- /IDMPhotoBrowser.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "IDMPhotoBrowser" 3 | s.summary = "Photo Browser / Viewer inspired by Facebook's and Tweetbot's with ARC support, swipe-to-dismiss, image progress and more." 4 | s.version = "1.3.2" 5 | s.homepage = "https://github.com/ideaismobile/IDMPhotoBrowser" 6 | s.license = { :type => 'MIT', :file => 'LICENSE.txt' } 7 | s.author = { "Ideais Mobile" => "mobile@ideais.com.br" } 8 | s.source = { :git => "https://github.com/ideaismobile/IDMPhotoBrowser.git", :tag => "1.3.2" } 9 | s.platform = :ios, '7.0' 10 | s.source_files = 'Classes/*.{h,m}' 11 | s.resources = 'Classes/IDMPhotoBrowser.bundle' 12 | s.framework = 'MessageUI', 'QuartzCore', 'SystemConfiguration', 'MobileCoreServices', 'Security' 13 | s.requires_arc = true 14 | s.dependency 'AFNetworking', '~> 2.0.2' 15 | s.dependency 'DACircularProgress', '~> 2.1.0' 16 | s.dependency 'SVProgressHUD', '~> 1.0' 17 | end 18 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DACircularProgress/DACircularProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DACircularProgressView.h 3 | // DACircularProgress 4 | // 5 | // Created by Daniel Amitay on 2/6/12. 6 | // Copyright (c) 2012 Daniel Amitay. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DACircularProgressView : UIView 12 | 13 | @property(nonatomic, strong) UIColor *trackTintColor UI_APPEARANCE_SELECTOR; 14 | @property(nonatomic, strong) UIColor *progressTintColor UI_APPEARANCE_SELECTOR; 15 | @property(nonatomic) NSInteger roundedCorners UI_APPEARANCE_SELECTOR; // Can not use BOOL with UI_APPEARANCE_SELECTOR :-( 16 | @property(nonatomic) CGFloat thicknessRatio UI_APPEARANCE_SELECTOR; 17 | @property(nonatomic) CGFloat progress; 18 | 19 | @property(nonatomic) CGFloat indeterminateDuration UI_APPEARANCE_SELECTOR; 20 | @property(nonatomic) NSInteger indeterminate UI_APPEARANCE_SELECTOR; // Can not use BOOL with UI_APPEARANCE_SELECTOR :-( 21 | 22 | - (void)setProgress:(CGFloat)progress animated:(BOOL)animated; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PhotoBrowserDemo 4 | // 5 | // Created by Michael Waterfall on 31/12/2011. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "Menu.h" 11 | #import "DCIntrospect.h" 12 | 13 | @implementation AppDelegate 14 | 15 | @synthesize window = _window; 16 | @synthesize viewController = _viewController; 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 21 | 22 | Menu *menu = [[Menu alloc] initWithStyle:UITableViewStyleGrouped]; 23 | self.viewController = (UIViewController *)[[UINavigationController alloc] initWithRootViewController:menu]; 24 | 25 | self.window.rootViewController = self.viewController; 26 | [self.window makeKeyAndVisible]; 27 | 28 | #if TARGET_IPHONE_SIMULATOR 29 | [[DCIntrospect sharedIntrospector] start]; 30 | #endif 31 | 32 | return YES; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Appkraft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Classes/IDMCaptionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMCaptionView.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 30/12/2011. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "IDMPhotoProtocol.h" 11 | 12 | @interface IDMCaptionView : UIView 13 | 14 | // Init 15 | - (id)initWithPhoto:(id)photo; 16 | 17 | // To create your own custom caption view, subclass this view 18 | // and override the following two methods (as well as any other 19 | // UIView methods that you see fit): 20 | 21 | // Override -setupCaption so setup your subviews and customise the appearance 22 | // of your custom caption 23 | // You can access the photo's data by accessing the _photo ivar 24 | // If you need more data per photo then simply subclass IDMPhoto and return your 25 | // subclass to the photo browsers -photoBrowser:photoAtIndex: delegate method 26 | - (void)setupCaption; 27 | 28 | // Override -sizeThatFits: and return a CGSize specifying the height of your 29 | // custom caption view. With width property is ignored and the caption is displayed 30 | // the full width of the screen 31 | - (CGSize)sizeThatFits:(CGSize)size; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCCrossHairView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DCCrossHairView.m 3 | // 4 | // Created by Domestic Cat on 3/05/11. 5 | // 6 | 7 | #import "DCCrossHairView.h" 8 | 9 | @implementation DCCrossHairView 10 | @synthesize color; 11 | 12 | - (void)dealloc 13 | { 14 | [color release]; 15 | [super dealloc]; 16 | } 17 | 18 | - (id)initWithFrame:(CGRect)frame color:(UIColor *)aColor 19 | { 20 | if ((self = [super initWithFrame:frame])) 21 | { 22 | self.color = aColor; 23 | self.backgroundColor = [UIColor clearColor]; 24 | self.opaque = NO; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (void)drawRect:(CGRect)rect 31 | { 32 | CGContextRef context = UIGraphicsGetCurrentContext(); 33 | [self.color set]; 34 | CGContextMoveToPoint(context, floorf(self.bounds.size.width / 2.0f) + 0.5f, 0.0f); 35 | CGContextAddLineToPoint(context, floorf(self.bounds.size.width / 2.0f) + 0.5f, self.bounds.size.height); 36 | CGContextStrokePath(context); 37 | 38 | CGContextMoveToPoint(context, 0, floorf(self.bounds.size.height / 2.0f) + 0.5f); 39 | CGContextAddLineToPoint(context, self.bounds.size.width, floorf(self.bounds.size.height / 2.0f) + 0.5f); 40 | CGContextStrokePath(context); 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Classes/IDMPBConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMPhotoBrowserConstants.h 3 | // PhotoBrowserDemo 4 | // 5 | // Created by Eduardo Callado on 10/7/13. 6 | // 7 | // 8 | 9 | #define SYSTEM_VERSION_EQUAL_TO(v) \ 10 | ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) 11 | 12 | #define SYSTEM_VERSION_GREATER_THAN(v) \ 13 | ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) 14 | 15 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) \ 16 | ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 17 | 18 | #define SYSTEM_VERSION_LESS_THAN(v) \ 19 | ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 20 | 21 | #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) \ 22 | ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) 23 | 24 | #define PADDING 10 25 | #define PAGE_INDEX_TAG_OFFSET 1000 26 | #define PAGE_INDEX(page) ([(page) tag] - PAGE_INDEX_TAG_OFFSET) 27 | 28 | // Debug Logging 29 | #if 0 // Set to 1 to enable debug logging 30 | #define IDMLog(x, ...) NSLog(x, ## __VA_ARGS__); 31 | #else 32 | #define IDMLog(x, ...) 33 | #endif 34 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCFrameView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DCFrameView.h 3 | // 4 | // Created by Domestic Cat on 29/04/11. 5 | // 6 | 7 | #import 8 | #import "DCCrossHairView.h" 9 | 10 | @protocol DCFrameViewDelegate 11 | 12 | @required 13 | 14 | - (void)touchAtPoint:(CGPoint)point; 15 | 16 | @end 17 | 18 | @interface DCFrameView : UIView 19 | { 20 | 21 | } 22 | 23 | @property (nonatomic, assign) id delegate; 24 | @property (nonatomic) CGRect mainRect; 25 | @property (nonatomic) CGRect superRect; 26 | @property (nonatomic, retain) UILabel *touchPointLabel; 27 | @property (nonatomic, retain) NSMutableArray *rectsToOutline; 28 | @property (nonatomic, retain) DCCrossHairView *touchPointView; 29 | 30 | /////////// 31 | // Setup // 32 | /////////// 33 | 34 | - (id)initWithFrame:(CGRect)frame delegate:(id)aDelegate; 35 | 36 | //////////////////// 37 | // Custom Setters // 38 | //////////////////// 39 | 40 | - (void)setMainRect:(CGRect)newMainRect; 41 | - (void)setSuperRect:(CGRect)newSuperRect; 42 | 43 | ///////////////////// 44 | // Drawing/Display // 45 | ///////////////////// 46 | 47 | - (void)drawRect:(CGRect)rect; 48 | 49 | //////////////////// 50 | // Touch Handling // 51 | //////////////////// 52 | 53 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Classes/IDMPhoto.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMPhoto.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 17/10/2010. 6 | // Copyright 2010 d3i. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "IDMPhotoProtocol.h" 11 | #import "AFNetworking.h" 12 | 13 | // This class models a photo/image and it's caption 14 | // If you want to handle photos, caching, decompression 15 | // yourself then you can simply ensure your custom data model 16 | // conforms to IDMPhotoProtocol 17 | @interface IDMPhoto : NSObject 18 | 19 | // Progress download block, used to update the circularView 20 | typedef void (^IDMProgressUpdateBlock)(CGFloat progress); 21 | 22 | // Properties 23 | @property (nonatomic, strong) NSString *caption; 24 | @property (nonatomic, strong) NSURL *photoURL; 25 | @property (nonatomic, strong) IDMProgressUpdateBlock progressUpdateBlock; 26 | 27 | // Class 28 | + (IDMPhoto *)photoWithImage:(UIImage *)image; 29 | + (IDMPhoto *)photoWithFilePath:(NSString *)path; 30 | + (IDMPhoto *)photoWithURL:(NSURL *)url; 31 | 32 | + (NSArray *)photosWithImages:(NSArray *)imagesArray; 33 | + (NSArray *)photosWithFilePaths:(NSArray *)pathsArray; 34 | + (NSArray *)photosWithURLs:(NSArray *)urlsArray; 35 | 36 | // Init 37 | - (id)initWithImage:(UIImage *)image; 38 | - (id)initWithFilePath:(NSString *)path; 39 | - (id)initWithURL:(NSURL *)url; 40 | 41 | @end 42 | 43 | -------------------------------------------------------------------------------- /Classes/IDMZoomingScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMZoomingScrollView.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 14/10/2010. 6 | // Copyright 2010 d3i. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "IDMPhotoProtocol.h" 11 | #import "IDMTapDetectingImageView.h" 12 | #import "IDMTapDetectingView.h" 13 | 14 | #import "DACircularProgressView.h" 15 | 16 | @class IDMPhotoBrowser, IDMPhoto, IDMCaptionView; 17 | 18 | @interface IDMZoomingScrollView : UIScrollView { 19 | 20 | IDMPhotoBrowser *__weak _photoBrowser; 21 | id _photo; 22 | 23 | // This view references the related caption view for simplified handling in photo browser 24 | IDMCaptionView *_captionView; 25 | 26 | IDMTapDetectingView *_tapView; // for background taps 27 | 28 | DACircularProgressView *_progressView; 29 | } 30 | 31 | @property (nonatomic, strong) IDMTapDetectingImageView *photoImageView; 32 | @property (nonatomic, strong) IDMCaptionView *captionView; 33 | @property (nonatomic, strong) id photo; 34 | 35 | - (id)initWithPhotoBrowser:(IDMPhotoBrowser *)browser; 36 | - (void)displayImage; 37 | - (void)displayImageFailure; 38 | - (void)setProgress:(CGFloat)progress forPhoto:(IDMPhoto*)photo; 39 | - (void)setMaxMinZoomScalesForCurrentBounds; 40 | - (void)prepareForReuse; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.bundle/Localizations/pt.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "Cancel" = "Cancelar"; 3 | 4 | /* Informing the user an item has finished copying */ 5 | "Copied" = "Copiado"; 6 | 7 | /* No comment provided by engineer. */ 8 | "Copy" = "Copiar"; 9 | 10 | /* Displayed with ellipsis as 'Copying...' when an item is in the process of being copied */ 11 | "Copying" = "Copiando"; 12 | 13 | /* No comment provided by engineer. */ 14 | "Dismiss" = "Fechar"; 15 | 16 | /* No comment provided by engineer. */ 17 | "Done" = "Fechar"; 18 | 19 | /* No comment provided by engineer. */ 20 | "Email" = "Email"; 21 | 22 | /* No comment provided by engineer. */ 23 | "Email failed to send. Please try again." = "Email falhou ao enviar. Por favor, tente novamente."; 24 | 25 | /* Informing the user a process has failed */ 26 | "Failed" = "Falhou"; 27 | 28 | /* Used in the context: 'Showing 1 of 3 items' */ 29 | "of" = "de"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Photo" = "Foto"; 33 | 34 | /* Displayed with ellipsis as 'Preparing...' when an item is in the process of being prepared */ 35 | "Preparing" = "Preparando"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Save" = "Salvar"; 39 | 40 | /* Informing the user an item has been saved */ 41 | "Saved" = "Salvada"; 42 | 43 | /* Displayed with ellipsis as 'Saving...' when an item is in the process of being saved */ 44 | "Saving" = "Salvando"; 45 | 46 | -------------------------------------------------------------------------------- /Demo/PhotoBrowserDemo/PhotoBrowserDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | PhotoBrowser 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.appkraft.${PRODUCT_NAME:rfc1034identifier} 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 | UIApplicationExitsOnSuspend 28 | 29 | UIStatusBarHidden 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Classes/IDMTapDetectingView.m: -------------------------------------------------------------------------------- 1 | // 2 | // IDMTapDetectingView.m 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 04/11/2009. 6 | // Copyright 2009 d3i. All rights reserved. 7 | // 8 | 9 | #import "IDMTapDetectingView.h" 10 | 11 | @implementation IDMTapDetectingView 12 | 13 | @synthesize tapDelegate; 14 | 15 | - (id)init { 16 | if ((self = [super init])) { 17 | self.userInteractionEnabled = YES; 18 | } 19 | return self; 20 | } 21 | 22 | - (id)initWithFrame:(CGRect)frame { 23 | if ((self = [super initWithFrame:frame])) { 24 | self.userInteractionEnabled = YES; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 30 | UITouch *touch = [touches anyObject]; 31 | NSUInteger tapCount = touch.tapCount; 32 | switch (tapCount) { 33 | case 1: 34 | [self handleSingleTap:touch]; 35 | break; 36 | case 2: 37 | [self handleDoubleTap:touch]; 38 | break; 39 | case 3: 40 | [self handleTripleTap:touch]; 41 | break; 42 | default: 43 | break; 44 | } 45 | [[self nextResponder] touchesEnded:touches withEvent:event]; 46 | } 47 | 48 | - (void)handleSingleTap:(UITouch *)touch { 49 | if ([tapDelegate respondsToSelector:@selector(view:singleTapDetected:)]) 50 | [tapDelegate view:self singleTapDetected:touch]; 51 | } 52 | 53 | - (void)handleDoubleTap:(UITouch *)touch { 54 | if ([tapDelegate respondsToSelector:@selector(view:doubleTapDetected:)]) 55 | [tapDelegate view:self doubleTapDetected:touch]; 56 | } 57 | 58 | - (void)handleTripleTap:(UITouch *)touch { 59 | if ([tapDelegate respondsToSelector:@selector(view:tripleTapDetected:)]) 60 | [tapDelegate view:self tripleTapDetected:touch]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIKit+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #ifndef _UIKIT_AFNETWORKING_ 26 | #define _UIKIT_AFNETWORKING_ 27 | 28 | #import "AFNetworkActivityIndicatorManager.h" 29 | 30 | #import "UIActivityIndicatorView+AFNetworking.h" 31 | #import "UIAlertView+AFNetworking.h" 32 | #import "UIButton+AFNetworking.h" 33 | #import "UIImageView+AFNetworking.h" 34 | #import "UIKit+AFNetworking.h" 35 | #import "UIProgressView+AFNetworking.h" 36 | #import "UIWebView+AFNetworking.h" 37 | #endif /* _UIKIT_AFNETWORKING_ */ 38 | -------------------------------------------------------------------------------- /Classes/IDMTapDetectingImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // IDMTapDetectingImageView.m 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 04/11/2009. 6 | // Copyright 2009 d3i. All rights reserved. 7 | // 8 | 9 | #import "IDMTapDetectingImageView.h" 10 | 11 | @implementation IDMTapDetectingImageView 12 | 13 | @synthesize tapDelegate; 14 | 15 | - (id)initWithFrame:(CGRect)frame { 16 | if ((self = [super initWithFrame:frame])) { 17 | self.userInteractionEnabled = YES; 18 | } 19 | return self; 20 | } 21 | 22 | - (id)initWithImage:(UIImage *)image { 23 | if ((self = [super initWithImage:image])) { 24 | self.userInteractionEnabled = YES; 25 | } 26 | return self; 27 | } 28 | 29 | - (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage { 30 | if ((self = [super initWithImage:image highlightedImage:highlightedImage])) { 31 | self.userInteractionEnabled = YES; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 37 | UITouch *touch = [touches anyObject]; 38 | NSUInteger tapCount = touch.tapCount; 39 | switch (tapCount) { 40 | case 1: 41 | [self handleSingleTap:touch]; 42 | break; 43 | case 2: 44 | [self handleDoubleTap:touch]; 45 | break; 46 | case 3: 47 | [self handleTripleTap:touch]; 48 | break; 49 | default: 50 | break; 51 | } 52 | [[self nextResponder] touchesEnded:touches withEvent:event]; 53 | } 54 | 55 | - (void)handleSingleTap:(UITouch *)touch { 56 | if ([tapDelegate respondsToSelector:@selector(imageView:singleTapDetected:)]) 57 | [tapDelegate imageView:self singleTapDetected:touch]; 58 | } 59 | 60 | - (void)handleDoubleTap:(UITouch *)touch { 61 | if ([tapDelegate respondsToSelector:@selector(imageView:doubleTapDetected:)]) 62 | [tapDelegate imageView:self doubleTapDetected:touch]; 63 | } 64 | 65 | - (void)handleTripleTap:(UITouch *)touch { 66 | if ([tapDelegate respondsToSelector:@selector(imageView:tripleTapDetected:)]) 67 | [tapDelegate imageView:self tripleTapDetected:touch]; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | #ifndef _AFNETWORKING_ 27 | #define _AFNETWORKING_ 28 | 29 | #import "AFURLRequestSerialization.h" 30 | #import "AFURLResponseSerialization.h" 31 | #import "AFSecurityPolicy.h" 32 | #import "AFNetworkReachabilityManager.h" 33 | 34 | #import "AFURLConnectionOperation.h" 35 | #import "AFHTTPRequestOperation.h" 36 | #import "AFHTTPRequestOperationManager.h" 37 | 38 | #if ( ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || \ 39 | ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) ) 40 | #import "AFURLSessionManager.h" 41 | #import "AFHTTPSessionManager.h" 42 | #endif 43 | 44 | #endif /* _AFNETWORKING_ */ 45 | -------------------------------------------------------------------------------- /Classes/IDMPhotoProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMPhotoProtocol.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 02/01/2012. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "IDMPBConstants.h" 11 | 12 | // Name of notification used when a photo has completed loading process 13 | // Used to notify browser display the image 14 | #define IDMPhoto_LOADING_DID_END_NOTIFICATION @"IDMPhoto_LOADING_DID_END_NOTIFICATION" 15 | 16 | // If you wish to use your own data models for photo then they must conform 17 | // to this protocol. See instructions for details on each method. 18 | // Otherwise you can use the IDMPhoto object or subclass it yourself to 19 | // store more information per photo. 20 | // 21 | // You can see the IDMPhoto class for an example implementation of this protocol 22 | // 23 | @protocol IDMPhoto 24 | 25 | @required 26 | 27 | // Return underlying UIImage to be displayed 28 | // Return nil if the image is not immediately available (loaded into memory, preferably 29 | // already decompressed) and needs to be loaded from a source (cache, file, web, etc) 30 | // IMPORTANT: You should *NOT* use this method to initiate 31 | // fetching of images from any external of source. That should be handled 32 | // in -loadUnderlyingImageAndNotify: which may be called by the photo browser if this 33 | // methods returns nil. 34 | - (UIImage *)underlyingImage; 35 | 36 | // Called when the browser has determined the underlying images is not 37 | // already loaded into memory but needs it. 38 | // You must load the image asyncronously (and decompress it for better performance). 39 | // See IDMPhoto object for an example implementation. 40 | // When the underlying UIImage is loaded (or failed to load) you should post the following 41 | // notification: 42 | // 43 | // [[NSNotificationCenter defaultCenter] postNotificationName:IDMPhoto_LOADING_DID_END_NOTIFICATION 44 | // object:self]; 45 | // 46 | - (void)loadUnderlyingImageAndNotify; 47 | 48 | // This is called when the photo browser has determined the photo data 49 | // is no longer needed or there are low memory conditions 50 | // You should release any underlying (possibly large and decompressed) image data 51 | // as long as the image can be re-loaded (from cache, file, or URL) 52 | - (void)unloadUnderlyingImage; 53 | 54 | @optional 55 | 56 | // Return a caption string to be displayed over the image 57 | // Return nil to display no caption 58 | - (NSString *)caption; 59 | 60 | @end -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIActivityIndicatorView+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | 32 | @class AFURLConnectionOperation; 33 | 34 | /** 35 | This category adds methods to the UIKit framework's `UIActivityIndicatorView` class. The methods in this category provide support for automatically starting and stopping animation depending on the loading state of a request operation or session task. 36 | */ 37 | @interface UIActivityIndicatorView (AFNetworking) 38 | 39 | ///---------------------------------- 40 | /// @name Animating for Session Tasks 41 | ///---------------------------------- 42 | 43 | /** 44 | Binds the animating state to the state of the specified task. 45 | 46 | @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. 47 | */ 48 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) 49 | - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; 50 | #endif 51 | 52 | ///--------------------------------------- 53 | /// @name Animating for Request Operations 54 | ///--------------------------------------- 55 | 56 | /** 57 | Binds the animating state to the execution state of the specified operation. 58 | 59 | @param operation The operation. If `nil`, automatic updating from any previously specified operation will be disabled. 60 | */ 61 | - (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation; 62 | 63 | @end 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /Classes/IDMPhotoBrowser.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDMPhotoBrowser.h 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 14/10/2010. 6 | // Copyright 2010 d3i. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "IDMPhoto.h" 12 | #import "IDMPhotoProtocol.h" 13 | #import "IDMCaptionView.h" 14 | 15 | // Delgate 16 | @class IDMPhotoBrowser; 17 | @protocol IDMPhotoBrowserDelegate 18 | @optional 19 | - (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser didShowPhotoAtIndex:(NSUInteger)index; 20 | - (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser didDismissAtPageIndex:(NSUInteger)index; 21 | - (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser didDismissActionSheetWithButtonIndex:(NSUInteger)buttonIndex photoIndex:(NSUInteger)photoIndex; 22 | - (IDMCaptionView *)photoBrowser:(IDMPhotoBrowser *)photoBrowser captionViewForPhotoAtIndex:(NSUInteger)index; 23 | @end 24 | 25 | // IDMPhotoBrowser 26 | @interface IDMPhotoBrowser : UIViewController 27 | 28 | // Properties 29 | @property (nonatomic, strong) id delegate; 30 | 31 | // Toolbar customization 32 | @property (nonatomic) BOOL displayToolbar; 33 | @property (nonatomic) BOOL displayCounterLabel; 34 | @property (nonatomic) BOOL displayArrowButton; 35 | @property (nonatomic) BOOL displayActionButton; 36 | @property (nonatomic, strong) NSArray *actionButtonTitles; 37 | @property (nonatomic, weak) UIImage *leftArrowImage, *leftArrowSelectedImage; 38 | @property (nonatomic, weak) UIImage *rightArrowImage, *rightArrowSelectedImage; 39 | 40 | // View customization 41 | @property (nonatomic) BOOL displayDoneButton; 42 | @property (nonatomic) BOOL useWhiteBackgroundColor; 43 | @property (nonatomic, weak) UIImage *doneButtonImage; 44 | @property (nonatomic, weak) UIColor *trackTintColor, *progressTintColor; 45 | 46 | @property (nonatomic, weak) UIImage *scaleImage; 47 | 48 | @property (nonatomic) BOOL arrowButtonsChangePhotosAnimated; 49 | 50 | // defines zooming of the background defauly 1.0 51 | @property (nonatomic) float backgroundScaleFactor; 52 | 53 | // animation time defult .28 54 | @property (nonatomic) float animationDuration; 55 | 56 | // Init 57 | - (id)initWithPhotos:(NSArray *)photosArray; 58 | 59 | // Init (animated) 60 | - (id)initWithPhotos:(NSArray *)photosArray animatedFromView:(UIView*)view; 61 | 62 | // Init with NSURL objects 63 | - (id)initWithPhotoURLs:(NSArray *)photoURLsArray; 64 | 65 | // Init with NSURL objects (animated) 66 | - (id)initWithPhotoURLs:(NSArray *)photoURLsArray animatedFromView:(UIView*)view; 67 | 68 | // Reloads the photo browser and refetches data 69 | - (void)reloadData; 70 | 71 | // Set page that photo browser starts on 72 | - (void)setInitialPageIndex:(NSUInteger)index; 73 | 74 | // Get IDMPhoto at index 75 | - (id)photoAtIndex:(NSUInteger)index; 76 | 77 | // Change Sender View 78 | //- (void)setSenderViewForAnimation:(UIView*)senderView; 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/SVProgressHUD/SVProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // SVProgressHUD.h 3 | // 4 | // Created by Sam Vermette on 27.03.11. 5 | // Copyright 2011 Sam Vermette. All rights reserved. 6 | // 7 | // https://github.com/samvermette/SVProgressHUD 8 | // 9 | 10 | #import 11 | #import 12 | 13 | extern NSString * const SVProgressHUDDidReceiveTouchEventNotification; 14 | extern NSString * const SVProgressHUDWillDisappearNotification; 15 | extern NSString * const SVProgressHUDDidDisappearNotification; 16 | extern NSString * const SVProgressHUDWillAppearNotification; 17 | extern NSString * const SVProgressHUDDidAppearNotification; 18 | 19 | extern NSString * const SVProgressHUDStatusUserInfoKey; 20 | 21 | enum { 22 | SVProgressHUDMaskTypeNone = 1, // allow user interactions while HUD is displayed 23 | SVProgressHUDMaskTypeClear, // don't allow 24 | SVProgressHUDMaskTypeBlack, // don't allow and dim the UI in the back of the HUD 25 | SVProgressHUDMaskTypeGradient // don't allow and dim the UI with a a-la-alert-view bg gradient 26 | }; 27 | 28 | typedef NSUInteger SVProgressHUDMaskType; 29 | 30 | @interface SVProgressHUD : UIView 31 | 32 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000 33 | @property (readwrite, nonatomic, retain) UIColor *hudBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 34 | @property (readwrite, nonatomic, retain) UIColor *hudForegroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 35 | @property (readwrite, nonatomic, retain) UIColor *hudStatusShadowColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 36 | @property (readwrite, nonatomic, retain) UIColor *hudRingBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 37 | @property (readwrite, nonatomic, retain) UIColor *hudRingForegroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 38 | @property (readwrite, nonatomic, retain) UIFont *hudFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 39 | @property (readwrite, nonatomic, retain) UIImage *hudSuccessImage NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 40 | @property (readwrite, nonatomic, retain) UIImage *hudErrorImage NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; 41 | #endif 42 | 43 | + (void)setOffsetFromCenter:(UIOffset)offset; 44 | + (void)resetOffsetFromCenter; 45 | 46 | + (void)show; 47 | + (void)showWithMaskType:(SVProgressHUDMaskType)maskType; 48 | + (void)showWithStatus:(NSString*)status; 49 | + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 50 | 51 | + (void)showProgress:(float)progress; 52 | + (void)showProgress:(float)progress status:(NSString*)status; 53 | + (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 54 | 55 | + (void)setStatus:(NSString*)string; // change the HUD loading status while it's showing 56 | 57 | // stops the activity indicator, shows a glyph + status, and dismisses HUD 1s later 58 | + (void)showSuccessWithStatus:(NSString*)string; 59 | + (void)showErrorWithStatus:(NSString *)string; 60 | + (void)showImage:(UIImage*)image status:(NSString*)status; // use 28x28 white pngs 61 | 62 | + (void)popActivity; 63 | + (void)dismiss; 64 | 65 | + (BOOL)isVisible; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkActivityIndicatorManager.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | /** 32 | `AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a network request operation has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero. 33 | 34 | You should enable the shared instance of `AFNetworkActivityIndicatorManager` when your application finishes launching. In `AppDelegate application:didFinishLaunchingWithOptions:` you can do so with the following code: 35 | 36 | [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; 37 | 38 | By setting `isNetworkActivityIndicatorVisible` to `YES` for `sharedManager`, the network activity indicator will show and hide automatically as requests start and finish. You should not ever need to call `incrementActivityCount` or `decrementActivityCount` yourself. 39 | 40 | See the Apple Human Interface Guidelines section about the Network Activity Indicator for more information: 41 | http://developer.apple.com/library/iOS/#documentation/UserExperience/Conceptual/MobileHIG/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW44 42 | */ 43 | @interface AFNetworkActivityIndicatorManager : NSObject 44 | 45 | /** 46 | A Boolean value indicating whether the manager is enabled. 47 | 48 | If YES, the manager will change status bar network activity indicator according to network operation notifications it receives. The default value is NO. 49 | */ 50 | @property (nonatomic, assign, getter = isEnabled) BOOL enabled; 51 | 52 | /** 53 | A Boolean value indicating whether the network activity indicator is currently displayed in the status bar. 54 | */ 55 | @property (readonly, nonatomic, assign) BOOL isNetworkActivityIndicatorVisible; 56 | 57 | /** 58 | Returns the shared network activity indicator manager object for the system. 59 | 60 | @return The systemwide network activity indicator manager. 61 | */ 62 | + (instancetype)sharedManager; 63 | 64 | /** 65 | Increments the number of active network requests. If this number was zero before incrementing, this will start animating the status bar network activity indicator. 66 | */ 67 | - (void)incrementActivityCount; 68 | 69 | /** 70 | Decrements the number of active network requests. If this number becomes zero before decrementing, this will stop animating the status bar network activity indicator. 71 | */ 72 | - (void)decrementActivityCount; 73 | 74 | @end 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIProgressView+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | @class AFURLConnectionOperation; 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIProgressView` class. The methods in this category provide support for binding the progress to the upload and download progress of a session task or request operation. 35 | */ 36 | @interface UIProgressView (AFNetworking) 37 | 38 | ///------------------------------------ 39 | /// @name Setting Session Task Progress 40 | ///------------------------------------ 41 | 42 | /** 43 | Binds the progress to the upload progress of the specified session task. 44 | 45 | @param task The session task. 46 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 47 | */ 48 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) 49 | - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task 50 | animated:(BOOL)animated; 51 | #endif 52 | 53 | /** 54 | Binds the progress to the download progress of the specified session task. 55 | 56 | @param task The session task. 57 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 58 | */ 59 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) 60 | - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task 61 | animated:(BOOL)animated; 62 | #endif 63 | 64 | ///------------------------------------ 65 | /// @name Setting Session Task Progress 66 | ///------------------------------------ 67 | 68 | /** 69 | Binds the progress to the upload progress of the specified request operation. 70 | 71 | @param operation The request operation. 72 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 73 | */ 74 | - (void)setProgressWithUploadProgressOfOperation:(AFURLConnectionOperation *)operation 75 | animated:(BOOL)animated; 76 | 77 | /** 78 | Binds the progress to the download progress of the specified request operation. 79 | 80 | @param operation The request operation. 81 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 82 | */ 83 | - (void)setProgressWithDownloadProgressOfOperation:(AFURLConnectionOperation *)operation 84 | animated:(BOOL)animated; 85 | 86 | @end 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCIntrospectSettings.h: -------------------------------------------------------------------------------- 1 | ////////////// 2 | // Settings // 3 | ////////////// 4 | 5 | #define kDCIntrospectFlashOnRedrawColor [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:0.4f] // UIColor 6 | #define kDCIntrospectFlashOnRedrawFlashLength 0.03f // NSTimeInterval 7 | #define kDCIntrospectOpaqueColor [UIColor redColor] // UIColor 8 | #define kDCIntrospectTemporaryDisableDuration 10. // Seconds 9 | 10 | ////////////////// 11 | // Key Bindings // 12 | ////////////////// 13 | 14 | // '' is equivalent to page up (copy and paste this character to use) 15 | // '' is equivalent to page down (copy and paste this character to use) 16 | 17 | // Global // 18 | #define kDCIntrospectKeysInvoke @" " // starts introspector 19 | #define kDCIntrospectKeysToggleViewOutlines @"o" // shows outlines for all views 20 | #define kDCIntrospectKeysToggleNonOpaqueViews @"O" // changes all non-opaque view background colours to red (destructive) 21 | #define kDCIntrospectKeysToggleHelp @"?" // shows help 22 | #define kDCIntrospectKeysToggleFlashViewRedraws @"f" // toggle flashing on redraw for all views that implement [[DCIntrospect sharedIntrospector] flashRect:inView:] in drawRect: 23 | #define kDCIntrospectKeysToggleShowCoordinates @"c" // toggles the coordinates display 24 | #define kDCIntrospectKeysEnterBlockMode @"b" // enters block action mode 25 | 26 | // When introspector is invoked and a view is selected // 27 | #define kDCIntrospectKeysNudgeViewLeft @"4" // nudges the selected view in given direction 28 | #define kDCIntrospectKeysNudgeViewRight @"6" // 29 | #define kDCIntrospectKeysNudgeViewUp @"8" // 30 | #define kDCIntrospectKeysNudgeViewDown @"2" // 31 | #define kDCIntrospectKeysCenterInSuperview @"5" // centers the selected view in it's superview 32 | #define kDCIntrospectKeysIncreaseWidth @"9" // increases/decreases the width/height of selected view 33 | #define kDCIntrospectKeysDecreaseWidth @"7" // 34 | #define kDCIntrospectKeysIncreaseHeight @"3" // 35 | #define kDCIntrospectKeysDecreaseHeight @"1" // 36 | #define kDCIntrospectKeysLogCodeForCurrentViewChanges @"0" // prints code to the console of the changes to the current view. If the view has not been changed nothing will be printed. For example, if you nudge a view or change it's rect with the nudge keys, this will log '<#view#>.frame = CGRectMake(50.0, ..etc);'. Or if you set it's name using setName:forObject:accessedWithSelf: it will use the name provided, for example 'myView.frame = CGRectMake(...);'. Setting accessedWithSelf to YES would output 'self.myView.frame = CGRectMake(...);'. 37 | 38 | #define kDCIntrospectKeysIncreaseViewAlpha @"+" // increases/decreases the selected views alpha value 39 | #define kDCIntrospectKeysDecreaseViewAlpha @"-" // 40 | 41 | #define kDCIntrospectKeysSetNeedsDisplay @"d" // calls setNeedsDisplay on selected view 42 | #define kDCIntrospectKeysSetNeedsLayout @"l" // calls setNeedsLayout on selected view 43 | #define kDCIntrospectKeysReloadData @"r" // calls reloadData on selected view if it's a UITableView 44 | #define kDCIntrospectKeysLogProperties @"p" // logs all properties of the selected view 45 | #define kDCIntrospectKeysLogAccessibilityProperties @"a" // logs accessibility info (useful for automated view tests - thanks to @samsoffes for the idea) 46 | #define kDCIntrospectKeysLogViewRecursive @"v" // calls private method recursiveDescription which logs selected view heirachy 47 | 48 | #define kDCIntrospectKeysMoveUpInViewHierarchy @"y" // changes the selected view to it's superview 49 | #define kDCIntrospectKeysMoveBackInViewHierarchy @"t" // changes the selected view back to the previous view selected (after using the above command) 50 | 51 | #define kDCIntrospectKeysMoveDownToFirstSubview @"h" 52 | #define kDCIntrospectKeysMoveToNextSiblingView @"j" 53 | #define kDCIntrospectKeysMoveToPrevSiblingView @"g" 54 | 55 | #define kDCIntrospectKeysEnterGDB @"`" // enters GDB 56 | #define kDCIntrospectKeysDisableForPeriod @"~" // disables DCIntrospect for a given period (see kDCIntrospectTemporaryDisableDuration) 57 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIActivityIndicatorView+AFNetworking.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIActivityIndicatorView+AFNetworking.h" 24 | 25 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 26 | 27 | #import "AFHTTPRequestOperation.h" 28 | 29 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 30 | #import "AFURLSessionManager.h" 31 | #endif 32 | 33 | @implementation UIActivityIndicatorView (AFNetworking) 34 | 35 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 36 | - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { 37 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 38 | 39 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidStartNotification object:nil]; 40 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; 41 | [notificationCenter removeObserver:self name:AFNetworkingTaskDidFinishNotification object:nil]; 42 | 43 | if (task) { 44 | if (task.state != NSURLSessionTaskStateCompleted) { 45 | if (task.state == NSURLSessionTaskStateRunning) { 46 | [self startAnimating]; 47 | } else { 48 | [self stopAnimating]; 49 | } 50 | 51 | [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidStartNotification object:task]; 52 | [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidFinishNotification object:task]; 53 | [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidSuspendNotification object:task]; 54 | } 55 | } 56 | } 57 | #endif 58 | 59 | #pragma mark - 60 | 61 | - (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation { 62 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 63 | 64 | [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil]; 65 | [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; 66 | 67 | if (operation) { 68 | if (![operation isFinished]) { 69 | if ([operation isExecuting]) { 70 | [self startAnimating]; 71 | } else { 72 | [self stopAnimating]; 73 | } 74 | 75 | [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingOperationDidStartNotification object:operation]; 76 | [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingOperationDidFinishNotification object:operation]; 77 | } 78 | } 79 | } 80 | 81 | #pragma mark - 82 | 83 | - (void)af_startAnimating { 84 | dispatch_async(dispatch_get_main_queue(), ^{ 85 | [self startAnimating]; 86 | }); 87 | } 88 | 89 | - (void)af_stopAnimating { 90 | dispatch_async(dispatch_get_main_queue(), ^{ 91 | [self stopAnimating]; 92 | }); 93 | } 94 | 95 | @end 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /Classes/IDMCaptionView.m: -------------------------------------------------------------------------------- 1 | // 2 | // IDMCaptionView.m 3 | // IDMPhotoBrowser 4 | // 5 | // Created by Michael Waterfall on 30/12/2011. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "IDMCaptionView.h" 10 | #import "IDMPhoto.h" 11 | #import 12 | 13 | static const CGFloat labelPadding = 10; 14 | 15 | // Private 16 | @interface IDMCaptionView () { 17 | id _photo; 18 | UILabel *_label; 19 | } 20 | @end 21 | 22 | @implementation IDMCaptionView 23 | 24 | - (id)initWithPhoto:(id)photo { 25 | CGRect screenBound = [[UIScreen mainScreen] bounds]; 26 | CGFloat screenWidth = screenBound.size.width; 27 | 28 | if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft || 29 | [[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) { 30 | screenWidth = screenBound.size.height; 31 | } 32 | 33 | self = [super initWithFrame:CGRectMake(0, 0, screenWidth, 44)]; // Random initial frame 34 | if (self) { 35 | _photo = photo; 36 | self.opaque = NO; 37 | 38 | [self setBackground]; 39 | 40 | [self setupCaption]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (CGSize)sizeThatFits:(CGSize)size { 47 | if (_label.text.length == 0) return CGSizeZero; 48 | 49 | CGFloat maxHeight = 9999; 50 | if (_label.numberOfLines > 0) maxHeight = _label.font.leading*_label.numberOfLines; 51 | 52 | /*CGSize textSizeOLD = [_label.text sizeWithFont:_label.font 53 | constrainedToSize:CGSizeMake(size.width - labelPadding*2, maxHeight) 54 | lineBreakMode:_label.lineBreakMode];*/ 55 | 56 | NSString *text = _label.text; 57 | CGFloat width = size.width - labelPadding*2; 58 | UIFont *font = _label.font; 59 | 60 | NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text 61 | attributes:@{NSFontAttributeName: font}]; 62 | 63 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, maxHeight} 64 | options:NSStringDrawingUsesLineFragmentOrigin 65 | context:nil]; 66 | 67 | CGSize textSize = rect.size; 68 | 69 | return CGSizeMake(size.width, textSize.height + labelPadding * 2); 70 | } 71 | 72 | - (void)setupCaption { 73 | _label = [[UILabel alloc] initWithFrame:CGRectMake(labelPadding, 0, 74 | self.bounds.size.width-labelPadding*2, 75 | self.bounds.size.height)]; 76 | _label.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 77 | _label.opaque = NO; 78 | _label.backgroundColor = [UIColor clearColor]; 79 | _label.textAlignment = NSTextAlignmentCenter; 80 | _label.lineBreakMode = NSLineBreakByWordWrapping; 81 | _label.numberOfLines = 3; 82 | _label.textColor = [UIColor whiteColor]; 83 | _label.shadowColor = [UIColor colorWithWhite:0 alpha:0.5]; 84 | _label.shadowOffset = CGSizeMake(0, 1); 85 | _label.font = [UIFont systemFontOfSize:17]; 86 | if ([_photo respondsToSelector:@selector(caption)]) { 87 | _label.text = [_photo caption] ? [_photo caption] : @" "; 88 | } 89 | 90 | [self addSubview:_label]; 91 | } 92 | 93 | - (void)setBackground { 94 | UIView *fadeView = [[UIView alloc] initWithFrame:CGRectMake(0, -100, 10000, 130+100)]; // Static width, autoresizingMask is not working 95 | CAGradientLayer *gradient = [CAGradientLayer layer]; 96 | gradient.frame = fadeView.bounds; 97 | gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0 alpha:0.0] CGColor], (id)[[UIColor colorWithWhite:0 alpha:0.8] CGColor], nil]; 98 | [fadeView.layer insertSublayer:gradient atIndex:0]; 99 | fadeView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; //UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin; 100 | [self addSubview:fadeView]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCStatusBarOverlay.m: -------------------------------------------------------------------------------- 1 | // 2 | // DCStatusBarOverlay.m 3 | // 4 | // Copyright 2011 Domestic Cat. All rights reserved. 5 | // 6 | 7 | #import "DCStatusBarOverlay.h" 8 | 9 | @implementation DCStatusBarOverlay 10 | @synthesize leftLabel, rightLabel; 11 | 12 | - (void)dealloc 13 | { 14 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; 15 | 16 | [leftLabel release]; 17 | [rightLabel release]; 18 | 19 | [super dealloc]; 20 | } 21 | 22 | #pragma mark Setup 23 | 24 | - (id)init 25 | { 26 | if ((self = [super initWithFrame:CGRectZero])) 27 | { 28 | self.windowLevel = UIWindowLevelStatusBar + 1.0f; 29 | UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 30 | CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; 31 | CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; 32 | const CGFloat bar_size = 20; 33 | if (UIInterfaceOrientationIsLandscape(orientation)) 34 | self.frame = CGRectMake(0, 0, screenHeight, bar_size); 35 | else 36 | self.frame = CGRectMake(0, 0, screenWidth, bar_size); 37 | self.backgroundColor = [UIColor blackColor]; 38 | 39 | UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.frame]; 40 | backgroundImageView.image = [[UIImage imageNamed:@"statusBarBackground.png"] stretchableImageWithLeftCapWidth:2.0f topCapHeight:0.0f]; 41 | [self addSubview:backgroundImageView]; 42 | [backgroundImageView release]; 43 | 44 | self.leftLabel = [[[UILabel alloc] initWithFrame:CGRectOffset(self.frame, 2.0f, 0.0f)] autorelease]; 45 | self.leftLabel.backgroundColor = [UIColor clearColor]; 46 | self.leftLabel.textAlignment = UITextAlignmentLeft; 47 | self.leftLabel.font = [UIFont boldSystemFontOfSize:12.0f]; 48 | self.leftLabel.textColor = [UIColor colorWithWhite:0.97f alpha:1.0f]; 49 | self.leftLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 50 | [self addSubview:self.leftLabel]; 51 | 52 | self.rightLabel = [[[UILabel alloc] initWithFrame:CGRectOffset(self.frame, -2.0f, 0.0f)] autorelease]; 53 | self.rightLabel.backgroundColor = [UIColor clearColor]; 54 | self.rightLabel.font = [UIFont boldSystemFontOfSize:12.0f]; 55 | self.rightLabel.textAlignment = UITextAlignmentRight; 56 | self.rightLabel.textColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; 57 | self.rightLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 58 | [self addSubview:self.rightLabel]; 59 | 60 | UITapGestureRecognizer *gestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped)] autorelease]; 61 | [self addGestureRecognizer:gestureRecognizer]; 62 | 63 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 64 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateBarFrame) name:UIDeviceOrientationDidChangeNotification object:nil]; 65 | } 66 | 67 | return self; 68 | } 69 | 70 | - (void)updateBarFrame 71 | { 72 | // current interface orientation 73 | UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 74 | CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; 75 | CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; 76 | 77 | CGFloat pi = (CGFloat)M_PI; 78 | if (orientation == UIDeviceOrientationPortrait) 79 | { 80 | self.transform = CGAffineTransformIdentity; 81 | self.frame = CGRectMake(0, 0, screenWidth, self.frame.size.height); 82 | } 83 | else if (orientation == UIDeviceOrientationLandscapeLeft) 84 | { 85 | self.transform = CGAffineTransformMakeRotation(pi * (90) / 180.0f); 86 | self.frame = CGRectMake(screenWidth - self.frame.size.width, 0, self.frame.size.width, screenHeight); 87 | } 88 | else if (orientation == UIDeviceOrientationLandscapeRight) 89 | { 90 | self.transform = CGAffineTransformMakeRotation(pi * (-90) / 180.0f); 91 | self.frame = CGRectMake(0, 0, self.frame.size.width, screenHeight); 92 | } 93 | else if (orientation == UIDeviceOrientationPortraitUpsideDown) 94 | { 95 | self.transform = CGAffineTransformMakeRotation(pi); 96 | self.frame = CGRectMake(0, screenHeight - self.frame.size.height, screenWidth, self.frame.size.height); 97 | } 98 | } 99 | 100 | #pragma mark Actions 101 | 102 | - (void)tapped 103 | { 104 | [[NSNotificationCenter defaultCenter] postNotificationName:kDCIntrospectNotificationStatusBarTapped object:nil]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFSecurityPolicy.h: -------------------------------------------------------------------------------- 1 | // AFSecurity.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 27 | AFSSLPinningModeNone, 28 | AFSSLPinningModePublicKey, 29 | AFSSLPinningModeCertificate, 30 | }; 31 | 32 | /** 33 | `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. 34 | 35 | Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. 36 | */ 37 | @interface AFSecurityPolicy : NSObject 38 | 39 | /** 40 | The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. 41 | */ 42 | @property (nonatomic, assign) AFSSLPinningMode SSLPinningMode; 43 | 44 | /** 45 | The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. 46 | */ 47 | @property (nonatomic, strong) NSArray *pinnedCertificates; 48 | 49 | /** 50 | Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. 51 | */ 52 | @property (nonatomic, assign) BOOL allowInvalidCertificates; 53 | 54 | ///----------------------------------------- 55 | /// @name Getting Specific Security Policies 56 | ///----------------------------------------- 57 | 58 | /** 59 | Returns the shared default security policy, which does not accept invalid certificates, and does not validate against pinned certificates or public keys. 60 | 61 | @return The default security policy. 62 | */ 63 | + (instancetype)defaultPolicy; 64 | 65 | ///--------------------- 66 | /// @name Initialization 67 | ///--------------------- 68 | 69 | /** 70 | Creates and returns a security policy with the specified pinning mode. 71 | 72 | @param pinningMode The SSL pinning mode. 73 | 74 | @return A new security policy. 75 | */ 76 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; 77 | 78 | ///------------------------------ 79 | /// @name Evaluating Server Trust 80 | ///------------------------------ 81 | 82 | /** 83 | Whether or not the specified server trust should be accepted, based on the security policy. 84 | 85 | This method should be used when responding to an authentication challenge from a server. 86 | 87 | @param serverTrust The X.509 certificate trust of the server. 88 | 89 | @return Whether or not to trust the server. 90 | */ 91 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust; 92 | 93 | @end 94 | 95 | ///---------------- 96 | /// @name Constants 97 | ///---------------- 98 | 99 | /** 100 | ## SSL Pinning Modes 101 | 102 | The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. 103 | 104 | enum { 105 | AFSSLPinningModeNone, 106 | AFSSLPinningModePublicKey, 107 | AFSSLPinningModeCertificate, 108 | } 109 | 110 | `AFSSLPinningModeNone` 111 | Do not validate servers against pinned certificates. 112 | 113 | `AFSSLPinningModePublicKey` 114 | Validate host certificates against public keys of pinned certificates. 115 | 116 | `AFSSLPinningModeCertificate` 117 | Validate host certificates against pinned certificates. 118 | */ 119 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFHTTPRequestOperation.h: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperation.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "AFURLConnectionOperation.h" 25 | #import "AFURLResponseSerialization.h" 26 | 27 | /** 28 | `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. 29 | */ 30 | @interface AFHTTPRequestOperation : AFURLConnectionOperation 31 | 32 | ///------------------------------------------------ 33 | /// @name Getting HTTP URL Connection Information 34 | ///------------------------------------------------ 35 | 36 | /** 37 | The last HTTP response received by the operation's connection. 38 | */ 39 | @property (readonly, nonatomic, strong) NSHTTPURLResponse *response; 40 | 41 | /** 42 | Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an AFHTTPResoinse serializer, which uses the raw data as its response object. The serializer validates the status code to be in the `2XX` range, denoting success. If the response serializer generates an error in `-responseObjectForResponse:data:error:`, the `failure` callback of the session task or request operation will be executed; otherwise, the `success` callback will be executed. 43 | 44 | @warning `responseSerializer` must not be `nil`. Setting a response serializer will clear out any cached value 45 | */ 46 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 47 | 48 | /** 49 | An object constructed by the `responseSerializer` from the response and response data. Returns `nil` unless the operation `isFinished`, has a `response`, and has `responseData` with non-zero content length. If an error occurs during serialization, `nil` will be returned, and the `error` property will be populated with the serialization error. 50 | */ 51 | @property (readonly, nonatomic, strong) id responseObject; 52 | 53 | ///----------------------------------------------------------- 54 | /// @name Setting Completion Block Success / Failure Callbacks 55 | ///----------------------------------------------------------- 56 | 57 | /** 58 | Sets the `completionBlock` property with a block that executes either the specified success or failure block, depending on the state of the request on completion. If `error` returns a value, which can be caused by an unacceptable status code or content type, then `failure` is executed. Otherwise, `success` is executed. 59 | 60 | This method should be overridden in subclasses in order to specify the response object passed into the success block. 61 | 62 | @param success The block to be executed on the completion of a successful request. This block has no return value and takes two arguments: the receiver operation and the object constructed from the response data of the request. 63 | @param failure The block to be executed on the completion of an unsuccessful request. This block has no return value and takes two arguments: the receiver operation and the error that occurred during the request. 64 | */ 65 | - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 66 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIAlertView+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | @class AFURLConnectionOperation; 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIAlertView` class. The methods in this category provide support for automatically showing an alert if a session task or request operation finishes with an error. Alert title and message are filled from the corresponding `localizedDescription` & `localizedRecoverySuggestion` or `localizedFailureReason` of the error. 35 | */ 36 | @interface UIAlertView (AFNetworking) 37 | 38 | ///------------------------------------- 39 | /// @name Showing Alert for Session Task 40 | ///------------------------------------- 41 | 42 | /** 43 | Shows an alert view with the error of the specified session task, if any. 44 | 45 | @param task The session task. 46 | @param delegate The alert view delegate. 47 | */ 48 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 49 | + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task 50 | delegate:(id)delegate; 51 | #endif 52 | 53 | /** 54 | Shows an alert view with the error of the specified session task, if any, with a custom cancel button title and other button titles. 55 | 56 | @param task The session task. 57 | @param delegate The alert view delegate. 58 | @param cancelButtonTitle The title of the cancel button or nil if there is no cancel button. Using this argument is equivalent to setting the cancel button index to the value returned by invoking addButtonWithTitle: specifying this title. 59 | @param otherButtonTitles The title of another button. Using this argument is equivalent to invoking addButtonWithTitle: with this title to add more buttons. Too many buttons can cause the alert view to scroll. For guidelines on the best ways to use an alert in an app, see "Temporary Views". Titles of additional buttons to add to the receiver, terminated with `nil`. 60 | */ 61 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 62 | + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task 63 | delegate:(id)delegate 64 | cancelButtonTitle:(NSString *)cancelButtonTitle 65 | otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; 66 | #endif 67 | 68 | ///------------------------------------------ 69 | /// @name Showing Alert for Request Operation 70 | ///------------------------------------------ 71 | 72 | /** 73 | Shows an alert view with the error of the specified request operation, if any. 74 | 75 | @param operation The request operation. 76 | @param delegate The alert view delegate. 77 | */ 78 | + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation 79 | delegate:(id)delegate; 80 | 81 | /** 82 | Shows an alert view with the error of the specified request operation, if any, with a custom cancel button title and other button titles. 83 | 84 | @param operation The request operation. 85 | @param delegate The alert view delegate. 86 | @param cancelButtonTitle The title of the cancel button or nil if there is no cancel button. Using this argument is equivalent to setting the cancel button index to the value returned by invoking addButtonWithTitle: specifying this title. 87 | @param otherButtonTitles The title of another button. Using this argument is equivalent to invoking addButtonWithTitle: with this title to add more buttons. Too many buttons can cause the alert view to scroll. For guidelines on the best ways to use an alert in an app, see "Temporary Views". Titles of additional buttons to add to the receiver, terminated with `nil`. 88 | */ 89 | + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation 90 | delegate:(id)delegate 91 | cancelButtonTitle:(NSString *)cancelButtonTitle 92 | otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; 93 | 94 | @end 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCIntrospect.h: -------------------------------------------------------------------------------- 1 | // 2 | // DCIntrospect.h 3 | // 4 | // Created by Domestic Cat on 29/04/11. 5 | // 6 | 7 | #define kDCIntrospectNotificationIntrospectionDidStart @"kDCIntrospectNotificationIntrospectionDidStart" 8 | #define kDCIntrospectNotificationIntrospectionDidEnd @"kDCIntrospectNotificationIntrospectionDidEnd" 9 | #define kDCIntrospectAnimationDuration 0.08 10 | 11 | #import 12 | #include "TargetConditionals.h" 13 | 14 | #import "DCIntrospectSettings.h" 15 | #import "DCFrameView.h" 16 | #import "DCStatusBarOverlay.h" 17 | 18 | #ifdef DEBUG 19 | 20 | @interface UIView (debug) 21 | 22 | - (NSString *)recursiveDescription; 23 | 24 | @end 25 | 26 | #endif 27 | 28 | @interface DCIntrospect : NSObject 29 | { 30 | } 31 | 32 | @property (nonatomic) BOOL keyboardBindingsOn; // default: YES 33 | @property (nonatomic) BOOL showStatusBarOverlay; // default: YES 34 | @property (nonatomic, retain) UIGestureRecognizer *invokeGestureRecognizer; // default: nil 35 | 36 | @property (nonatomic) BOOL on; 37 | @property (nonatomic) BOOL handleArrowKeys; 38 | @property (nonatomic) BOOL viewOutlines; 39 | @property (nonatomic) BOOL highlightNonOpaqueViews; 40 | @property (nonatomic) BOOL flashOnRedraw; 41 | @property (nonatomic, retain) DCFrameView *frameView; 42 | @property (nonatomic, retain) UITextView *inputTextView; 43 | @property (nonatomic, retain) DCStatusBarOverlay *statusBarOverlay; 44 | 45 | @property (nonatomic, retain) NSMutableDictionary *objectNames; 46 | 47 | @property (nonatomic, assign) UIView *currentView; 48 | @property (nonatomic) CGRect originalFrame; 49 | @property (nonatomic) CGFloat originalAlpha; 50 | @property (nonatomic, retain) NSMutableArray *currentViewHistory; 51 | 52 | @property (nonatomic) BOOL showingHelp; 53 | 54 | /////////// 55 | // Setup // 56 | /////////// 57 | 58 | + (DCIntrospect *)sharedIntrospector; // this returns nil when NOT in DEGBUG mode 59 | - (void)start; // NOTE: call setup AFTER [window makeKeyAndVisible] so statusBarOrientation is reported correctly. 60 | 61 | //////////////////// 62 | // Custom Setters // 63 | //////////////////// 64 | 65 | - (void)setInvokeGestureRecognizer:(UIGestureRecognizer *)newGestureRecognizer; 66 | - (void)setKeyboardBindingsOn:(BOOL)keyboardBindingsOn; 67 | 68 | ////////////////// 69 | // Main Actions // 70 | ////////////////// 71 | 72 | - (void)invokeIntrospector; // can be called manually 73 | - (void)touchAtPoint:(CGPoint)point; // can be called manually 74 | - (void)selectView:(UIView *)view; 75 | - (void)statusBarTapped; 76 | 77 | ////////////////////// 78 | // Keyboard Capture // 79 | ////////////////////// 80 | 81 | - (void)textViewDidChangeSelection:(UITextView *)textView; 82 | - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string; 83 | 84 | ///////////////////////////////// 85 | // Logging Code & Object Names // 86 | ///////////////////////////////// 87 | 88 | - (void)logCodeForCurrentViewChanges; 89 | 90 | // make sure all names that are added are removed at dealloc or else they will be retained here! 91 | - (void)setName:(NSString *)name forObject:(id)object accessedWithSelf:(BOOL)accessedWithSelf; 92 | - (NSString *)nameForObject:(id)object; 93 | - (void)removeNamesForViewsInView:(UIView *)view; 94 | - (void)removeNameForObject:(id)object; 95 | 96 | //////////// 97 | // Layout // 98 | //////////// 99 | 100 | - (void)updateFrameView; 101 | - (void)updateStatusBar; 102 | - (void)updateViews; 103 | - (void)showTemporaryStringInStatusBar:(NSString *)string; 104 | 105 | ///////////// 106 | // Actions // 107 | ///////////// 108 | 109 | - (void)logRecursiveDescriptionForCurrentView; 110 | - (void)logRecursiveDescriptionForView:(UIView *)view; 111 | - (void)forceSetNeedsDisplay; 112 | - (void)forceSetNeedsLayout; 113 | - (void)forceReloadOfView; 114 | - (void)toggleOutlines; 115 | - (void)addOutlinesToFrameViewFromSubview:(UIView *)view; 116 | - (void)toggleNonOpaqueViews; 117 | - (void)setBackgroundColor:(UIColor *)color ofNonOpaqueViewsInSubview:(UIView *)view; 118 | - (void)toggleRedrawFlashing; 119 | - (void)callDrawRectOnViewsInSubview:(UIView *)subview; 120 | - (void)flashRect:(CGRect)rect inView:(UIView *)view; 121 | 122 | ///////////////////////////// 123 | // (Somewhat) Experimental // 124 | ///////////////////////////// 125 | 126 | - (void)logPropertiesForCurrentView; 127 | - (void)logPropertiesForObject:(id)object; 128 | - (void)logAccessabilityPropertiesForObject:(id)object; 129 | - (NSArray *)subclassesOfClass:(Class)parentClass; 130 | 131 | ///////////////////////// 132 | // Description Methods // 133 | ///////////////////////// 134 | 135 | - (NSString *)describeProperty:(NSString *)propertyName value:(id)value; 136 | - (NSString *)describeColor:(UIColor *)color; 137 | 138 | ///////////////////////// 139 | // DCIntrospector Help // 140 | ///////////////////////// 141 | 142 | - (void)toggleHelp; 143 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 144 | 145 | //////////////////// 146 | // Helper Methods // 147 | //////////////////// 148 | 149 | - (UIWindow *)mainWindow; 150 | - (NSMutableArray *)viewsAtPoint:(CGPoint)touchPoint inView:(UIView *)view; 151 | - (void)fadeView:(UIView *)view toAlpha:(CGFloat)alpha; 152 | - (BOOL)view:(UIView *)view containsSubview:(UIView *)subview; 153 | - (BOOL)shouldIgnoreView:(UIView *)view; 154 | 155 | @end 156 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIWebView+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | #import "AFURLRequestSerialization.h" 32 | #import "AFURLResponseSerialization.h" 33 | 34 | /** 35 | This category adds methods to the UIKit framework's `UIWebView` class. The methods in this category provide increased control over the request cycle, including progress monitoring and success / failure handling. 36 | */ 37 | @interface UIWebView (AFNetworking) 38 | 39 | /** 40 | The request serializer used to serialize requests made with the `-loadRequest:...` category methods. By default, this is an instance of `AFHTTPRequestSerializer`. 41 | */ 42 | @property (nonatomic, strong) AFHTTPRequestSerializer * requestSerializer; 43 | 44 | /** 45 | The response serializer used to serialize responses made with the `-loadRequest:...` category methods. By default, this is an instance of `AFHTTPResponseSerializer`. 46 | */ 47 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 48 | 49 | /** 50 | Asynchronously loads the specified request. 51 | 52 | @param request A URL request identifying the location of the content to load. This must not be `nil`. 53 | @param progress A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. 54 | @param success A block object to be executed when the request finishes loading successfully. This block returns the HTML string to be loaded by the web view, and takes two arguments: the response, and the response string. 55 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. 56 | */ 57 | - (void)loadRequest:(NSURLRequest *)request 58 | progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress 59 | success:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success 60 | failure:(void (^)(NSError *error))failure; 61 | 62 | /** 63 | Asynchronously loads the data associated with a particular request with a specified MIME type and text encoding. 64 | 65 | @param request A URL request identifying the location of the content to load. This must not be `nil`. 66 | @param MIMEType The MIME type of the content. Defaults to the content type of the response if not specified. 67 | @param textEncodingName The IANA encoding name, as in `utf-8` or `utf-16`. Defaults to the response text encoding if not specified. 68 | @param progress A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. 69 | @param success A block object to be executed when the request finishes loading successfully. This block returns the data to be loaded by the web view and takes two arguments: the response, and the downloaded data. 70 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. 71 | */ 72 | - (void)loadRequest:(NSURLRequest *)request 73 | MIMEType:(NSString *)MIMEType 74 | textEncodingName:(NSString *)textEncodingName 75 | progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress 76 | success:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))success 77 | failure:(void (^)(NSError *error))failure; 78 | 79 | @end 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIAlertView+AFNetworking.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIAlertView+AFNetworking.h" 24 | 25 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 26 | 27 | #import "AFURLConnectionOperation.h" 28 | 29 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 30 | #import "AFURLSessionManager.h" 31 | #endif 32 | 33 | static void AFGetAlertViewTitleAndMessageFromError(NSError *error, NSString * __autoreleasing *title, NSString * __autoreleasing *message) { 34 | if (error.localizedDescription && (error.localizedRecoverySuggestion || error.localizedFailureReason)) { 35 | *title = error.localizedDescription; 36 | 37 | if (error.localizedRecoverySuggestion) { 38 | *message = error.localizedRecoverySuggestion; 39 | } else { 40 | *message = error.localizedFailureReason; 41 | } 42 | } else if (error.localizedDescription) { 43 | *title = NSLocalizedStringFromTable(@"Error", @"AFNetworking", @"Fallback Error Description"); 44 | *message = error.localizedDescription; 45 | } else { 46 | *title = NSLocalizedStringFromTable(@"Error", @"AFNetworking", @"Fallback Error Description"); 47 | *message = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Error: %d", @"AFNetworking", @"Fallback Error Failure Reason Format"), error.domain, error.code]; 48 | } 49 | } 50 | 51 | @implementation UIAlertView (AFNetworking) 52 | 53 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 54 | + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task 55 | delegate:(id)delegate 56 | { 57 | [self showAlertViewForTaskWithErrorOnCompletion:task delegate:delegate cancelButtonTitle:NSLocalizedStringFromTable(@"Dismiss", @"AFNetworking", @"UIAlertView Cancel Button Title") otherButtonTitles:nil, nil]; 58 | } 59 | 60 | + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task 61 | delegate:(id)delegate 62 | cancelButtonTitle:(NSString *)cancelButtonTitle 63 | otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION 64 | { 65 | __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingTaskDidFinishNotification object:task queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { 66 | 67 | NSError *error = notification.userInfo[AFNetworkingTaskDidFinishErrorKey]; 68 | if (error) { 69 | NSString *title, *message; 70 | AFGetAlertViewTitleAndMessageFromError(error, &title, &message); 71 | 72 | [[[UIAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil] show]; 73 | } 74 | 75 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:AFNetworkingTaskDidFinishNotification object:notification.object]; 76 | }]; 77 | } 78 | #endif 79 | 80 | #pragma mark - 81 | 82 | + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation 83 | delegate:(id)delegate 84 | { 85 | [self showAlertViewForRequestOperationWithErrorOnCompletion:operation delegate:delegate cancelButtonTitle:NSLocalizedStringFromTable(@"Dismiss", @"AFNetworking", @"UIAlert View Cancel Button Title") otherButtonTitles:nil, nil]; 86 | } 87 | 88 | + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation 89 | delegate:(id)delegate 90 | cancelButtonTitle:(NSString *)cancelButtonTitle 91 | otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION 92 | { 93 | __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingOperationDidFinishNotification object:operation queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { 94 | 95 | if (notification.object && [notification.object isKindOfClass:[AFURLConnectionOperation class]]) { 96 | NSError *error = [(AFURLConnectionOperation *)notification.object error]; 97 | if (error) { 98 | NSString *title, *message; 99 | AFGetAlertViewTitleAndMessageFromError(error, &title, &message); 100 | 101 | [[[UIAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil] show]; 102 | } 103 | } 104 | 105 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:AFNetworkingOperationDidFinishNotification object:notification.object]; 106 | }]; 107 | } 108 | 109 | @end 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIImageView+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | #import "AFURLResponseSerialization.h" 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIImageView` class. The methods in this category provide support for loading remote images asynchronously from a URL. 35 | */ 36 | @interface UIImageView (AFNetworking) 37 | 38 | ///------------------------------------ 39 | /// @name Accessing Response Serializer 40 | ///------------------------------------ 41 | 42 | /** 43 | The response serializer used to create an image representation from the server response and response data. By default, this is an instance of `AFImageResponseSerializer`. 44 | 45 | @discussion Subclasses of `AFImageResponseSerializer` could be used to perform post-processing, such as color correction, face detection, or other effects. See https://github.com/AFNetworking/AFCoreImageSerializer 46 | */ 47 | @property (nonatomic, strong) AFImageResponseSerializer * imageResponseSerializer; 48 | 49 | ///-------------------- 50 | /// @name Setting Image 51 | ///-------------------- 52 | 53 | /** 54 | Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. 55 | 56 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 57 | 58 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 59 | 60 | @param url The URL used for the image request. 61 | */ 62 | - (void)setImageWithURL:(NSURL *)url; 63 | 64 | /** 65 | Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. 66 | 67 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 68 | 69 | By default, URL requests have a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` 70 | 71 | @param url The URL used for the image request. 72 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 73 | */ 74 | - (void)setImageWithURL:(NSURL *)url 75 | placeholderImage:(UIImage *)placeholderImage; 76 | 77 | /** 78 | Asynchronously downloads an image from the specified URL request, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. 79 | 80 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 81 | 82 | If a success block is specified, it is the responsibility of the block to set the image of the image view before returning. If no success block is specified, the default behavior of setting the image with `self.image = image` is applied. 83 | 84 | @param urlRequest The URL request used for the image request. 85 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. 86 | @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the request and response parameters will be `nil`. 87 | @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. 88 | */ 89 | - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 90 | placeholderImage:(UIImage *)placeholderImage 91 | success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success 92 | failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; 93 | 94 | /** 95 | Cancels any executing image operation for the receiver, if one exists. 96 | */ 97 | - (void)cancelImageRequestOperation; 98 | 99 | @end 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIWebView+AFNetworking.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIWebView+AFNetworking.h" 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import "AFHTTPRequestOperation.h" 30 | 31 | static char kAFRequestSerializerKey; 32 | static char kAFResponseSerializerKey; 33 | static char kAFHTTPRequestOperationKey; 34 | 35 | @interface UIWebView (_AFNetworking) 36 | @property (readwrite, nonatomic, strong, setter = af_setHTTPRequestOperation:) AFHTTPRequestOperation *af_HTTPRequestOperation; 37 | @end 38 | 39 | @implementation UIWebView (_AFNetworking) 40 | 41 | - (AFHTTPRequestOperation *)af_HTTPRequestOperation { 42 | return (AFHTTPRequestOperation *)objc_getAssociatedObject(self, &kAFHTTPRequestOperationKey); 43 | } 44 | 45 | - (void)af_setHTTPRequestOperation:(AFHTTPRequestOperation *)operation { 46 | objc_setAssociatedObject(self, &kAFHTTPRequestOperationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 47 | } 48 | 49 | @end 50 | 51 | #pragma mark - 52 | 53 | @implementation UIWebView (AFNetworking) 54 | 55 | - (AFHTTPRequestSerializer *)requestSerializer { 56 | static AFHTTPRequestSerializer * _af_defaultRequestSerializer = nil; 57 | static dispatch_once_t onceToken; 58 | dispatch_once(&onceToken, ^{ 59 | _af_defaultRequestSerializer = [AFHTTPRequestSerializer serializer]; 60 | }); 61 | 62 | #pragma clang diagnostic push 63 | #pragma clang diagnostic ignored "-Wgnu" 64 | return objc_getAssociatedObject(self, &kAFRequestSerializerKey) ?: _af_defaultRequestSerializer; 65 | #pragma clang diagnostic pop 66 | } 67 | 68 | - (void)setRequestSerializer:(AFHTTPRequestSerializer *)requestSerializer { 69 | objc_setAssociatedObject(self, &kAFRequestSerializerKey, requestSerializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 70 | } 71 | 72 | - (AFHTTPResponseSerializer *)responseSerializer { 73 | static AFHTTPResponseSerializer * _af_defaultResponseSerializer = nil; 74 | static dispatch_once_t onceToken; 75 | dispatch_once(&onceToken, ^{ 76 | _af_defaultResponseSerializer = [AFHTTPResponseSerializer serializer]; 77 | }); 78 | 79 | #pragma clang diagnostic push 80 | #pragma clang diagnostic ignored "-Wgnu" 81 | return objc_getAssociatedObject(self, &kAFRequestSerializerKey) ?: _af_defaultResponseSerializer; 82 | #pragma clang diagnostic pop 83 | } 84 | 85 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 86 | objc_setAssociatedObject(self, &kAFResponseSerializerKey, responseSerializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 87 | } 88 | 89 | #pragma mark - 90 | 91 | - (void)loadRequest:(NSURLRequest *)request 92 | progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress 93 | success:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success 94 | failure:(void (^)(NSError *error))failure 95 | { 96 | [self loadRequest:request MIMEType:nil textEncodingName:nil progress:progress success:^NSData *(NSHTTPURLResponse *response, NSData *data) { 97 | if (!success) { 98 | return data; 99 | } 100 | 101 | NSStringEncoding stringEncoding = NSUTF8StringEncoding; 102 | if (response.textEncodingName) { 103 | CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName); 104 | if (encoding != kCFStringEncodingInvalidId) { 105 | stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding); 106 | } 107 | } 108 | 109 | return [[[NSString alloc] initWithData:data encoding:stringEncoding] dataUsingEncoding:stringEncoding]; 110 | } failure:failure]; 111 | } 112 | 113 | - (void)loadRequest:(NSURLRequest *)request 114 | MIMEType:(NSString *)MIMEType 115 | textEncodingName:(NSString *)textEncodingName 116 | progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress 117 | success:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))success 118 | failure:(void (^)(NSError *error))failure 119 | { 120 | NSParameterAssert(request); 121 | 122 | if (self.af_HTTPRequestOperation) { 123 | [self.af_HTTPRequestOperation cancel]; 124 | } 125 | 126 | request = [self.requestSerializer requestBySerializingRequest:request withParameters:nil error:nil]; 127 | 128 | self.af_HTTPRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 129 | self.af_HTTPRequestOperation.responseSerializer = self.responseSerializer; 130 | 131 | __weak __typeof(self)weakSelf = self; 132 | [self.af_HTTPRequestOperation setDownloadProgressBlock:progress]; 133 | [self.af_HTTPRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id __unused responseObject) { 134 | NSData *data = success ? success(operation.response, operation.responseData) : operation.responseData; 135 | 136 | #pragma clang diagnostic push 137 | #pragma clang diagnostic ignored "-Wgnu" 138 | [weakSelf loadData:data MIMEType:(MIMEType ?: [operation.response MIMEType]) textEncodingName:(textEncodingName ?: [operation.response textEncodingName]) baseURL:[operation.response URL]]; 139 | #pragma clang diagnostic pop 140 | } failure:^(AFHTTPRequestOperation * __unused operation, NSError *error) { 141 | if (failure) { 142 | failure(error); 143 | } 144 | }]; 145 | 146 | [self.af_HTTPRequestOperation start]; 147 | } 148 | 149 | @end 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m: -------------------------------------------------------------------------------- 1 | // AFNetworkActivityIndicatorManager.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFNetworkActivityIndicatorManager.h" 24 | 25 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 26 | 27 | #import "AFHTTPRequestOperation.h" 28 | 29 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 30 | #import "AFURLSessionManager.h" 31 | #endif 32 | 33 | static NSTimeInterval const kAFNetworkActivityIndicatorInvisibilityDelay = 0.17; 34 | 35 | static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notification) { 36 | if ([[notification object] isKindOfClass:[AFURLConnectionOperation class]]) { 37 | return [(AFURLConnectionOperation *)[notification object] request]; 38 | } 39 | 40 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 41 | if ([[notification object] respondsToSelector:@selector(originalRequest)]) { 42 | return [(NSURLSessionTask *)[notification object] originalRequest]; 43 | } 44 | #endif 45 | 46 | return nil; 47 | } 48 | 49 | @interface AFNetworkActivityIndicatorManager () 50 | @property (readwrite, nonatomic, assign) NSInteger activityCount; 51 | @property (readwrite, nonatomic, strong) NSTimer *activityIndicatorVisibilityTimer; 52 | @property (readonly, nonatomic, getter = isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; 53 | 54 | - (void)updateNetworkActivityIndicatorVisibility; 55 | - (void)updateNetworkActivityIndicatorVisibilityDelayed; 56 | @end 57 | 58 | @implementation AFNetworkActivityIndicatorManager 59 | @dynamic networkActivityIndicatorVisible; 60 | 61 | + (instancetype)sharedManager { 62 | static AFNetworkActivityIndicatorManager *_sharedManager = nil; 63 | static dispatch_once_t oncePredicate; 64 | dispatch_once(&oncePredicate, ^{ 65 | _sharedManager = [[self alloc] init]; 66 | }); 67 | 68 | return _sharedManager; 69 | } 70 | 71 | + (NSSet *)keyPathsForValuesAffectingIsNetworkActivityIndicatorVisible { 72 | return [NSSet setWithObject:@"activityCount"]; 73 | } 74 | 75 | - (id)init { 76 | self = [super init]; 77 | if (!self) { 78 | return nil; 79 | } 80 | 81 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidStart:) name:AFNetworkingOperationDidStartNotification object:nil]; 82 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingOperationDidFinishNotification object:nil]; 83 | 84 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 85 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidStart:) name:AFNetworkingTaskDidStartNotification object:nil]; 86 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidSuspendNotification object:nil]; 87 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidFinishNotification object:nil]; 88 | #endif 89 | 90 | return self; 91 | } 92 | 93 | - (void)dealloc { 94 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 95 | 96 | [_activityIndicatorVisibilityTimer invalidate]; 97 | } 98 | 99 | - (void)updateNetworkActivityIndicatorVisibilityDelayed { 100 | if (self.enabled) { 101 | // Delay hiding of activity indicator for a short interval, to avoid flickering 102 | if (![self isNetworkActivityIndicatorVisible]) { 103 | [self.activityIndicatorVisibilityTimer invalidate]; 104 | self.activityIndicatorVisibilityTimer = [NSTimer timerWithTimeInterval:kAFNetworkActivityIndicatorInvisibilityDelay target:self selector:@selector(updateNetworkActivityIndicatorVisibility) userInfo:nil repeats:NO]; 105 | [[NSRunLoop mainRunLoop] addTimer:self.activityIndicatorVisibilityTimer forMode:NSRunLoopCommonModes]; 106 | } else { 107 | [self performSelectorOnMainThread:@selector(updateNetworkActivityIndicatorVisibility) withObject:nil waitUntilDone:NO modes:@[NSRunLoopCommonModes]]; 108 | } 109 | } 110 | } 111 | 112 | - (BOOL)isNetworkActivityIndicatorVisible { 113 | return self.activityCount > 0; 114 | } 115 | 116 | - (void)updateNetworkActivityIndicatorVisibility { 117 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:[self isNetworkActivityIndicatorVisible]]; 118 | } 119 | 120 | - (void)setActivityCount:(NSInteger)activityCount { 121 | @synchronized(self) { 122 | _activityCount = activityCount; 123 | } 124 | 125 | dispatch_async(dispatch_get_main_queue(), ^{ 126 | [self updateNetworkActivityIndicatorVisibilityDelayed]; 127 | }); 128 | } 129 | 130 | - (void)incrementActivityCount { 131 | [self willChangeValueForKey:@"activityCount"]; 132 | @synchronized(self) { 133 | _activityCount++; 134 | } 135 | [self didChangeValueForKey:@"activityCount"]; 136 | 137 | dispatch_async(dispatch_get_main_queue(), ^{ 138 | [self updateNetworkActivityIndicatorVisibilityDelayed]; 139 | }); 140 | } 141 | 142 | - (void)decrementActivityCount { 143 | [self willChangeValueForKey:@"activityCount"]; 144 | @synchronized(self) { 145 | #pragma clang diagnostic push 146 | #pragma clang diagnostic ignored "-Wgnu" 147 | _activityCount = MAX(_activityCount - 1, 0); 148 | #pragma clang diagnostic pop 149 | } 150 | [self didChangeValueForKey:@"activityCount"]; 151 | 152 | dispatch_async(dispatch_get_main_queue(), ^{ 153 | [self updateNetworkActivityIndicatorVisibilityDelayed]; 154 | }); 155 | } 156 | 157 | - (void)networkRequestDidStart:(NSNotification *)notification { 158 | if ([AFNetworkRequestFromNotification(notification) URL]) { 159 | [self incrementActivityCount]; 160 | } 161 | } 162 | 163 | - (void)networkRequestDidFinish:(NSNotification *)notification { 164 | if ([AFNetworkRequestFromNotification(notification) URL]) { 165 | [self decrementActivityCount]; 166 | } 167 | } 168 | 169 | @end 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFHTTPRequestOperation.m: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperation.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFHTTPRequestOperation.h" 24 | 25 | static dispatch_queue_t http_request_operation_processing_queue() { 26 | static dispatch_queue_t af_http_request_operation_processing_queue; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | af_http_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.http-request.processing", DISPATCH_QUEUE_CONCURRENT); 30 | }); 31 | 32 | return af_http_request_operation_processing_queue; 33 | } 34 | 35 | static dispatch_group_t http_request_operation_completion_group() { 36 | static dispatch_group_t af_http_request_operation_completion_group; 37 | static dispatch_once_t onceToken; 38 | dispatch_once(&onceToken, ^{ 39 | af_http_request_operation_completion_group = dispatch_group_create(); 40 | }); 41 | 42 | return af_http_request_operation_completion_group; 43 | } 44 | 45 | #pragma mark - 46 | 47 | @interface AFHTTPRequestOperation () 48 | @property (readwrite, nonatomic, strong) NSURLRequest *request; 49 | @property (readwrite, nonatomic, strong) NSHTTPURLResponse *response; 50 | @property (readwrite, nonatomic, strong) id responseObject; 51 | @property (readwrite, nonatomic, strong) NSError *responseSerializationError; 52 | @property (readwrite, nonatomic, strong) NSRecursiveLock *lock; 53 | @end 54 | 55 | @implementation AFHTTPRequestOperation 56 | @dynamic lock; 57 | 58 | - (instancetype)initWithRequest:(NSURLRequest *)urlRequest { 59 | self = [super initWithRequest:urlRequest]; 60 | if (!self) { 61 | return nil; 62 | } 63 | 64 | self.responseSerializer = [AFHTTPResponseSerializer serializer]; 65 | 66 | return self; 67 | } 68 | 69 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 70 | NSParameterAssert(responseSerializer); 71 | 72 | [self.lock lock]; 73 | _responseSerializer = responseSerializer; 74 | self.responseObject = nil; 75 | self.responseSerializationError = nil; 76 | [self.lock unlock]; 77 | } 78 | 79 | - (id)responseObject { 80 | [self.lock lock]; 81 | if (!_responseObject && [self isFinished] && !self.error) { 82 | NSError *error = nil; 83 | self.responseObject = [self.responseSerializer responseObjectForResponse:self.response data:self.responseData error:&error]; 84 | if (error) { 85 | self.responseSerializationError = error; 86 | } 87 | } 88 | [self.lock unlock]; 89 | 90 | return _responseObject; 91 | } 92 | 93 | - (NSError *)error { 94 | if (_responseSerializationError) { 95 | return _responseSerializationError; 96 | } else { 97 | return [super error]; 98 | } 99 | } 100 | 101 | #pragma mark - AFHTTPRequestOperation 102 | 103 | - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 104 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 105 | { 106 | // completionBlock is manually nilled out in AFURLConnectionOperation to break the retain cycle. 107 | #pragma clang diagnostic push 108 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 109 | #pragma clang diagnostic ignored "-Wgnu" 110 | self.completionBlock = ^{ 111 | if (self.completionGroup) { 112 | dispatch_group_enter(self.completionGroup); 113 | } 114 | 115 | dispatch_async(http_request_operation_processing_queue(), ^{ 116 | if (self.error) { 117 | if (failure) { 118 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 119 | failure(self, self.error); 120 | }); 121 | } 122 | } else { 123 | id responseObject = self.responseObject; 124 | if (self.error) { 125 | if (failure) { 126 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 127 | failure(self, self.error); 128 | }); 129 | } 130 | } else { 131 | if (success) { 132 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 133 | success(self, responseObject); 134 | }); 135 | } 136 | } 137 | } 138 | 139 | if (self.completionGroup) { 140 | dispatch_group_leave(self.completionGroup); 141 | } 142 | }); 143 | }; 144 | #pragma clang diagnostic pop 145 | } 146 | 147 | #pragma mark - AFURLRequestOperation 148 | 149 | - (void)pause { 150 | int64_t offset = 0; 151 | if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) { 152 | offset = [(NSNumber *)[self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey] longLongValue]; 153 | } else { 154 | offset = [(NSData *)[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length]; 155 | } 156 | 157 | NSMutableURLRequest *mutableURLRequest = [self.request mutableCopy]; 158 | if ([self.response respondsToSelector:@selector(allHeaderFields)] && [[self.response allHeaderFields] valueForKey:@"ETag"]) { 159 | [mutableURLRequest setValue:[[self.response allHeaderFields] valueForKey:@"ETag"] forHTTPHeaderField:@"If-Range"]; 160 | } 161 | [mutableURLRequest setValue:[NSString stringWithFormat:@"bytes=%llu-", offset] forHTTPHeaderField:@"Range"]; 162 | self.request = mutableURLRequest; 163 | 164 | [super pause]; 165 | } 166 | 167 | #pragma mark - NSCoding 168 | 169 | - (id)initWithCoder:(NSCoder *)decoder { 170 | self = [super initWithCoder:decoder]; 171 | if (!self) { 172 | return nil; 173 | } 174 | 175 | self.responseSerializer = [decoder decodeObjectForKey:NSStringFromSelector(@selector(responseSerializer))]; 176 | 177 | return self; 178 | } 179 | 180 | - (void)encodeWithCoder:(NSCoder *)coder { 181 | [super encodeWithCoder:coder]; 182 | 183 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 184 | } 185 | 186 | #pragma mark - NSCopying 187 | 188 | - (id)copyWithZone:(NSZone *)zone { 189 | AFHTTPRequestOperation *operation = [[[self class] allocWithZone:zone] initWithRequest:self.request]; 190 | 191 | operation.responseSerializer = [self.responseSerializer copyWithZone:zone]; 192 | operation.completionQueue = self.completionQueue; 193 | operation.completionGroup = self.completionGroup; 194 | 195 | return operation; 196 | } 197 | 198 | @end 199 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | 32 | typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { 33 | AFNetworkReachabilityStatusUnknown = -1, 34 | AFNetworkReachabilityStatusNotReachable = 0, 35 | AFNetworkReachabilityStatusReachableViaWWAN = 1, 36 | AFNetworkReachabilityStatusReachableViaWiFi = 2, 37 | }; 38 | 39 | /** 40 | `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. 41 | 42 | See Apple's Reachability Sample Code (https://developer.apple.com/library/ios/samplecode/reachability/) 43 | */ 44 | @interface AFNetworkReachabilityManager : NSObject 45 | 46 | /** 47 | The current network reachability status. 48 | */ 49 | @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 50 | 51 | /** 52 | Whether or not the network is currently reachable. 53 | */ 54 | @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; 55 | 56 | /** 57 | Whether or not the network is currently reachable via WWAN. 58 | */ 59 | @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; 60 | 61 | /** 62 | Whether or not the network is currently reachable via WiFi. 63 | */ 64 | @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; 65 | 66 | ///--------------------- 67 | /// @name Initialization 68 | ///--------------------- 69 | 70 | /** 71 | Returns the shared network reachability manager. 72 | */ 73 | + (instancetype)sharedManager; 74 | 75 | /** 76 | Creates and returns a network reachability manager for the specified domain. 77 | 78 | @param domain The domain used to evaluate network reachability. 79 | 80 | @return An initialized network reachability manager, actively monitoring the specified domain. 81 | */ 82 | + (instancetype)managerForDomain:(NSString *)domain; 83 | 84 | /** 85 | Creates and returns a network reachability manager for the socket address. 86 | 87 | @param address The socket address used to evaluate network reachability. 88 | 89 | @return An initialized network reachability manager, actively monitoring the specified socket address. 90 | */ 91 | + (instancetype)managerForAddress:(const struct sockaddr_in *)address; 92 | 93 | /** 94 | Initializes an instance of a network reachability manager from the specified reachability object. 95 | 96 | @param reachability The reachability object to monitor. 97 | 98 | @return An initialized network reachability manager, actively monitoring the specified reachability. 99 | */ 100 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability; 101 | 102 | ///-------------------------------------------------- 103 | /// @name Starting & Stopping Reachability Monitoring 104 | ///-------------------------------------------------- 105 | 106 | /** 107 | Starts monitoring for changes in network reachability status. 108 | */ 109 | - (void)startMonitoring; 110 | 111 | /** 112 | Stops monitoring for changes in network reachability status. 113 | */ 114 | - (void)stopMonitoring; 115 | 116 | ///------------------------------------------------- 117 | /// @name Getting Localized Reachability Description 118 | ///------------------------------------------------- 119 | 120 | /** 121 | Returns a localized string representation of the current network reachability status. 122 | */ 123 | - (NSString *)localizedNetworkReachabilityStatusString; 124 | 125 | ///--------------------------------------------------- 126 | /// @name Setting Network Reachability Change Callback 127 | ///--------------------------------------------------- 128 | 129 | /** 130 | Sets a callback to be executed when the network availability of the `baseURL` host changes. 131 | 132 | @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. 133 | */ 134 | - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block; 135 | 136 | @end 137 | 138 | ///---------------- 139 | /// @name Constants 140 | ///---------------- 141 | 142 | /** 143 | ## Network Reachability 144 | 145 | The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. 146 | 147 | enum { 148 | AFNetworkReachabilityStatusUnknown, 149 | AFNetworkReachabilityStatusNotReachable, 150 | AFNetworkReachabilityStatusReachableViaWWAN, 151 | AFNetworkReachabilityStatusReachableViaWiFi, 152 | } 153 | 154 | `AFNetworkReachabilityStatusUnknown` 155 | The `baseURL` host reachability is not known. 156 | 157 | `AFNetworkReachabilityStatusNotReachable` 158 | The `baseURL` host cannot be reached. 159 | 160 | `AFNetworkReachabilityStatusReachableViaWWAN` 161 | The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. 162 | 163 | `AFNetworkReachabilityStatusReachableViaWiFi` 164 | The `baseURL` host can be reached via a Wi-Fi connection. 165 | 166 | ### Keys for Notification UserInfo Dictionary 167 | 168 | Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. 169 | 170 | `AFNetworkingReachabilityNotificationStatusItem` 171 | A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. 172 | The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. 173 | */ 174 | 175 | ///-------------------- 176 | /// @name Notifications 177 | ///-------------------- 178 | 179 | /** 180 | Posted when network reachability changes. 181 | This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. 182 | 183 | @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). 184 | */ 185 | extern NSString * const AFNetworkingReachabilityDidChangeNotification; 186 | extern NSString * const AFNetworkingReachabilityNotificationStatusItem; 187 | 188 | ///-------------------- 189 | /// @name Functions 190 | ///-------------------- 191 | 192 | /** 193 | Returns a localized string representation of an `AFNetworkReachabilityStatus` value. 194 | */ 195 | extern NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 196 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # IDMPhotoBrowser ![](http://cocoapod-badges.herokuapp.com/v/IDMPhotoBrowser/badge.png) ![](http://cocoapod-badges.herokuapp.com/p/IDMPhotoBrowser/badge.png) 2 | 3 | IDMPhotoBrowser is a new implementation based on [MWPhotoBrowser](https://github.com/mwaterfall/MWPhotoBrowser). 4 | 5 | We've added both user experience and technical features inspired by Facebook's and Tweetbot's photo browsers. 6 | 7 | ## New features: 8 | - Uses ARC 9 | - Uses AFNetworking for image loading 10 | - Image progress shown 11 | - Minimalistic Facebook-like interface, swipe up/down to dismiss 12 | - Ability to add custom actions on the action sheet 13 | 14 | ## Features 15 | 16 | - Can display one or more images by providing either `UIImage` objects, file paths to images on the device, or URLs to images online 17 | - Handles the downloading and caching of photos from the web seamlessly 18 | - Photos can be zoomed and panned, and optional captions can be displayed 19 | 20 | ## Screenshots 21 | 22 | [![Alt][screenshot1_thumb]][screenshot1] [![Alt][screenshot2_thumb]][screenshot2] [![Alt][screenshot3_thumb]][screenshot3] [![Alt][screenshot4_thumb]][screenshot4] [![Alt][screenshot5_thumb]][screenshot5] 23 | [screenshot1_thumb]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb1.png 24 | [screenshot1]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss1.png 25 | [screenshot2_thumb]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb2.png 26 | [screenshot2]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss2.png 27 | [screenshot3_thumb]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb3.png 28 | [screenshot3]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss3.png 29 | [screenshot4_thumb]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb4.png 30 | [screenshot4]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss4.png 31 | [screenshot5_thumb]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_thumb5.png 32 | [screenshot5]: https://raw.github.com/appkraft/IDMPhotoBrowser/master/Screenshots/idmphotobrowser_ss5.png 33 | 34 | ## Usage 35 | 36 | See the code snippet below for an example of how to implement the photo browser. 37 | 38 | First create a photos array containing IDMPhoto objects: 39 | 40 | ``` objective-c 41 | // URLs array 42 | NSArray *photosURL = @[[NSURL URLWithString:@"http://farm4.static.flickr.com/3567/3523321514_371d9ac42f_b.jpg"], 43 | [NSURL URLWithString:@"http://farm4.static.flickr.com/3629/3339128908_7aecabc34b_b.jpg"], 44 | [NSURL URLWithString:@"http://farm4.static.flickr.com/3364/3338617424_7ff836d55f_b.jpg"], 45 | [NSURL URLWithString:@"http://farm4.static.flickr.com/3590/3329114220_5fbc5bc92b_b.jpg"]]; 46 | 47 | // Create an array to store IDMPhoto objects 48 | NSMutableArray *photos = [NSMutableArray new]; 49 | 50 | for (NSURL *url in photosURL) { 51 | IDMPhoto *photo = [IDMPhoto photoWithURL:url]; 52 | [photos addObject:photo]; 53 | } 54 | 55 | // Or use this constructor to receive an NSArray of IDMPhoto objects from your NSURL objects 56 | NSArray *photos = [IDMPhoto photosWithURLs:photosURL]; 57 | ```` 58 | 59 | There are two main ways to presente the photoBrowser, with a fade on screen or with a zooming effect from an existing view. 60 | 61 | Using a simple fade transition: 62 | 63 | ``` objective-c 64 | IDMPhotoBrowser *browser = [[IDMPhotoBrowser alloc] initWithPhotos:photos]; 65 | ``` 66 | 67 | Zooming effect from a view: 68 | 69 | ``` objective-c 70 | IDMPhotoBrowser *browser = [[IDMPhotoBrowser alloc] initWithPhotos:photos animatedFromView:sender]; 71 | ``` 72 | 73 | When using this animation you can set the `scaleImage` property, in case the image from the view is not the same as the one that will be shown on the browser, so it will dynamically scale it: 74 | 75 | ``` objective-c 76 | browser.scaleImage = buttonSender.currentImage; 77 | ``` 78 | 79 | Presenting using a modal view controller: 80 | 81 | ``` objective-c 82 | [self presentViewController:browser animated:YES completion:nil]; 83 | ``` 84 | 85 | ### Customization 86 | 87 | ##### Toolbar 88 | 89 | You can customize the toolbar. There are three boolean properties you can set: displayActionButton (default is YES), displayArrowButton (default is YES) and displayCounterLabel (default is NO). If you dont want the toolbar at all, you can set displayToolbar = NO. 90 | 91 | Toolbar setup example: 92 | ``` objective-c 93 | browser.displayActionButton = NO; 94 | browser.displayArrowButton = YES; 95 | browser.displayCounterLabel = YES; 96 | ``` 97 | 98 | It is possible to use your own image on the toolbar arrows: 99 | ``` objective-c 100 | browser.leftArrowImage = [UIImage imageNamed:@"IDMPhotoBrowser_customArrowLeft.png"]; 101 | browser.rightArrowImage = [UIImage imageNamed:@"IDMPhotoBrowser_customArrowRight.png"]; 102 | browser.leftArrowSelectedImage = [UIImage imageNamed:@"IDMPhotoBrowser_customArrowLeftSelected.png"]; 103 | browser.rightArrowSelectedImage = [UIImage imageNamed:@"IDMPhotoBrowser_customArrowRightSelected.png"]; 104 | ``` 105 | 106 | If you want to use custom actions, set the actionButtonTitles array with the titles for the actionSheet. Then, implement the photoBrowser:didDismissActionSheetWithButtonIndex:photoIndex: method, from the IDMPhotoBrowser delegate 107 | 108 | ``` objective-c 109 | browser.actionButtonTitles = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4"]; 110 | ``` 111 | 112 | #### Others 113 | 114 | Others customizations you can make are: use white background color, don't display the done button and change the done button background image: 115 | 116 | ``` objective-c 117 | browser.useWhiteBackgroundColor = YES; 118 | browser.displayDoneButton = NO; 119 | browser.doneBackgroundImage = [UIImage imageNamed:@"IDMPhotoBrowser_customDoneButton.png"]; 120 | ``` 121 | 122 | ### Photo Captions 123 | 124 | Photo captions can be displayed simply by setting the `caption` property on specific photos: 125 | ``` objective-c 126 | IDMPhoto *photo = [IDMPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:@"photo2l" ofType:@"jpg"]]; 127 | photo.caption = @"Campervan"; 128 | ``` 129 | 130 | No caption will be displayed if the caption property is not set. 131 | 132 | #### Custom Captions 133 | 134 | By default, the caption is a simple black transparent view with a label displaying the photo's caption in white. If you want to implement your own caption view, follow these steps: 135 | 136 | 1. Optionally use a subclass of `IDMPhoto` for your photos so you can store more data than a simple caption string. 137 | 2. Subclass `IDMCaptionView` and override `-setupCaption` and `-sizeThatFits:` (and any other UIView methods you see fit) to layout your own view and set it's size. More information on this can be found in `IDMCaptionView.h` 138 | 3. Implement the `-photoBrowser:captionViewForPhotoAtIndex:` IDMPhotoBrowser delegate method (shown below). 139 | 140 | Example delegate method for custom caption view: 141 | ``` objective-c 142 | - (IDMCaptionView *)photoBrowser:(IDMPhotoBrowser *)photoBrowser captionViewForPhotoAtIndex:(NSUInteger)index { 143 | IDMPhoto *photo = [self.photos objectAtIndex:index]; 144 | MyIDMCaptionViewSubclass *captionView = [[MyIDMCaptionViewSubclass alloc] initWithPhoto:photo]; 145 | return captionView; 146 | } 147 | ``` 148 | 149 | ## Adding to your project 150 | 151 | ### Using CocoaPods 152 | 153 | Just add `pod 'IDMPhotoBrowser'` to your Podfile. 154 | 155 | ### Including Source Directly Into Your Project 156 | 157 | Simply add the files inside `IDMPhotoBrowser/Classes` to your Xcode project, copying them to your project's directory if required. And also any library inside `IDMPhotoBrowser/ExternalLibraries` needed. 158 | 159 | ### Opensource libraries used 160 | 161 | - [AFNetWorking](https://github.com/AFNetworking/AFNetworking) 162 | - [DACircularProgress](https://github.com/danielamitay/DACircularProgress) 163 | - [SVProgressHUD](https://github.com/samvermette/SVProgressHUD) 164 | 165 | ## Licence 166 | 167 | This project uses MIT License. 168 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DACircularProgress/DACircularProgressView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DACircularProgressView.m 3 | // DACircularProgress 4 | // 5 | // Created by Daniel Amitay on 2/6/12. 6 | // Copyright (c) 2012 Daniel Amitay. All rights reserved. 7 | // 8 | 9 | #import "DACircularProgressView.h" 10 | 11 | #import 12 | 13 | @interface DACircularProgressLayer : CALayer 14 | 15 | @property(nonatomic, strong) UIColor *trackTintColor; 16 | @property(nonatomic, strong) UIColor *progressTintColor; 17 | @property(nonatomic) NSInteger roundedCorners; 18 | @property(nonatomic) CGFloat thicknessRatio; 19 | @property(nonatomic) CGFloat progress; 20 | 21 | @end 22 | 23 | @implementation DACircularProgressLayer 24 | 25 | @dynamic trackTintColor; 26 | @dynamic progressTintColor; 27 | @dynamic roundedCorners; 28 | @dynamic thicknessRatio; 29 | @dynamic progress; 30 | 31 | + (BOOL)needsDisplayForKey:(NSString *)key 32 | { 33 | return [key isEqualToString:@"progress"] ? YES : [super needsDisplayForKey:key]; 34 | } 35 | 36 | - (void)drawInContext:(CGContextRef)context 37 | { 38 | CGRect rect = self.bounds; 39 | CGPoint centerPoint = CGPointMake(rect.size.height / 2, rect.size.width / 2); 40 | CGFloat radius = MIN(rect.size.height, rect.size.width) / 2; 41 | 42 | CGFloat progress = MIN(self.progress, 1.f - FLT_EPSILON); 43 | CGFloat radians = (progress * 2 * M_PI) - M_PI_2; 44 | 45 | CGContextSetFillColorWithColor(context, self.trackTintColor.CGColor); 46 | CGMutablePathRef trackPath = CGPathCreateMutable(); 47 | CGPathMoveToPoint(trackPath, NULL, centerPoint.x, centerPoint.y); 48 | CGPathAddArc(trackPath, NULL, centerPoint.x, centerPoint.y, radius, 3 * M_PI_2, -M_PI_2, NO); 49 | CGPathCloseSubpath(trackPath); 50 | CGContextAddPath(context, trackPath); 51 | CGContextFillPath(context); 52 | CGPathRelease(trackPath); 53 | 54 | if (progress > 0.f) 55 | { 56 | CGContextSetFillColorWithColor(context, self.progressTintColor.CGColor); 57 | CGMutablePathRef progressPath = CGPathCreateMutable(); 58 | CGPathMoveToPoint(progressPath, NULL, centerPoint.x, centerPoint.y); 59 | CGPathAddArc(progressPath, NULL, centerPoint.x, centerPoint.y, radius, 3 * M_PI_2, radians, NO); 60 | CGPathCloseSubpath(progressPath); 61 | CGContextAddPath(context, progressPath); 62 | CGContextFillPath(context); 63 | CGPathRelease(progressPath); 64 | } 65 | 66 | if (progress > 0.f && self.roundedCorners) 67 | { 68 | CGFloat pathWidth = radius * self.thicknessRatio; 69 | CGFloat xOffset = radius * (1.f + ((1 - (self.thicknessRatio / 2.f)) * cosf(radians))); 70 | CGFloat yOffset = radius * (1.f + ((1 - (self.thicknessRatio / 2.f)) * sinf(radians))); 71 | CGPoint endPoint = CGPointMake(xOffset, yOffset); 72 | 73 | CGContextAddEllipseInRect(context, CGRectMake(centerPoint.x - pathWidth / 2, 0, pathWidth, pathWidth)); 74 | CGContextFillPath(context); 75 | 76 | CGContextAddEllipseInRect(context, CGRectMake(endPoint.x - pathWidth / 2, endPoint.y - pathWidth / 2, pathWidth, pathWidth)); 77 | CGContextFillPath(context); 78 | } 79 | 80 | CGContextSetBlendMode(context, kCGBlendModeClear); 81 | CGFloat innerRadius = radius * (1.f - self.thicknessRatio); 82 | CGPoint newCenterPoint = CGPointMake(centerPoint.x - innerRadius, centerPoint.y - innerRadius); 83 | CGContextAddEllipseInRect(context, CGRectMake(newCenterPoint.x, newCenterPoint.y, innerRadius * 2, innerRadius * 2)); 84 | CGContextFillPath(context); 85 | } 86 | 87 | @end 88 | 89 | @implementation DACircularProgressView 90 | 91 | + (void) initialize 92 | { 93 | if (self != [DACircularProgressView class]) 94 | return; 95 | 96 | id appearance = [self appearance]; 97 | [appearance setTrackTintColor:[[UIColor whiteColor] colorWithAlphaComponent:0.3f]]; 98 | [appearance setProgressTintColor:[UIColor whiteColor]]; 99 | [appearance setThicknessRatio:0.3f]; 100 | [appearance setRoundedCorners:NO]; 101 | 102 | [appearance setIndeterminateDuration:2.0f]; 103 | [appearance setIndeterminate:NO]; 104 | } 105 | 106 | + (Class)layerClass 107 | { 108 | return [DACircularProgressLayer class]; 109 | } 110 | 111 | - (DACircularProgressLayer *)circularProgressLayer 112 | { 113 | return (DACircularProgressLayer *)self.layer; 114 | } 115 | 116 | - (id)init 117 | { 118 | return [self initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)]; 119 | } 120 | 121 | - (id)initWithFrame:(CGRect)frame 122 | { 123 | self = [super initWithFrame:frame]; 124 | if (self) 125 | { 126 | self.backgroundColor = [UIColor clearColor]; 127 | } 128 | return self; 129 | } 130 | 131 | - (void)didMoveToWindow 132 | { 133 | self.circularProgressLayer.contentsScale = [UIScreen mainScreen].scale; 134 | } 135 | 136 | #pragma mark - Progress 137 | 138 | -(CGFloat)progress 139 | { 140 | return self.circularProgressLayer.progress; 141 | } 142 | 143 | - (void)setProgress:(CGFloat)progress 144 | { 145 | [self setProgress:progress animated:NO]; 146 | } 147 | 148 | - (void)setProgress:(CGFloat)progress animated:(BOOL)animated 149 | { 150 | CGFloat pinnedProgress = MIN(MAX(progress, 0.f), 1.f); 151 | if (animated) 152 | { 153 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"progress"]; 154 | animation.duration = fabsf(self.progress - pinnedProgress); // Same duration as UIProgressView animation 155 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 156 | animation.fromValue = [NSNumber numberWithFloat:self.progress]; 157 | animation.toValue = [NSNumber numberWithFloat:pinnedProgress]; 158 | [self.circularProgressLayer addAnimation:animation forKey:@"progress"]; 159 | } 160 | else 161 | { 162 | [self.circularProgressLayer setNeedsDisplay]; 163 | } 164 | self.circularProgressLayer.progress = pinnedProgress; 165 | } 166 | 167 | #pragma mark - UIAppearance methods 168 | 169 | - (UIColor *)trackTintColor 170 | { 171 | return self.circularProgressLayer.trackTintColor; 172 | } 173 | 174 | - (void)setTrackTintColor:(UIColor *)trackTintColor 175 | { 176 | self.circularProgressLayer.trackTintColor = trackTintColor; 177 | [self.circularProgressLayer setNeedsDisplay]; 178 | } 179 | 180 | - (UIColor *)progressTintColor 181 | { 182 | return self.circularProgressLayer.progressTintColor; 183 | } 184 | 185 | - (void)setProgressTintColor:(UIColor *)progressTintColor 186 | { 187 | self.circularProgressLayer.progressTintColor = progressTintColor; 188 | [self.circularProgressLayer setNeedsDisplay]; 189 | } 190 | 191 | - (NSInteger)roundedCorners 192 | { 193 | return self.roundedCorners; 194 | } 195 | 196 | -(void)setRoundedCorners:(NSInteger)roundedCorners 197 | { 198 | self.circularProgressLayer.roundedCorners = roundedCorners; 199 | [self.circularProgressLayer setNeedsDisplay]; 200 | } 201 | 202 | -(CGFloat)thicknessRatio 203 | { 204 | return self.circularProgressLayer.thicknessRatio; 205 | } 206 | 207 | - (void)setThicknessRatio:(CGFloat)thicknessRatio 208 | { 209 | self.circularProgressLayer.thicknessRatio = MIN(MAX(thicknessRatio, 0.f), 1.f); 210 | [self.circularProgressLayer setNeedsDisplay]; 211 | } 212 | 213 | - (NSInteger)indeterminate 214 | { 215 | CAAnimation *spinAnimation = [self.layer animationForKey:@"indeterminateAnimation"]; 216 | return spinAnimation == nil ? 0 : 1; 217 | } 218 | 219 | - (void)setIndeterminate:(NSInteger)indeterminate 220 | { 221 | if (indeterminate && !self.indeterminate) 222 | { 223 | CABasicAnimation *spinAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 224 | spinAnimation.byValue = [NSNumber numberWithFloat:2.0f*M_PI]; 225 | spinAnimation.duration = self.indeterminateDuration; 226 | spinAnimation.repeatCount = HUGE_VALF; 227 | [self.layer addAnimation:spinAnimation forKey:@"indeterminateAnimation"]; 228 | } 229 | else 230 | { 231 | [self.layer removeAnimationForKey:@"indeterminateAnimation"]; 232 | } 233 | } 234 | 235 | @end 236 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIImageView+AFNetworking.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIImageView+AFNetworking.h" 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import "AFHTTPRequestOperation.h" 30 | 31 | @interface AFImageCache : NSCache 32 | - (UIImage *)cachedImageForRequest:(NSURLRequest *)request; 33 | - (void)cacheImage:(UIImage *)image 34 | forRequest:(NSURLRequest *)request; 35 | @end 36 | 37 | #pragma mark - 38 | 39 | static char kAFImageRequestOperationKey; 40 | static char kAFResponseSerializerKey; 41 | 42 | @interface UIImageView (_AFNetworking) 43 | @property (readwrite, nonatomic, strong, setter = af_setImageRequestOperation:) AFHTTPRequestOperation *af_imageRequestOperation; 44 | @end 45 | 46 | @implementation UIImageView (_AFNetworking) 47 | 48 | + (NSOperationQueue *)af_sharedImageRequestOperationQueue { 49 | static NSOperationQueue *_af_sharedImageRequestOperationQueue = nil; 50 | static dispatch_once_t onceToken; 51 | dispatch_once(&onceToken, ^{ 52 | _af_sharedImageRequestOperationQueue = [[NSOperationQueue alloc] init]; 53 | _af_sharedImageRequestOperationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount; 54 | }); 55 | 56 | return _af_sharedImageRequestOperationQueue; 57 | } 58 | 59 | + (AFImageCache *)af_sharedImageCache { 60 | static AFImageCache *_af_imageCache = nil; 61 | static dispatch_once_t oncePredicate; 62 | dispatch_once(&oncePredicate, ^{ 63 | _af_imageCache = [[AFImageCache alloc] init]; 64 | 65 | [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * __unused notification) { 66 | [_af_imageCache removeAllObjects]; 67 | }]; 68 | }); 69 | 70 | return _af_imageCache; 71 | } 72 | 73 | - (AFHTTPRequestOperation *)af_imageRequestOperation { 74 | return (AFHTTPRequestOperation *)objc_getAssociatedObject(self, &kAFImageRequestOperationKey); 75 | } 76 | 77 | - (void)af_setImageRequestOperation:(AFHTTPRequestOperation *)imageRequestOperation { 78 | objc_setAssociatedObject(self, &kAFImageRequestOperationKey, imageRequestOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 79 | } 80 | 81 | @end 82 | 83 | #pragma mark - 84 | 85 | @implementation UIImageView (AFNetworking) 86 | @dynamic imageResponseSerializer; 87 | 88 | - (id )imageResponseSerializer { 89 | static id _af_defaultImageResponseSerializer = nil; 90 | static dispatch_once_t onceToken; 91 | dispatch_once(&onceToken, ^{ 92 | _af_defaultImageResponseSerializer = [AFImageResponseSerializer serializer]; 93 | }); 94 | 95 | #pragma clang diagnostic push 96 | #pragma clang diagnostic ignored "-Wgnu" 97 | return objc_getAssociatedObject(self, &kAFResponseSerializerKey) ?: _af_defaultImageResponseSerializer; 98 | #pragma clang diagnostic pop 99 | } 100 | 101 | - (void)setImageResponseSerializer:(id )serializer { 102 | objc_setAssociatedObject(self, &kAFResponseSerializerKey, serializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 103 | } 104 | 105 | #pragma mark - 106 | 107 | - (void)setImageWithURL:(NSURL *)url { 108 | [self setImageWithURL:url placeholderImage:nil]; 109 | } 110 | 111 | - (void)setImageWithURL:(NSURL *)url 112 | placeholderImage:(UIImage *)placeholderImage 113 | { 114 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 115 | [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; 116 | 117 | [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; 118 | } 119 | 120 | - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest 121 | placeholderImage:(UIImage *)placeholderImage 122 | success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success 123 | failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure 124 | { 125 | [self cancelImageRequestOperation]; 126 | 127 | UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForRequest:urlRequest]; 128 | if (cachedImage) { 129 | if (success) { 130 | success(nil, nil, cachedImage); 131 | } else { 132 | self.image = cachedImage; 133 | } 134 | 135 | self.af_imageRequestOperation = nil; 136 | } else { 137 | self.image = placeholderImage; 138 | 139 | __weak __typeof(self)weakSelf = self; 140 | self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; 141 | self.af_imageRequestOperation.responseSerializer = self.imageResponseSerializer; 142 | [self.af_imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 143 | __strong __typeof(weakSelf)strongSelf = weakSelf; 144 | if ([[urlRequest URL] isEqual:[operation.request URL]]) { 145 | if (success) { 146 | success(urlRequest, operation.response, responseObject); 147 | } else if (responseObject) { 148 | strongSelf.image = responseObject; 149 | } 150 | } else { 151 | 152 | } 153 | 154 | [[[strongSelf class] af_sharedImageCache] cacheImage:responseObject forRequest:urlRequest]; 155 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 156 | if ([[urlRequest URL] isEqual:[operation.request URL]]) { 157 | if (failure) { 158 | failure(urlRequest, operation.response, error); 159 | } 160 | } 161 | }]; 162 | 163 | [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_imageRequestOperation]; 164 | } 165 | } 166 | 167 | - (void)cancelImageRequestOperation { 168 | [self.af_imageRequestOperation cancel]; 169 | self.af_imageRequestOperation = nil; 170 | } 171 | 172 | @end 173 | 174 | #pragma mark - 175 | 176 | static inline NSString * AFImageCacheKeyFromURLRequest(NSURLRequest *request) { 177 | return [[request URL] absoluteString]; 178 | } 179 | 180 | @implementation AFImageCache 181 | 182 | - (UIImage *)cachedImageForRequest:(NSURLRequest *)request { 183 | switch ([request cachePolicy]) { 184 | case NSURLRequestReloadIgnoringCacheData: 185 | case NSURLRequestReloadIgnoringLocalAndRemoteCacheData: 186 | return nil; 187 | default: 188 | break; 189 | } 190 | 191 | return [self objectForKey:AFImageCacheKeyFromURLRequest(request)]; 192 | } 193 | 194 | - (void)cacheImage:(UIImage *)image 195 | forRequest:(NSURLRequest *)request 196 | { 197 | if (image && request) { 198 | [self setObject:image forKey:AFImageCacheKeyFromURLRequest(request)]; 199 | } 200 | } 201 | 202 | @end 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIButton+AFNetworking.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIButton+AFNetworking.h" 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import "AFHTTPRequestOperation.h" 30 | 31 | static char kAFImageRequestOperationKey; 32 | static char kAFBackgroundImageRequestOperationKey; 33 | 34 | @interface UIButton (_AFNetworking) 35 | @property (readwrite, nonatomic, strong, setter = af_setImageRequestOperation:) AFHTTPRequestOperation *af_imageRequestOperation; 36 | @property (readwrite, nonatomic, strong, setter = af_setBackgroundImageRequestOperation:) AFHTTPRequestOperation *af_backgroundImageRequestOperation; 37 | @end 38 | 39 | @implementation UIButton (_AFNetworking) 40 | 41 | + (NSOperationQueue *)af_sharedImageRequestOperationQueue { 42 | static NSOperationQueue *_af_sharedImageRequestOperationQueue = nil; 43 | static dispatch_once_t onceToken; 44 | dispatch_once(&onceToken, ^{ 45 | _af_sharedImageRequestOperationQueue = [[NSOperationQueue alloc] init]; 46 | _af_sharedImageRequestOperationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount; 47 | }); 48 | 49 | return _af_sharedImageRequestOperationQueue; 50 | } 51 | 52 | - (AFHTTPRequestOperation *)af_imageRequestOperation { 53 | return (AFHTTPRequestOperation *)objc_getAssociatedObject(self, &kAFImageRequestOperationKey); 54 | } 55 | 56 | - (void)af_setImageRequestOperation:(AFHTTPRequestOperation *)imageRequestOperation { 57 | objc_setAssociatedObject(self, &kAFImageRequestOperationKey, imageRequestOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 58 | } 59 | 60 | - (AFHTTPRequestOperation *)af_backgroundImageRequestOperation { 61 | return (AFHTTPRequestOperation *)objc_getAssociatedObject(self, &kAFBackgroundImageRequestOperationKey); 62 | } 63 | 64 | - (void)af_setBackgroundImageRequestOperation:(AFHTTPRequestOperation *)imageRequestOperation { 65 | objc_setAssociatedObject(self, &kAFBackgroundImageRequestOperationKey, imageRequestOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 66 | } 67 | 68 | @end 69 | 70 | #pragma mark - 71 | 72 | @implementation UIButton (AFNetworking) 73 | 74 | - (void)setImageForState:(UIControlState)state 75 | withURL:(NSURL *)url 76 | { 77 | [self setImageForState:state withURL:url placeholderImage:nil]; 78 | } 79 | 80 | - (void)setImageForState:(UIControlState)state 81 | withURL:(NSURL *)url 82 | placeholderImage:(UIImage *)placeholderImage 83 | { 84 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 85 | [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; 86 | 87 | [self setImageForState:state withURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; 88 | } 89 | 90 | - (void)setImageForState:(UIControlState)state 91 | withURLRequest:(NSURLRequest *)urlRequest 92 | placeholderImage:(UIImage *)placeholderImage 93 | success:(void (^)(NSHTTPURLResponse *response, UIImage *image))success 94 | failure:(void (^)(NSError *error))failure 95 | { 96 | [self cancelImageRequestOperation]; 97 | 98 | [self setImage:placeholderImage forState:state]; 99 | 100 | __weak __typeof(self)weakSelf = self; 101 | self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; 102 | self.af_imageRequestOperation.responseSerializer = [AFImageResponseSerializer serializer]; 103 | [self.af_imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 104 | __strong __typeof(weakSelf)strongSelf = weakSelf; 105 | if ([[urlRequest URL] isEqual:[operation.request URL]]) { 106 | if (success) { 107 | success(operation.response, responseObject); 108 | } else if (responseObject) { 109 | [strongSelf setImage:responseObject forState:state]; 110 | } 111 | } else { 112 | 113 | } 114 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 115 | if ([[urlRequest URL] isEqual:[operation.response URL]]) { 116 | if (failure) { 117 | failure(error); 118 | } 119 | } 120 | }]; 121 | 122 | [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_imageRequestOperation]; 123 | } 124 | 125 | #pragma mark - 126 | 127 | - (void)setBackgroundImageForState:(UIControlState)state 128 | withURL:(NSURL *)url 129 | { 130 | [self setBackgroundImageForState:state withURL:url placeholderImage:nil]; 131 | } 132 | 133 | - (void)setBackgroundImageForState:(UIControlState)state 134 | withURL:(NSURL *)url 135 | placeholderImage:(UIImage *)placeholderImage 136 | { 137 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 138 | [request addValue:@"image/*" forHTTPHeaderField:@"Accept"]; 139 | 140 | [self setBackgroundImageForState:state withURLRequest:request placeholderImage:placeholderImage success:nil failure:nil]; 141 | } 142 | 143 | - (void)setBackgroundImageForState:(UIControlState)state 144 | withURLRequest:(NSURLRequest *)urlRequest 145 | placeholderImage:(UIImage *)placeholderImage 146 | success:(void (^)(NSHTTPURLResponse *response, UIImage *image))success 147 | failure:(void (^)(NSError *error))failure 148 | { 149 | [self cancelBackgroundImageRequestOperation]; 150 | 151 | [self setBackgroundImage:placeholderImage forState:state]; 152 | 153 | __weak __typeof(self)weakSelf = self; 154 | self.af_backgroundImageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; 155 | self.af_backgroundImageRequestOperation.responseSerializer = [AFImageResponseSerializer serializer]; 156 | [self.af_backgroundImageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 157 | __strong __typeof(weakSelf)strongSelf = weakSelf; 158 | if ([[urlRequest URL] isEqual:[operation.request URL]]) { 159 | if (success) { 160 | success(operation.response, responseObject); 161 | } else if (responseObject) { 162 | [strongSelf setBackgroundImage:responseObject forState:state]; 163 | } 164 | } else { 165 | 166 | } 167 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 168 | if ([[urlRequest URL] isEqual:[operation.response URL]]) { 169 | if (failure) { 170 | failure(error); 171 | } 172 | } 173 | }]; 174 | 175 | [[[self class] af_sharedImageRequestOperationQueue] addOperation:self.af_backgroundImageRequestOperation]; 176 | } 177 | 178 | #pragma mark - 179 | 180 | - (void)cancelImageRequestOperation { 181 | [self.af_imageRequestOperation cancel]; 182 | self.af_imageRequestOperation = nil; 183 | } 184 | 185 | - (void)cancelBackgroundImageRequestOperation { 186 | [self.af_backgroundImageRequestOperation cancel]; 187 | self.af_backgroundImageRequestOperation = nil; 188 | } 189 | 190 | @end 191 | 192 | #endif 193 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIButton+AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import 30 | 31 | /** 32 | This category adds methods to the UIKit framework's `UIButton` class. The methods in this category provide support for loading remote images and background images asynchronously from a URL. 33 | */ 34 | @interface UIButton (AFNetworking) 35 | 36 | ///-------------------- 37 | /// @name Setting Image 38 | ///-------------------- 39 | 40 | /** 41 | Asynchronously downloads an image from the specified URL, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. 42 | 43 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 44 | 45 | @param state The control state. 46 | @param url The URL used for the image request. 47 | */ 48 | - (void)setImageForState:(UIControlState)state 49 | withURL:(NSURL *)url; 50 | 51 | /** 52 | Asynchronously downloads an image from the specified URL, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. 53 | 54 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 55 | 56 | @param state The control state. 57 | @param url The URL used for the image request. 58 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. 59 | */ 60 | - (void)setImageForState:(UIControlState)state 61 | withURL:(NSURL *)url 62 | placeholderImage:(UIImage *)placeholderImage; 63 | 64 | /** 65 | Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. 66 | 67 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 68 | 69 | If a success block is specified, it is the responsibility of the block to set the image of the button before returning. If no success block is specified, the default behavior of setting the image with `setImage:forState:` is applied. 70 | 71 | @param state The control state. 72 | @param urlRequest The URL request used for the image request. 73 | @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. 74 | @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the request and response parameters will be `nil`. 75 | @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes a single argument: the error that occurred. 76 | */ 77 | - (void)setImageForState:(UIControlState)state 78 | withURLRequest:(NSURLRequest *)urlRequest 79 | placeholderImage:(UIImage *)placeholderImage 80 | success:(void (^)(NSHTTPURLResponse *response, UIImage *image))success 81 | failure:(void (^)(NSError *error))failure; 82 | 83 | 84 | ///------------------------------- 85 | /// @name Setting Background Image 86 | ///------------------------------- 87 | 88 | /** 89 | Asynchronously downloads an image from the specified URL, and sets it as the background image for the specified state once the request is finished. Any previous background image request for the receiver will be cancelled. 90 | 91 | If the background image is cached locally, the background image is set immediately, otherwise the specified placeholder background image will be set immediately, and then the remote background image will be set once the request is finished. 92 | 93 | @param state The control state. 94 | @param url The URL used for the background image request. 95 | */ 96 | - (void)setBackgroundImageForState:(UIControlState)state 97 | withURL:(NSURL *)url; 98 | 99 | /** 100 | Asynchronously downloads an image from the specified URL, and sets it as the background image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. 101 | 102 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 103 | 104 | @param state The control state. 105 | @param url The URL used for the background image request. 106 | @param placeholderImage The background image to be set initially, until the background image request finishes. If `nil`, the button will not change its background image until the background image request finishes. 107 | */ 108 | - (void)setBackgroundImageForState:(UIControlState)state 109 | withURL:(NSURL *)url 110 | placeholderImage:(UIImage *)placeholderImage; 111 | 112 | /** 113 | Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. 114 | 115 | If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. 116 | 117 | If a success block is specified, it is the responsibility of the block to set the image of the button before returning. If no success block is specified, the default behavior of setting the image with `setBackgroundImage:forState:` is applied. 118 | 119 | @param state The control state. 120 | @param urlRequest The URL request used for the image request. 121 | @param placeholderImage The background image to be set initially, until the background image request finishes. If `nil`, the button will not change its background image until the background image request finishes. 122 | */ 123 | - (void)setBackgroundImageForState:(UIControlState)state 124 | withURLRequest:(NSURLRequest *)urlRequest 125 | placeholderImage:(UIImage *)placeholderImage 126 | success:(void (^)(NSHTTPURLResponse *response, UIImage *image))success 127 | failure:(void (^)(NSError *error))failure; 128 | 129 | 130 | ///------------------------------ 131 | /// @name Canceling Image Loading 132 | ///------------------------------ 133 | 134 | /** 135 | Cancels any executing image operation for the receiver, if one exists. 136 | */ 137 | - (void)cancelImageRequestOperation; 138 | 139 | /** 140 | Cancels any executing background image operation for the receiver, if one exists. 141 | */ 142 | - (void)cancelBackgroundImageRequestOperation; 143 | 144 | @end 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.m: -------------------------------------------------------------------------------- 1 | // UIProgressView+AFNetworking.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "UIProgressView+AFNetworking.h" 24 | 25 | #import 26 | 27 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | 29 | #import "AFURLConnectionOperation.h" 30 | 31 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 32 | #import "AFURLSessionManager.h" 33 | #endif 34 | 35 | static void * AFTaskCountOfBytesSentContext = &AFTaskCountOfBytesSentContext; 36 | static void * AFTaskCountOfBytesReceivedContext = &AFTaskCountOfBytesReceivedContext; 37 | 38 | static char kAFUploadProgressAnimated; 39 | static char kAFDownloadProgressAnimated; 40 | 41 | @interface AFURLConnectionOperation (_UIProgressView) 42 | @property (readwrite, nonatomic, copy) void (^uploadProgress)(NSUInteger bytes, long long totalBytes, long long totalBytesExpected); 43 | @property (readwrite, nonatomic, assign, setter = af_setUploadProgressAnimated:) BOOL af_uploadProgressAnimated; 44 | 45 | @property (readwrite, nonatomic, copy) void (^downloadProgress)(NSUInteger bytes, long long totalBytes, long long totalBytesExpected); 46 | @property (readwrite, nonatomic, assign, setter = af_setDownloadProgressAnimated:) BOOL af_downloadProgressAnimated; 47 | @end 48 | 49 | @implementation AFURLConnectionOperation (_UIProgressView) 50 | @dynamic uploadProgress; // Implemented in AFURLConnectionOperation 51 | @dynamic af_uploadProgressAnimated; 52 | 53 | @dynamic downloadProgress; // Implemented in AFURLConnectionOperation 54 | @dynamic af_downloadProgressAnimated; 55 | @end 56 | 57 | #pragma mark - 58 | 59 | @implementation UIProgressView (AFNetworking) 60 | 61 | - (BOOL)af_uploadProgressAnimated { 62 | return [(NSNumber *)objc_getAssociatedObject(self, &kAFUploadProgressAnimated) boolValue]; 63 | } 64 | 65 | - (void)af_setUploadProgressAnimated:(BOOL)animated { 66 | objc_setAssociatedObject(self, &kAFUploadProgressAnimated, @(animated), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 67 | } 68 | 69 | - (BOOL)af_downloadProgressAnimated { 70 | return [(NSNumber *)objc_getAssociatedObject(self, &kAFDownloadProgressAnimated) boolValue]; 71 | } 72 | 73 | - (void)af_setDownloadProgressAnimated:(BOOL)animated { 74 | objc_setAssociatedObject(self, &kAFDownloadProgressAnimated, @(animated), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 75 | } 76 | 77 | #pragma mark - 78 | 79 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 80 | 81 | - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task 82 | animated:(BOOL)animated 83 | { 84 | [task addObserver:self forKeyPath:@"state" options:0 context:AFTaskCountOfBytesSentContext]; 85 | [task addObserver:self forKeyPath:@"countOfBytesSent" options:0 context:AFTaskCountOfBytesSentContext]; 86 | 87 | [self af_setUploadProgressAnimated:animated]; 88 | } 89 | 90 | - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task 91 | animated:(BOOL)animated 92 | { 93 | [task addObserver:self forKeyPath:@"state" options:0 context:AFTaskCountOfBytesReceivedContext]; 94 | [task addObserver:self forKeyPath:@"countOfBytesReceived" options:0 context:AFTaskCountOfBytesReceivedContext]; 95 | 96 | [self af_setDownloadProgressAnimated:animated]; 97 | } 98 | 99 | #endif 100 | 101 | #pragma mark - 102 | 103 | - (void)setProgressWithUploadProgressOfOperation:(AFURLConnectionOperation *)operation 104 | animated:(BOOL)animated 105 | { 106 | __weak __typeof(self)weakSelf = self; 107 | void (^original)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) = [operation.uploadProgress copy]; 108 | [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { 109 | if (original) { 110 | original(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); 111 | } 112 | 113 | dispatch_async(dispatch_get_main_queue(), ^{ 114 | if (totalBytesExpectedToWrite > 0) { 115 | [weakSelf setProgress:(totalBytesWritten / (totalBytesExpectedToWrite * 1.0f)) animated:animated]; 116 | } 117 | }); 118 | }]; 119 | } 120 | 121 | - (void)setProgressWithDownloadProgressOfOperation:(AFURLConnectionOperation *)operation 122 | animated:(BOOL)animated 123 | { 124 | __weak __typeof(self)weakSelf = self; 125 | void (^original)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) = [operation.downloadProgress copy]; 126 | [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { 127 | if (original) { 128 | original(bytesRead, totalBytesRead, totalBytesExpectedToRead); 129 | } 130 | 131 | dispatch_async(dispatch_get_main_queue(), ^{ 132 | if (totalBytesExpectedToRead > 0) { 133 | [weakSelf setProgress:(totalBytesRead / (totalBytesExpectedToRead * 1.0f)) animated:animated]; 134 | } 135 | }); 136 | }]; 137 | } 138 | 139 | #pragma mark - NSKeyValueObserving 140 | 141 | - (void)observeValueForKeyPath:(NSString *)keyPath 142 | ofObject:(id)object 143 | change:(__unused NSDictionary *)change 144 | context:(void *)context 145 | { 146 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 147 | if (context == AFTaskCountOfBytesSentContext || context == AFTaskCountOfBytesReceivedContext) { 148 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) { 149 | if ([object countOfBytesExpectedToSend] > 0) { 150 | dispatch_async(dispatch_get_main_queue(), ^{ 151 | [self setProgress:[object countOfBytesSent] / ([object countOfBytesExpectedToSend] * 1.0f) animated:self.af_uploadProgressAnimated]; 152 | }); 153 | } 154 | } 155 | 156 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) { 157 | if ([object countOfBytesExpectedToReceive] > 0) { 158 | dispatch_async(dispatch_get_main_queue(), ^{ 159 | [self setProgress:[object countOfBytesReceived] / ([object countOfBytesExpectedToReceive] * 1.0f) animated:self.af_downloadProgressAnimated]; 160 | }); 161 | } 162 | } 163 | 164 | if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) { 165 | if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) { 166 | @try { 167 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))]; 168 | 169 | if (context == AFTaskCountOfBytesSentContext) { 170 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))]; 171 | } 172 | 173 | if (context == AFTaskCountOfBytesReceivedContext) { 174 | [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))]; 175 | } 176 | } 177 | @catch (NSException * __unused exception) {} 178 | } 179 | } 180 | } 181 | #endif 182 | } 183 | 184 | @end 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFNetworkReachabilityManager.h" 24 | 25 | NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; 26 | NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; 27 | 28 | typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); 29 | 30 | NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { 31 | switch (status) { 32 | case AFNetworkReachabilityStatusNotReachable: 33 | return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil); 34 | case AFNetworkReachabilityStatusReachableViaWWAN: 35 | return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil); 36 | case AFNetworkReachabilityStatusReachableViaWiFi: 37 | return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil); 38 | case AFNetworkReachabilityStatusUnknown: 39 | default: 40 | return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil); 41 | } 42 | } 43 | 44 | static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { 45 | BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); 46 | BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); 47 | BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); 48 | BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); 49 | BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); 50 | 51 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; 52 | if (isNetworkReachable == NO) { 53 | status = AFNetworkReachabilityStatusNotReachable; 54 | } 55 | #if TARGET_OS_IPHONE 56 | else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { 57 | status = AFNetworkReachabilityStatusReachableViaWWAN; 58 | } 59 | #endif 60 | else { 61 | status = AFNetworkReachabilityStatusReachableViaWiFi; 62 | } 63 | 64 | return status; 65 | } 66 | 67 | static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { 68 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 69 | AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info; 70 | if (block) { 71 | block(status); 72 | } 73 | 74 | 75 | dispatch_async(dispatch_get_main_queue(), ^{ 76 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 77 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; 78 | }); 79 | } 80 | 81 | static const void * AFNetworkReachabilityRetainCallback(const void *info) { 82 | return Block_copy(info); 83 | } 84 | 85 | static void AFNetworkReachabilityReleaseCallback(const void *info) { 86 | if (info) { 87 | Block_release(info); 88 | } 89 | } 90 | 91 | @interface AFNetworkReachabilityManager () 92 | @property (readwrite, nonatomic, assign) SCNetworkReachabilityRef networkReachability; 93 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 94 | @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; 95 | @end 96 | 97 | @implementation AFNetworkReachabilityManager 98 | 99 | + (instancetype)sharedManager { 100 | static AFNetworkReachabilityManager *_sharedManager = nil; 101 | static dispatch_once_t onceToken; 102 | dispatch_once(&onceToken, ^{ 103 | struct sockaddr_in address; 104 | bzero(&address, sizeof(address)); 105 | address.sin_len = sizeof(address); 106 | address.sin_family = AF_INET; 107 | 108 | _sharedManager = [self managerForAddress:&address]; 109 | }); 110 | 111 | return _sharedManager; 112 | } 113 | 114 | + (instancetype)managerForDomain:(NSString *)domain { 115 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); 116 | 117 | return [[self alloc] initWithReachability:reachability]; 118 | } 119 | 120 | + (instancetype)managerForAddress:(const struct sockaddr_in *)address { 121 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); 122 | 123 | return [[self alloc] initWithReachability:reachability]; 124 | } 125 | 126 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { 127 | self = [super init]; 128 | if (!self) { 129 | return nil; 130 | } 131 | 132 | self.networkReachability = reachability; 133 | 134 | self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; 135 | 136 | return self; 137 | } 138 | 139 | - (void)dealloc { 140 | [self stopMonitoring]; 141 | 142 | CFRelease(_networkReachability); 143 | _networkReachability = NULL; 144 | } 145 | 146 | #pragma mark - 147 | 148 | - (BOOL)isReachable { 149 | return [self isReachableViaWWAN] || [self isReachableViaWiFi]; 150 | } 151 | 152 | - (BOOL)isReachableViaWWAN { 153 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; 154 | } 155 | 156 | - (BOOL)isReachableViaWiFi { 157 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; 158 | } 159 | 160 | #pragma mark - 161 | 162 | - (void)startMonitoring { 163 | [self stopMonitoring]; 164 | 165 | if (!self.networkReachability) { 166 | return; 167 | } 168 | 169 | __weak __typeof(self)weakSelf = self; 170 | AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { 171 | __strong __typeof(weakSelf)strongSelf = weakSelf; 172 | 173 | strongSelf.networkReachabilityStatus = status; 174 | if (strongSelf.networkReachabilityStatusBlock) { 175 | strongSelf.networkReachabilityStatusBlock(status); 176 | } 177 | }; 178 | 179 | SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; 180 | SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); 181 | 182 | SCNetworkReachabilityFlags flags; 183 | SCNetworkReachabilityGetFlags(self.networkReachability, &flags); 184 | dispatch_async(dispatch_get_main_queue(), ^{ 185 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 186 | callback(status); 187 | }); 188 | 189 | SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 190 | } 191 | 192 | - (void)stopMonitoring { 193 | if (!self.networkReachability) { 194 | return; 195 | } 196 | 197 | SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 198 | } 199 | 200 | #pragma mark - 201 | 202 | - (NSString *)localizedNetworkReachabilityStatusString { 203 | return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus); 204 | } 205 | 206 | #pragma mark - 207 | 208 | - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { 209 | self.networkReachabilityStatusBlock = block; 210 | } 211 | 212 | #pragma mark - NSKeyValueObserving 213 | 214 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { 215 | if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) { 216 | return [NSSet setWithObject:@"networkReachabilityStatus"]; 217 | } 218 | 219 | return [super keyPathsForValuesAffectingValueForKey:key]; 220 | } 221 | 222 | @end 223 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/AFNetworking/AFNetworking/AFSecurityPolicy.m: -------------------------------------------------------------------------------- 1 | // AFSecurity.m 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFSecurityPolicy.h" 24 | 25 | #if !defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 26 | static NSData * AFSecKeyGetData(SecKeyRef key) { 27 | CFDataRef data = NULL; 28 | 29 | #if defined(NS_BLOCK_ASSERTIONS) 30 | SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data); 31 | #else 32 | OSStatus status = SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data); 33 | NSCAssert(status == errSecSuccess, @"SecItemExport error: %ld", (long int)status); 34 | #endif 35 | 36 | NSCParameterAssert(data); 37 | 38 | return (__bridge_transfer NSData *)data; 39 | } 40 | #endif 41 | 42 | static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { 43 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 44 | return [(__bridge id)key1 isEqual:(__bridge id)key2]; 45 | #else 46 | return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; 47 | #endif 48 | } 49 | 50 | static id AFPublicKeyForCertificate(NSData *certificate) { 51 | SecCertificateRef allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); 52 | NSCParameterAssert(allowedCertificate); 53 | 54 | SecCertificateRef allowedCertificates[] = {allowedCertificate}; 55 | CFArrayRef tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL); 56 | 57 | SecPolicyRef policy = SecPolicyCreateBasicX509(); 58 | SecTrustRef allowedTrust = NULL; 59 | #if defined(NS_BLOCK_ASSERTIONS) 60 | SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust); 61 | #else 62 | OSStatus status = SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust); 63 | NSCAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates error: %ld", (long int)status); 64 | #endif 65 | 66 | SecTrustResultType result = 0; 67 | 68 | #if defined(NS_BLOCK_ASSERTIONS) 69 | SecTrustEvaluate(allowedTrust, &result); 70 | #else 71 | status = SecTrustEvaluate(allowedTrust, &result); 72 | NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status); 73 | #endif 74 | 75 | SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(allowedTrust); 76 | NSCParameterAssert(allowedPublicKey); 77 | 78 | CFRelease(allowedTrust); 79 | CFRelease(policy); 80 | CFRelease(tempCertificates); 81 | CFRelease(allowedCertificate); 82 | 83 | return (__bridge_transfer id)allowedPublicKey; 84 | } 85 | 86 | static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { 87 | SecTrustResultType result = 0; 88 | 89 | #if defined(NS_BLOCK_ASSERTIONS) 90 | SecTrustEvaluate(serverTrust, &result); 91 | #else 92 | OSStatus status = SecTrustEvaluate(serverTrust, &result); 93 | NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status); 94 | #endif 95 | 96 | return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); 97 | } 98 | 99 | static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) { 100 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 101 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 102 | 103 | for (CFIndex i = 0; i < certificateCount; i++) { 104 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 105 | [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]; 106 | } 107 | 108 | return [NSArray arrayWithArray:trustChain]; 109 | } 110 | 111 | static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { 112 | SecPolicyRef policy = SecPolicyCreateBasicX509(); 113 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 114 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 115 | for (CFIndex i = 0; i < certificateCount; i++) { 116 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 117 | 118 | SecCertificateRef someCertificates[] = {certificate}; 119 | CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); 120 | 121 | SecTrustRef trust = NULL; 122 | 123 | OSStatus status = SecTrustCreateWithCertificates(certificates, policy, &trust); 124 | NSCAssert(status == errSecSuccess, @"SecTrustCreateWithCertificates error: %ld", (long int)status); 125 | 126 | SecTrustResultType result; 127 | status = SecTrustEvaluate(trust, &result); 128 | NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status); 129 | 130 | [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; 131 | 132 | CFRelease(trust); 133 | CFRelease(certificates); 134 | } 135 | CFRelease(policy); 136 | 137 | return [NSArray arrayWithArray:trustChain]; 138 | } 139 | 140 | #pragma mark - 141 | 142 | @interface AFSecurityPolicy() 143 | @property (readwrite, nonatomic, strong) NSArray *pinnedPublicKeys; 144 | @end 145 | 146 | @implementation AFSecurityPolicy 147 | 148 | + (NSArray *)defaultPinnedCertificates { 149 | static NSArray *_defaultPinnedCertificates = nil; 150 | static dispatch_once_t onceToken; 151 | dispatch_once(&onceToken, ^{ 152 | NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 153 | NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; 154 | 155 | NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[paths count]]; 156 | for (NSString *path in paths) { 157 | NSData *certificateData = [NSData dataWithContentsOfFile:path]; 158 | [certificates addObject:certificateData]; 159 | } 160 | 161 | _defaultPinnedCertificates = [[NSArray alloc] initWithArray:certificates]; 162 | }); 163 | 164 | return _defaultPinnedCertificates; 165 | } 166 | 167 | + (instancetype)defaultPolicy { 168 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 169 | securityPolicy.SSLPinningMode = AFSSLPinningModeNone; 170 | 171 | return securityPolicy; 172 | } 173 | 174 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode { 175 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 176 | securityPolicy.SSLPinningMode = pinningMode; 177 | [securityPolicy setPinnedCertificates:[self defaultPinnedCertificates]]; 178 | 179 | return securityPolicy; 180 | } 181 | 182 | #pragma mark - 183 | 184 | - (void)setPinnedCertificates:(NSArray *)pinnedCertificates { 185 | _pinnedCertificates = pinnedCertificates; 186 | 187 | if (self.pinnedCertificates) { 188 | NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]]; 189 | for (NSData *certificate in self.pinnedCertificates) { 190 | [mutablePinnedPublicKeys addObject:AFPublicKeyForCertificate(certificate)]; 191 | } 192 | self.pinnedPublicKeys = [NSArray arrayWithArray:mutablePinnedPublicKeys]; 193 | } else { 194 | self.pinnedPublicKeys = nil; 195 | } 196 | } 197 | 198 | #pragma mark - 199 | 200 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust { 201 | switch (self.SSLPinningMode) { 202 | case AFSSLPinningModeNone: 203 | return (self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust)); 204 | case AFSSLPinningModeCertificate: { 205 | for (NSData *trustChainCertificate in AFCertificateTrustChainForServerTrust(serverTrust)) { 206 | if ([self.pinnedCertificates containsObject:trustChainCertificate]) { 207 | return YES; 208 | } 209 | } 210 | } 211 | break; 212 | case AFSSLPinningModePublicKey: { 213 | for (id trustChainPublicKey in AFPublicKeyTrustChainForServerTrust(serverTrust)) { 214 | for (id pinnedPublicKey in self.pinnedPublicKeys) { 215 | if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { 216 | return YES; 217 | } 218 | } 219 | } 220 | } 221 | break; 222 | default: 223 | break; 224 | } 225 | 226 | return NO; 227 | } 228 | 229 | #pragma mark - NSKeyValueObserving 230 | 231 | + (NSSet *)keyPathsForValuesAffectingPinnedPublicKeys { 232 | return [NSSet setWithObject:@"pinnedCertificates"]; 233 | } 234 | 235 | @end 236 | -------------------------------------------------------------------------------- /Classes/ExternalLibraries/DCIntrospect/DCFrameView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DCFrameView.m 3 | // 4 | // Created by Domestic Cat on 29/04/11. 5 | // 6 | 7 | #import "DCFrameView.h" 8 | 9 | @implementation DCFrameView 10 | @synthesize delegate; 11 | @synthesize mainRect, superRect; 12 | @synthesize touchPointLabel; 13 | @synthesize rectsToOutline; 14 | @synthesize touchPointView; 15 | 16 | - (void)dealloc 17 | { 18 | self.delegate = nil; 19 | [touchPointLabel release]; 20 | [touchPointView release]; 21 | 22 | [super dealloc]; 23 | } 24 | 25 | #pragma mark - Setup 26 | 27 | - (id)initWithFrame:(CGRect)frame delegate:(id)aDelegate 28 | { 29 | self = [super initWithFrame:frame]; 30 | if (self) 31 | { 32 | self.delegate = aDelegate; 33 | self.backgroundColor = [UIColor clearColor]; 34 | self.opaque = NO; 35 | 36 | self.touchPointLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease]; 37 | self.touchPointLabel.text = @"X 320 Y 480"; 38 | self.touchPointLabel.font = [UIFont boldSystemFontOfSize:12.0f]; 39 | self.touchPointLabel.textAlignment = UITextAlignmentCenter; 40 | self.touchPointLabel.textColor = [UIColor whiteColor]; 41 | self.touchPointLabel.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.65f]; 42 | self.touchPointLabel.layer.cornerRadius = 5.5f; 43 | self.touchPointLabel.layer.masksToBounds = YES; 44 | self.touchPointLabel.alpha = 0.0f; 45 | [self addSubview:self.touchPointLabel]; 46 | 47 | self.rectsToOutline = [NSMutableArray array]; 48 | 49 | self.touchPointView = [[[DCCrossHairView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 17.0f, 17.0f) color:[UIColor blueColor]] autorelease]; 50 | self.touchPointView.alpha = 0.0f; 51 | [self addSubview:self.touchPointView]; 52 | } 53 | return self; 54 | } 55 | 56 | #pragma mark - Custom Setters 57 | 58 | - (void)setMainRect:(CGRect)newMainRect 59 | { 60 | mainRect = newMainRect; 61 | [self setNeedsDisplay]; 62 | } 63 | 64 | - (void)setSuperRect:(CGRect)newSuperRect 65 | { 66 | superRect = newSuperRect; 67 | [self setNeedsDisplay]; 68 | } 69 | 70 | #pragma mark - Drawing/Display 71 | 72 | - (void)drawRect:(CGRect)rect 73 | { 74 | CGContextRef context = UIGraphicsGetCurrentContext(); 75 | 76 | if (self.rectsToOutline.count > 0) 77 | { 78 | for (NSValue *value in self.rectsToOutline) 79 | { 80 | UIColor *randomColor = [UIColor colorWithRed:(arc4random() % 256) / 256.0f 81 | green:(arc4random() % 256) / 256.0f 82 | blue:(arc4random() % 256) / 256.0f 83 | alpha:1.0f]; 84 | [randomColor set]; 85 | CGRect valueRect = [value CGRectValue]; 86 | valueRect = CGRectMake(valueRect.origin.x + 0.5f, 87 | valueRect.origin.y + 0.5f, 88 | valueRect.size.width - 1.0f, 89 | valueRect.size.height - 1.0f); 90 | CGContextStrokeRect(context, valueRect); 91 | } 92 | return; 93 | } 94 | 95 | if (CGRectIsEmpty(self.mainRect)) 96 | return; 97 | 98 | CGRect mainRectOffset = CGRectOffset(mainRect, -superRect.origin.x, -superRect.origin.y); 99 | BOOL showAntialiasingWarning = NO; 100 | if (! CGRectIsEmpty(self.superRect)) 101 | { 102 | if ((mainRectOffset.origin.x != floorf(mainRectOffset.origin.x) && mainRect.origin.x != 0) || (mainRectOffset.origin.y != floor(mainRectOffset.origin.y) && mainRect.origin.y != 0)) 103 | showAntialiasingWarning = YES; 104 | } 105 | 106 | if (showAntialiasingWarning) 107 | { 108 | [[UIColor redColor] set]; 109 | NSLog(@"DCIntrospect: *** WARNING: One or more values of this view's frame are non-integer values. This view will likely look blurry. ***"); 110 | } 111 | else 112 | { 113 | [[UIColor blueColor] set]; 114 | } 115 | 116 | CGRect adjustedMainRect = CGRectMake(self.mainRect.origin.x + 0.5f, 117 | self.mainRect.origin.y + 0.5f, 118 | self.mainRect.size.width - 1.0f, 119 | self.mainRect.size.height - 1.0f); 120 | CGContextStrokeRect(context, adjustedMainRect); 121 | 122 | UIFont *font = [UIFont systemFontOfSize:10.0f]; 123 | 124 | float dash[2] = {3, 3}; 125 | CGContextSetLineDash(context, 0, dash, 2); 126 | 127 | // edge->left side 128 | CGContextMoveToPoint(context, CGRectGetMinX(self.superRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f); 129 | CGContextAddLineToPoint(context, CGRectGetMinX(adjustedMainRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f); 130 | CGContextStrokePath(context); 131 | 132 | NSString *leftDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", CGRectGetMinX(mainRectOffset)] : [NSString stringWithFormat:@"%.0f", CGRectGetMinX(mainRectOffset)]; 133 | CGSize leftDistanceStringSize = [leftDistanceString sizeWithFont:font]; 134 | [leftDistanceString drawInRect:CGRectMake(CGRectGetMinX(superRect) + 1.0f, 135 | floorf(CGRectGetMidY(adjustedMainRect)) - leftDistanceStringSize.height, 136 | leftDistanceStringSize.width, 137 | leftDistanceStringSize.height) 138 | withFont:font]; 139 | 140 | // right side->edge 141 | if (CGRectGetMaxX(self.mainRect) < CGRectGetMaxX(self.superRect)) 142 | { 143 | CGContextMoveToPoint(context, CGRectGetMaxX(adjustedMainRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f); 144 | CGContextAddLineToPoint(context, CGRectGetMaxX(self.superRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f); 145 | CGContextStrokePath(context); 146 | } 147 | NSString *rightDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", CGRectGetMaxX(self.superRect) - CGRectGetMaxX(adjustedMainRect) - 0.5] : [NSString stringWithFormat:@"%.0f", CGRectGetMaxX(self.superRect) - CGRectGetMaxX(adjustedMainRect) - 0.5]; 148 | CGSize rightDistanceStringSize = [rightDistanceString sizeWithFont:font]; 149 | [rightDistanceString drawInRect:CGRectMake(CGRectGetMaxX(self.superRect) - rightDistanceStringSize.width - 1.0f, 150 | floorf(CGRectGetMidY(adjustedMainRect)) - 0.5f - rightDistanceStringSize.height, 151 | rightDistanceStringSize.width, 152 | rightDistanceStringSize.height) 153 | withFont:font]; 154 | 155 | // edge->top side 156 | CGContextMoveToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, self.superRect.origin.y); 157 | CGContextAddLineToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, CGRectGetMinY(adjustedMainRect)); 158 | CGContextStrokePath(context); 159 | NSString *topDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", mainRectOffset.origin.y] : [NSString stringWithFormat:@"%.0f", mainRectOffset.origin.y]; 160 | CGSize topDistanceStringSize = [topDistanceString sizeWithFont:font]; 161 | [topDistanceString drawInRect:CGRectMake(floorf(CGRectGetMidX(adjustedMainRect)) + 3.0f, 162 | floorf(CGRectGetMinY(self.superRect)), 163 | topDistanceStringSize.width, 164 | topDistanceStringSize.height) 165 | withFont:font]; 166 | 167 | // bottom side->edge 168 | if (CGRectGetMaxY(self.mainRect) < CGRectGetMaxY(self.superRect)) 169 | { 170 | CGContextMoveToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, CGRectGetMaxY(adjustedMainRect)); 171 | CGContextAddLineToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, CGRectGetMaxY(self.superRect)); 172 | CGContextStrokePath(context); 173 | } 174 | NSString *bottomDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", CGRectGetMaxY(self.superRect) - CGRectGetMaxY(mainRectOffset)] : [NSString stringWithFormat:@"%.0f", self.superRect.size.height - mainRectOffset.origin.y - mainRectOffset.size.height]; 175 | CGSize bottomDistanceStringSize = [bottomDistanceString sizeWithFont:font]; 176 | [bottomDistanceString drawInRect:CGRectMake(floorf(CGRectGetMidX(adjustedMainRect)) + 3.0f, 177 | floorf(CGRectGetMaxY(self.superRect)) - bottomDistanceStringSize.height - 1.0f, 178 | bottomDistanceStringSize.width, 179 | bottomDistanceStringSize.height) 180 | withFont:font]; 181 | 182 | } 183 | 184 | #pragma mark - Touch Handling 185 | 186 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 187 | { 188 | CGFloat labelDistance = 16.0f; 189 | CGPoint touchPoint = [[touches anyObject] locationInView:self]; 190 | 191 | // adjust the point so it's exactly on the point of the mouse cursor 192 | touchPoint.x -= 1; 193 | touchPoint.y -= 2; 194 | 195 | NSString *touchPontLabelString = [NSString stringWithFormat:@"%.0f, %.0f", touchPoint.x, touchPoint.y]; 196 | self.touchPointLabel.text = touchPontLabelString; 197 | 198 | CGSize stringSize = [touchPontLabelString sizeWithFont:touchPointLabel.font]; 199 | CGRect frame = CGRectMake(touchPoint.x - floorf(stringSize.width / 2.0f) - 5.0f, 200 | touchPoint.y - stringSize.height - labelDistance, 201 | stringSize.width + 11.0f, 202 | stringSize.height + 4.0f); 203 | 204 | // make sure the label stays inside the frame 205 | UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 206 | CGFloat minY = UIInterfaceOrientationIsPortrait(orientation) ? [UIApplication sharedApplication].statusBarFrame.size.height : [UIApplication sharedApplication].statusBarFrame.size.width; 207 | minY += 2.0f; // to keep it touching the top bar 208 | if (frame.origin.x < 2.0f) 209 | frame.origin.x = 2.0f; 210 | else if (CGRectGetMaxX(frame) > self.bounds.size.width - 2.0f) 211 | frame.origin.x = self.bounds.size.width - frame.size.width - 2.0f; 212 | if (frame.origin.y < minY) 213 | frame.origin.y = touchPoint.y + stringSize.height + 4.0f; 214 | 215 | self.touchPointLabel.frame = frame; 216 | self.touchPointView.center = CGPointMake(touchPoint.x + 0.5f, touchPoint.y + 0.5f); 217 | self.touchPointView.alpha = self.touchPointLabel.alpha = 1.0f; 218 | 219 | [self.delegate touchAtPoint:touchPoint]; 220 | } 221 | 222 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 223 | { 224 | [self touchesBegan:touches withEvent:event]; 225 | } 226 | 227 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 228 | { 229 | [UIView animateWithDuration:0.08 animations:^{ 230 | self.touchPointView.alpha = self.touchPointLabel.alpha = 0.0f; 231 | }]; 232 | } 233 | 234 | @end 235 | --------------------------------------------------------------------------------