├── README.md ├── ZZPhotoKit.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── Dev.z.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── Migic_Z.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── Yuan.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── Dev.z.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── ZZPhotoKit.xcscheme │ │ └── xcschememanagement.plist │ ├── Migic_Z.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── ZZPhotoKit.xcscheme │ │ └── xcschememanagement.plist │ └── Yuan.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── ZZPhotoKit.xcscheme │ └── xcschememanagement.plist ├── ZZPhotoKit ├── .DS_Store ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── .DS_Store │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── LaunchScreen.storyboard ├── Info.plist ├── PicsCell.h ├── PicsCell.m ├── Resources │ ├── scv1.jpg │ ├── scv2.jpg │ ├── scv3.jpg │ ├── scv4.jpg │ └── scv5.jpg ├── SDWebImage │ ├── .DS_Store │ ├── MKAnnotationView+WebCache.h │ ├── MKAnnotationView+WebCache.m │ ├── NSData+ImageContentType.h │ ├── NSData+ImageContentType.m │ ├── SDImageCache.h │ ├── SDImageCache.m │ ├── SDWebImageCompat.h │ ├── SDWebImageCompat.m │ ├── SDWebImageDecoder.h │ ├── SDWebImageDecoder.m │ ├── SDWebImageDownloader.h │ ├── SDWebImageDownloader.m │ ├── SDWebImageDownloaderOperation.h │ ├── SDWebImageDownloaderOperation.m │ ├── SDWebImageManager.h │ ├── SDWebImageManager.m │ ├── SDWebImageOperation.h │ ├── SDWebImagePrefetcher.h │ ├── SDWebImagePrefetcher.m │ ├── UIButton+WebCache.h │ ├── UIButton+WebCache.m │ ├── UIImage+GIF.h │ ├── UIImage+GIF.m │ ├── UIImage+MultiFormat.h │ ├── UIImage+MultiFormat.m │ ├── UIImage+WebP.h │ ├── UIImage+WebP.m │ ├── UIImageView+HighlightedWebCache.h │ ├── UIImageView+HighlightedWebCache.m │ ├── UIImageView+WebCache.h │ ├── UIImageView+WebCache.m │ ├── UIView+WebCacheOperation.h │ └── UIView+WebCacheOperation.m ├── SVProgressHUD │ └── .DS_Store ├── ViewController.h ├── ViewController.m ├── ZZPhotoKit │ ├── Public │ │ ├── Other │ │ │ ├── ZZAlumAnimation.h │ │ │ └── ZZAlumAnimation.m │ │ ├── Resources │ │ │ ├── back_button_normal.png │ │ │ ├── back_button_normal@2x.png │ │ │ ├── camera_focus_pic.png │ │ │ ├── change_camera_pic.png │ │ │ ├── flash_close_pic.png │ │ │ ├── flash_open_pic.png │ │ │ ├── no_data.png │ │ │ ├── photo_add.png │ │ │ ├── remove_btn_pic.png │ │ │ ├── select_no.png │ │ │ ├── select_yes.png │ │ │ ├── take_photo_pic.png │ │ │ ├── take_photo_pic@2x.png │ │ │ ├── trash_btn_pic.png │ │ │ └── zz_alumb_rightCell.png │ │ └── ZZResourceConfig.h │ ├── ZZBrowser │ │ ├── ZZBrowserPickerCell.h │ │ ├── ZZBrowserPickerCell.m │ │ ├── ZZBrowserPickerViewController.h │ │ ├── ZZBrowserPickerViewController.m │ │ ├── ZZPageControl.h │ │ └── ZZPageControl.m │ ├── ZZCamera │ │ ├── Controller │ │ │ ├── ZZCameraBrowerViewController.h │ │ │ ├── ZZCameraBrowerViewController.m │ │ │ ├── ZZCameraController.h │ │ │ ├── ZZCameraController.m │ │ │ ├── ZZCameraPickerViewController.h │ │ │ └── ZZCameraPickerViewController.m │ │ ├── Model │ │ │ ├── ZZCamera.h │ │ │ └── ZZCamera.m │ │ └── View │ │ │ ├── ZZCameraBrowerCell.h │ │ │ ├── ZZCameraBrowerCell.m │ │ │ ├── ZZCameraFocusView.h │ │ │ ├── ZZCameraFocusView.m │ │ │ ├── ZZCameraPickerCell.h │ │ │ └── ZZCameraPickerCell.m │ ├── ZZPhoto │ │ ├── Controller │ │ │ ├── ZZPhotoBrowerViewController.h │ │ │ ├── ZZPhotoBrowerViewController.m │ │ │ ├── ZZPhotoController.h │ │ │ ├── ZZPhotoController.m │ │ │ ├── ZZPhotoListViewController.h │ │ │ ├── ZZPhotoListViewController.m │ │ │ ├── ZZPhotoPickerViewController.h │ │ │ └── ZZPhotoPickerViewController.m │ │ ├── Model │ │ │ ├── ZZPhoto.h │ │ │ ├── ZZPhoto.m │ │ │ ├── ZZPhotoDatas.h │ │ │ ├── ZZPhotoDatas.m │ │ │ ├── ZZPhotoListModel.h │ │ │ └── ZZPhotoListModel.m │ │ └── View │ │ │ ├── ZZPhotoAlert.h │ │ │ ├── ZZPhotoAlert.m │ │ │ ├── ZZPhotoBrowerCell.h │ │ │ ├── ZZPhotoBrowerCell.m │ │ │ ├── ZZPhotoHud.h │ │ │ ├── ZZPhotoHud.m │ │ │ ├── ZZPhotoListCell.h │ │ │ ├── ZZPhotoListCell.m │ │ │ ├── ZZPhotoPickerCell.h │ │ │ ├── ZZPhotoPickerCell.m │ │ │ ├── ZZPhotoPickerFooterView.h │ │ │ └── ZZPhotoPickerFooterView.m │ └── ZZPhotoKit.h └── main.m ├── ZZPhotoKitTests ├── Info.plist └── ZZPhotoKitTests.m ├── ZZPhotoKitUITests ├── Info.plist └── ZZPhotoKitUITests.m └── image ├── demonstrate.gif ├── examplepic.png ├── object.png ├── privacy_use.png └── zz_camera_intro.jpg /README.md: -------------------------------------------------------------------------------- 1 | # ZZPhotoKit 2 | ##说明 3 | 4 | * 此开源目前接近于成熟状态,不喜欢的大神们还望轻虐。 5 | * 注意此框架只支持 IOS 8.0 及以上系统使用。 6 | * 注意由于工作原因后续不做IOS7适配了,IOS7占有率也比较低了,所以也不考虑后续再做了。 7 | * 这次升级了版本之后以后可能不会有太大变动的。 8 | * 相册多选基于最新的 Photos 框架。 9 | * 相机连续拍摄基于AVFundation 框架。 10 | * 图片浏览器支持 SDWebImage 加载图片 11 | * 欢迎大家使用,欢迎大家Star 12 | 13 | ###告诉我您的APP,使用到我框架的把APP名字告诉我,谢谢哦。单纯看看使用率。(*^__^*) 14 | ###有什么不明白的地方,或者哪里需要改进的可以联系我 15 | ###联系方式 16 | ###关注微博:袁亮_ 17 | 18 | ##项目介绍 19 | ![image](https://github.com/ACEYL/ZZPhotoKit/raw/master/image/demonstrate.gif) 20 | ![image](https://github.com/ACEYL/ZZPhotoKit/raw/master/image/zz_camera_intro.jpg) 21 | 22 | ##更新内容 23 | 24 | * 10月13日更新内容:网友提出意见,图片浏览器加入放大缩小手势。点击放大缩小下一版本添加。 25 | * 10月13日更新内容:相册多选中加入图片预览功能。 26 | * 10月12日更新内容:对不起同志们,框架中有内存暴增问题,今日发现已经解决。在使用的同志们看见后尽快更改一下吧。或者升级一下。 27 | * 逐步加入autolayout布局。一步一步走向横屏设备。 28 | * iOS 10适配框架 29 | * info.plist文件中添加相册与相机的权限 30 | * 相册权限 Privacy - Photo Library Usage Description 31 | * 相机权限 Privacy - Camera Usage Description 32 | * 在iOS 10 使用时,如不添加如上权限则会导致崩溃闪退。 33 | ![image](https://github.com/ACEYL/ZZPhotoKit/raw/master/image/privacy_use.png) 34 | 35 | ##使用方法 36 | 37 | 首先重要提醒一个 文件,ZZResourceConfig.h 这个配置文件。 38 | ###包含内容 39 | 40 | * 1.包含了所有的按钮图片信息,任意更换即可. 41 | * 2.包含了图片返回类型的公共枚举. 42 | * 3.所有用到的头文件。以及一些颜色、控制器宽高、屏幕宽高宏定义. 43 | 44 | ### 导入头文件 45 | ###import "ZZPhotoKit.h" 46 | 47 | * 相册多选的调用 48 | ``` 49 | ZZPhotoController *photoController = [[ZZPhotoController alloc]init]; 50 | 51 | //设置最大选择张数 52 | photoController.selectPhotoOfMax = 5; 53 | 54 | [photoController showIn:self result:^(id responseObject){ 55 | //responseObject 中元素类型为 ZZPhoto 56 | //返回结果集 57 | NSLog(@"%@",responseObject); 58 | NSArray *array = (NSArray *)responseObject; 59 | 60 | }]; 61 | ``` 62 | 63 | * 相机连拍的调用 64 | ``` 65 | ZZCameraController *cameraController = [[ZZCameraController alloc]init]; 66 | //设置最大连拍张数 67 | cameraController.takePhotoOfMax = 8; 68 | //设置图片返回类型 (下面例子为缩略图) 69 | cameraController.imageType = ZZImageTypeOfThumb; 70 | [cameraController showIn:self result:^(id responseObject){ 71 | //responseObject 中元素类型为 ZZCamera 72 | //返回结果集 73 | NSLog(@"%@",responseObject); 74 | NSArray *array = (NSArray *)responseObject; 75 | }]; 76 | 77 | ``` 78 | ### 新增model查看 79 | * ![image](https://github.com/ACEYL/ZZPhotoKit/raw/master/image/object.png) 80 | * ![image](https://github.com/ACEYL/ZZPhotoKit/raw/master/image/examplepic.png) 81 | 82 | * 简单的图片浏览器 83 | ``` 84 | ZZBrowserPickerViewController *browserController = [[ZZBrowserPickerViewController alloc]init]; 85 | browserController.delegate = self; 86 | [browserController showIn:self animation:ShowAnimationOfPush]; 87 | 88 | //delegate 89 | //图片的个数。 90 | -(NSInteger)zzbrowserPickerPhotoNum:(ZZBrowserPickerViewController *)controller 91 | //图片的数组。 92 | -(NSArray *)zzbrowserPickerPhotoContent:(ZZBrowserPickerViewController *)controller 93 | ``` 94 | 95 | ###详细使用方法还是看demo 吧。 96 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/project.xcworkspace/xcuserdata/Dev.z.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit.xcodeproj/project.xcworkspace/xcuserdata/Dev.z.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/project.xcworkspace/xcuserdata/Migic_Z.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit.xcodeproj/project.xcworkspace/xcuserdata/Migic_Z.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/project.xcworkspace/xcuserdata/Yuan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit.xcodeproj/project.xcworkspace/xcuserdata/Yuan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Dev.z.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Dev.z.xcuserdatad/xcschemes/ZZPhotoKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Dev.z.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZZPhotoKit.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1C94AC011C3A7B1E00B26FAE 16 | 17 | primary 18 | 19 | 20 | 1C94AC1A1C3A7B1F00B26FAE 21 | 22 | primary 23 | 24 | 25 | 1C94AC251C3A7B1F00B26FAE 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Migic_Z.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Migic_Z.xcuserdatad/xcschemes/ZZPhotoKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Migic_Z.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZZPhotoKit.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1C94AC011C3A7B1E00B26FAE 16 | 17 | primary 18 | 19 | 20 | 1C94AC1A1C3A7B1F00B26FAE 21 | 22 | primary 23 | 24 | 25 | 1C94AC251C3A7B1F00B26FAE 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Yuan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Yuan.xcuserdatad/xcschemes/ZZPhotoKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /ZZPhotoKit.xcodeproj/xcuserdata/Yuan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZZPhotoKit.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1C94AC011C3A7B1E00B26FAE 16 | 17 | primary 18 | 19 | 20 | 1C94AC1A1C3A7B1F00B26FAE 21 | 22 | primary 23 | 24 | 25 | 1C94AC251C3A7B1F00B26FAE 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ZZPhotoKit/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/.DS_Store -------------------------------------------------------------------------------- /ZZPhotoKit/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ZZPhotoKit/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | 20 | UIImage *navBarBgImage = [self imageWithColor:[UIColor redColor]]; 21 | 22 | [[UINavigationBar appearance] setBackgroundImage:navBarBgImage forBarMetrics:UIBarMetricsDefault]; 23 | 24 | [[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],NSForegroundColorAttributeName,[UIFont systemFontOfSize:18.0f],NSFontAttributeName,nil]]; 25 | 26 | // Override point for customization after application launch. 27 | self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen] bounds]]; 28 | 29 | self.window.backgroundColor = [UIColor whiteColor]; 30 | 31 | 32 | ViewController *mainViewController = [[ViewController alloc]initWithNibName:nil bundle:nil]; 33 | 34 | UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:mainViewController]; 35 | self.window.rootViewController = navi; 36 | [self.window makeKeyAndVisible]; 37 | return YES; 38 | } 39 | 40 | -(UIImage *)imageWithColor:(UIColor *)color 41 | { 42 | CGRect rect = CGRectMake(0, 0, 1, 1); 43 | UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0); 44 | CGContextRef context = UIGraphicsGetCurrentContext(); 45 | CGContextSetFillColorWithColor(context, [color CGColor]); 46 | CGContextFillRect(context, rect); 47 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 48 | UIGraphicsEndImageContext(); 49 | return image; 50 | } 51 | 52 | - (void)applicationWillResignActive:(UIApplication *)application { 53 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 54 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 55 | } 56 | 57 | - (void)applicationDidEnterBackground:(UIApplication *)application { 58 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 59 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 60 | } 61 | 62 | - (void)applicationWillEnterForeground:(UIApplication *)application { 63 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 64 | } 65 | 66 | - (void)applicationDidBecomeActive:(UIApplication *)application { 67 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 68 | } 69 | 70 | - (void)applicationWillTerminate:(UIApplication *)application { 71 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /ZZPhotoKit/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /ZZPhotoKit/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /ZZPhotoKit/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ZZPhotoKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ZZPhotoKit 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | NSCameraUsageDescription 31 | 是否开启相机权限 32 | NSPhotoLibraryUsageDescription 33 | 是否开启相册权限 34 | UILaunchStoryboardName 35 | LaunchScreen 36 | UIRequiredDeviceCapabilities 37 | 38 | armv7 39 | 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ZZPhotoKit/PicsCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PicsCell.h 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/13. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PicsCell : UICollectionViewCell 12 | 13 | @property(strong,nonatomic) UIImageView *photo; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZZPhotoKit/PicsCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PicsCell.m 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/13. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "PicsCell.h" 10 | 11 | @implementation PicsCell 12 | 13 | -(instancetype)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | CGFloat photoSize = ([UIScreen mainScreen].bounds.size.width - 50) / 3; 18 | 19 | _photo = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, photoSize, photoSize)]; 20 | 21 | _photo.layer.masksToBounds = YES; 22 | 23 | _photo.contentMode = UIViewContentModeScaleAspectFill; 24 | 25 | [self.contentView addSubview:_photo]; 26 | } 27 | return self; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ZZPhotoKit/Resources/scv1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/Resources/scv1.jpg -------------------------------------------------------------------------------- /ZZPhotoKit/Resources/scv2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/Resources/scv2.jpg -------------------------------------------------------------------------------- /ZZPhotoKit/Resources/scv3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/Resources/scv3.jpg -------------------------------------------------------------------------------- /ZZPhotoKit/Resources/scv4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/Resources/scv4.jpg -------------------------------------------------------------------------------- /ZZPhotoKit/Resources/scv5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/Resources/scv5.jpg -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/SDWebImage/.DS_Store -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/MKAnnotationView+WebCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKAnnotationView+WebCache.h 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 14/03/12. 6 | // Copyright (c) 2012 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "MapKit/MapKit.h" 10 | #import "SDWebImageManager.h" 11 | 12 | /** 13 | * Integrates SDWebImage async downloading and caching of remote images with MKAnnotationView. 14 | */ 15 | @interface MKAnnotationView (WebCache) 16 | 17 | /** 18 | * Get the current image URL. 19 | * 20 | * Note that because of the limitations of categories this property can get out of sync 21 | * if you use sd_setImage: directly. 22 | */ 23 | - (NSURL *)sd_imageURL; 24 | 25 | /** 26 | * Set the imageView `image` with an `url`. 27 | * 28 | * The download is asynchronous and cached. 29 | * 30 | * @param url The url for the image. 31 | */ 32 | - (void)sd_setImageWithURL:(NSURL *)url; 33 | 34 | /** 35 | * Set the imageView `image` with an `url` and a placeholder. 36 | * 37 | * The download is asynchronous and cached. 38 | * 39 | * @param url The url for the image. 40 | * @param placeholder The image to be set initially, until the image request finishes. 41 | * @see sd_setImageWithURL:placeholderImage:options: 42 | */ 43 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; 44 | 45 | /** 46 | * Set the imageView `image` with an `url`, placeholder and custom options. 47 | * 48 | * The download is asynchronous and cached. 49 | * 50 | * @param url The url for the image. 51 | * @param placeholder The image to be set initially, until the image request finishes. 52 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 53 | */ 54 | 55 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; 56 | 57 | /** 58 | * Set the imageView `image` with an `url`. 59 | * 60 | * The download is asynchronous and cached. 61 | * 62 | * @param url The url for the image. 63 | * @param completedBlock A block called when operation has been completed. This block has no return value 64 | * and takes the requested UIImage as first parameter. In case of error the image parameter 65 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 66 | * indicating if the image was retrived from the local cache or from the network. 67 | * The fourth parameter is the original image url. 68 | */ 69 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; 70 | 71 | /** 72 | * Set the imageView `image` with an `url`, placeholder. 73 | * 74 | * The download is asynchronous and cached. 75 | * 76 | * @param url The url for the image. 77 | * @param placeholder The image to be set initially, until the image request finishes. 78 | * @param completedBlock A block called when operation has been completed. This block has no return value 79 | * and takes the requested UIImage as first parameter. In case of error the image parameter 80 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 81 | * indicating if the image was retrived from the local cache or from the network. 82 | * The fourth parameter is the original image url. 83 | */ 84 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; 85 | 86 | /** 87 | * Set the imageView `image` with an `url`, placeholder and custom options. 88 | * 89 | * The download is asynchronous and cached. 90 | * 91 | * @param url The url for the image. 92 | * @param placeholder The image to be set initially, until the image request finishes. 93 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 94 | * @param completedBlock A block called when operation has been completed. This block has no return value 95 | * and takes the requested UIImage as first parameter. In case of error the image parameter 96 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 97 | * indicating if the image was retrived from the local cache or from the network. 98 | * The fourth parameter is the original image url. 99 | */ 100 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; 101 | 102 | /** 103 | * Cancel the current download 104 | */ 105 | - (void)sd_cancelCurrentImageLoad; 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/MKAnnotationView+WebCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKAnnotationView+WebCache.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 14/03/12. 6 | // Copyright (c) 2012 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "MKAnnotationView+WebCache.h" 10 | #import "objc/runtime.h" 11 | #import "UIView+WebCacheOperation.h" 12 | 13 | static char imageURLKey; 14 | 15 | @implementation MKAnnotationView (WebCache) 16 | 17 | - (NSURL *)sd_imageURL { 18 | return objc_getAssociatedObject(self, &imageURLKey); 19 | } 20 | 21 | - (void)sd_setImageWithURL:(NSURL *)url { 22 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:nil]; 23 | } 24 | 25 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { 26 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:nil]; 27 | } 28 | 29 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 30 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil]; 31 | } 32 | 33 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { 34 | [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:completedBlock]; 35 | } 36 | 37 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { 38 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:completedBlock]; 39 | } 40 | 41 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 42 | [self sd_cancelCurrentImageLoad]; 43 | 44 | objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 45 | self.image = placeholder; 46 | 47 | if (url) { 48 | __weak MKAnnotationView *wself = self; 49 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 50 | if (!wself) return; 51 | dispatch_main_sync_safe(^{ 52 | __strong MKAnnotationView *sself = wself; 53 | if (!sself) return; 54 | if (image) { 55 | sself.image = image; 56 | } 57 | if (completedBlock && finished) { 58 | completedBlock(image, error, cacheType, url); 59 | } 60 | }); 61 | }]; 62 | [self sd_setImageLoadOperation:operation forKey:@"MKAnnotationViewImage"]; 63 | } else { 64 | dispatch_main_async_safe(^{ 65 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 66 | if (completedBlock) { 67 | completedBlock(nil, error, SDImageCacheTypeNone, url); 68 | } 69 | }); 70 | } 71 | } 72 | 73 | - (void)sd_cancelCurrentImageLoad { 74 | [self sd_cancelImageLoadOperationWithKey:@"MKAnnotationViewImage"]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/NSData+ImageContentType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Fabrice Aneche on 06/01/14. 3 | // Copyright (c) 2014 Dailymotion. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface NSData (ImageContentType) 9 | 10 | /** 11 | * Compute the content type for an image data 12 | * 13 | * @param data the input data 14 | * 15 | * @return the content type as string (i.e. image/jpeg, image/gif) 16 | */ 17 | + (NSString *)sd_contentTypeForImageData:(NSData *)data; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/NSData+ImageContentType.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Fabrice Aneche on 06/01/14. 3 | // Copyright (c) 2014 Dailymotion. All rights reserved. 4 | // 5 | 6 | #import "NSData+ImageContentType.h" 7 | 8 | 9 | @implementation NSData (ImageContentType) 10 | 11 | + (NSString *)sd_contentTypeForImageData:(NSData *)data { 12 | uint8_t c; 13 | [data getBytes:&c length:1]; 14 | switch (c) { 15 | case 0xFF: 16 | return @"image/jpeg"; 17 | case 0x89: 18 | return @"image/png"; 19 | case 0x47: 20 | return @"image/gif"; 21 | case 0x49: 22 | case 0x4D: 23 | return @"image/tiff"; 24 | case 0x52: 25 | // R as RIFF for WEBP 26 | if ([data length] < 12) { 27 | return nil; 28 | } 29 | 30 | NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding]; 31 | if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) { 32 | return @"image/webp"; 33 | } 34 | 35 | return nil; 36 | } 37 | return nil; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDImageCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageCompat.h" 11 | 12 | typedef NS_ENUM(NSInteger, SDImageCacheType) { 13 | /** 14 | * The image wasn't available the SDWebImage caches, but was downloaded from the web. 15 | */ 16 | SDImageCacheTypeNone, 17 | /** 18 | * The image was obtained from the disk cache. 19 | */ 20 | SDImageCacheTypeDisk, 21 | /** 22 | * The image was obtained from the memory cache. 23 | */ 24 | SDImageCacheTypeMemory 25 | }; 26 | 27 | typedef void(^SDWebImageQueryCompletedBlock)(UIImage *image, SDImageCacheType cacheType); 28 | 29 | typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); 30 | 31 | typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize); 32 | 33 | /** 34 | * SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed 35 | * asynchronous so it doesn’t add unnecessary latency to the UI. 36 | */ 37 | @interface SDImageCache : NSObject 38 | 39 | /** 40 | * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. 41 | */ 42 | @property (assign, nonatomic) NSUInteger maxMemoryCost; 43 | 44 | /** 45 | * The maximum length of time to keep an image in the cache, in seconds 46 | */ 47 | @property (assign, nonatomic) NSInteger maxCacheAge; 48 | 49 | /** 50 | * The maximum size of the cache, in bytes. 51 | */ 52 | @property (assign, nonatomic) NSUInteger maxCacheSize; 53 | 54 | /** 55 | * Returns global shared cache instance 56 | * 57 | * @return SDImageCache global instance 58 | */ 59 | + (SDImageCache *)sharedImageCache; 60 | 61 | /** 62 | * Init a new cache store with a specific namespace 63 | * 64 | * @param ns The namespace to use for this cache store 65 | */ 66 | - (id)initWithNamespace:(NSString *)ns; 67 | 68 | /** 69 | * Add a read-only cache path to search for images pre-cached by SDImageCache 70 | * Useful if you want to bundle pre-loaded images with your app 71 | * 72 | * @param path The path to use for this read-only cache path 73 | */ 74 | - (void)addReadOnlyCachePath:(NSString *)path; 75 | 76 | /** 77 | * Store an image into memory and disk cache at the given key. 78 | * 79 | * @param image The image to store 80 | * @param key The unique image cache key, usually it's image absolute URL 81 | */ 82 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key; 83 | 84 | /** 85 | * Store an image into memory and optionally disk cache at the given key. 86 | * 87 | * @param image The image to store 88 | * @param key The unique image cache key, usually it's image absolute URL 89 | * @param toDisk Store the image to disk cache if YES 90 | */ 91 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk; 92 | 93 | /** 94 | * Store an image into memory and optionally disk cache at the given key. 95 | * 96 | * @param image The image to store 97 | * @param recalculate BOOL indicates if imageData can be used or a new data should be constructed from the UIImage 98 | * @param imageData The image data as returned by the server, this representation will be used for disk storage 99 | * instead of converting the given image object into a storable/compressed image format in order 100 | * to save quality and CPU 101 | * @param key The unique image cache key, usually it's image absolute URL 102 | * @param toDisk Store the image to disk cache if YES 103 | */ 104 | - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk; 105 | 106 | /** 107 | * Query the disk cache asynchronously. 108 | * 109 | * @param key The unique key used to store the wanted image 110 | */ 111 | - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock; 112 | 113 | /** 114 | * Query the memory cache synchronously. 115 | * 116 | * @param key The unique key used to store the wanted image 117 | */ 118 | - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key; 119 | 120 | /** 121 | * Query the disk cache synchronously after checking the memory cache. 122 | * 123 | * @param key The unique key used to store the wanted image 124 | */ 125 | - (UIImage *)imageFromDiskCacheForKey:(NSString *)key; 126 | 127 | /** 128 | * Remove the image from memory and disk cache synchronously 129 | * 130 | * @param key The unique image cache key 131 | */ 132 | - (void)removeImageForKey:(NSString *)key; 133 | 134 | 135 | /** 136 | * Remove the image from memory and disk cache synchronously 137 | * 138 | * @param key The unique image cache key 139 | * @param completion An block that should be executed after the image has been removed (optional) 140 | */ 141 | - (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion; 142 | 143 | /** 144 | * Remove the image from memory and optionally disk cache synchronously 145 | * 146 | * @param key The unique image cache key 147 | * @param fromDisk Also remove cache entry from disk if YES 148 | */ 149 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk; 150 | 151 | /** 152 | * Remove the image from memory and optionally disk cache synchronously 153 | * 154 | * @param key The unique image cache key 155 | * @param fromDisk Also remove cache entry from disk if YES 156 | * @param completion An block that should be executed after the image has been removed (optional) 157 | */ 158 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion; 159 | 160 | /** 161 | * Clear all memory cached images 162 | */ 163 | - (void)clearMemory; 164 | 165 | /** 166 | * Clear all disk cached images. Non-blocking method - returns immediately. 167 | * @param completion An block that should be executed after cache expiration completes (optional) 168 | */ 169 | - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion; 170 | 171 | /** 172 | * Clear all disk cached images 173 | * @see clearDiskOnCompletion: 174 | */ 175 | - (void)clearDisk; 176 | 177 | /** 178 | * Remove all expired cached image from disk. Non-blocking method - returns immediately. 179 | * @param completionBlock An block that should be executed after cache expiration completes (optional) 180 | */ 181 | - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock; 182 | 183 | /** 184 | * Remove all expired cached image from disk 185 | * @see cleanDiskWithCompletionBlock: 186 | */ 187 | - (void)cleanDisk; 188 | 189 | /** 190 | * Get the size used by the disk cache 191 | */ 192 | - (NSUInteger)getSize; 193 | 194 | /** 195 | * Get the number of images in the disk cache 196 | */ 197 | - (NSUInteger)getDiskCount; 198 | 199 | /** 200 | * Asynchronously calculate the disk cache's size. 201 | */ 202 | - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock; 203 | 204 | /** 205 | * Async check if image exists in disk cache already (does not load the image) 206 | * 207 | * @param key the key describing the url 208 | * @param completionBlock the block to be executed when the check is done. 209 | * @note the completion block will be always executed on the main queue 210 | */ 211 | - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock; 212 | 213 | /** 214 | * Check if image exists in disk cache already (does not load the image) 215 | * 216 | * @param key the key describing the url 217 | * 218 | * @return YES if an image exists for the given key 219 | */ 220 | - (BOOL)diskImageExistsWithKey:(NSString *)key; 221 | 222 | /** 223 | * Get the cache path for a certain key (needs the cache path root folder) 224 | * 225 | * @param key the key (can be obtained from url using cacheKeyForURL) 226 | * @param path the cach path root folder 227 | * 228 | * @return the cache path 229 | */ 230 | - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path; 231 | 232 | /** 233 | * Get the default cache path for a certain key 234 | * 235 | * @param key the key (can be obtained from url using cacheKeyForURL) 236 | * 237 | * @return the default cache path 238 | */ 239 | - (NSString *)defaultCachePathForKey:(NSString *)key; 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageCompat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Jamie Pinkham 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import 11 | 12 | #ifdef __OBJC_GC__ 13 | #error SDWebImage does not support Objective-C Garbage Collection 14 | #endif 15 | 16 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 17 | #error SDWebImage doesn't support Deployement Target version < 5.0 18 | #endif 19 | 20 | #if !TARGET_OS_IPHONE 21 | #import 22 | #ifndef UIImage 23 | #define UIImage NSImage 24 | #endif 25 | #ifndef UIImageView 26 | #define UIImageView NSImageView 27 | #endif 28 | #else 29 | 30 | #import 31 | 32 | #endif 33 | 34 | #ifndef NS_ENUM 35 | #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type 36 | #endif 37 | 38 | #ifndef NS_OPTIONS 39 | #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type 40 | #endif 41 | 42 | #if OS_OBJECT_USE_OBJC 43 | #undef SDDispatchQueueRelease 44 | #undef SDDispatchQueueSetterSementics 45 | #define SDDispatchQueueRelease(q) 46 | #define SDDispatchQueueSetterSementics strong 47 | #else 48 | #undef SDDispatchQueueRelease 49 | #undef SDDispatchQueueSetterSementics 50 | #define SDDispatchQueueRelease(q) (dispatch_release(q)) 51 | #define SDDispatchQueueSetterSementics assign 52 | #endif 53 | 54 | extern UIImage *SDScaledImageForKey(NSString *key, UIImage *image); 55 | 56 | typedef void(^SDWebImageNoParamsBlock)(); 57 | 58 | #define dispatch_main_sync_safe(block)\ 59 | if ([NSThread isMainThread]) {\ 60 | block();\ 61 | } else {\ 62 | dispatch_sync(dispatch_get_main_queue(), block);\ 63 | } 64 | 65 | #define dispatch_main_async_safe(block)\ 66 | if ([NSThread isMainThread]) {\ 67 | block();\ 68 | } else {\ 69 | dispatch_async(dispatch_get_main_queue(), block);\ 70 | } 71 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageCompat.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDWebImageCompat.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 11/12/12. 6 | // Copyright (c) 2012 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "SDWebImageCompat.h" 10 | 11 | #if !__has_feature(objc_arc) 12 | #error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag 13 | #endif 14 | 15 | inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) { 16 | if (!image) { 17 | return nil; 18 | } 19 | 20 | if ([image.images count] > 0) { 21 | NSMutableArray *scaledImages = [NSMutableArray array]; 22 | 23 | for (UIImage *tempImage in image.images) { 24 | [scaledImages addObject:SDScaledImageForKey(key, tempImage)]; 25 | } 26 | 27 | return [UIImage animatedImageWithImages:scaledImages duration:image.duration]; 28 | } 29 | else { 30 | if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { 31 | CGFloat scale = 1.0; 32 | if (key.length >= 8) { 33 | // Search @2x. at the end of the string, before a 3 to 4 extension length (only if key len is 8 or more @2x. + 4 len ext) 34 | NSRange range = [key rangeOfString:@"@2x." options:0 range:NSMakeRange(key.length - 8, 5)]; 35 | if (range.location != NSNotFound) { 36 | scale = 2.0; 37 | } 38 | } 39 | 40 | UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; 41 | image = scaledImage; 42 | } 43 | return image; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageDecoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * Created by james on 9/28/11. 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | #import 12 | #import "SDWebImageCompat.h" 13 | 14 | @interface UIImage (ForceDecode) 15 | 16 | + (UIImage *)decodedImageWithImage:(UIImage *)image; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageDecoder.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * Created by james on 9/28/11. 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | #import "SDWebImageDecoder.h" 12 | 13 | @implementation UIImage (ForceDecode) 14 | 15 | + (UIImage *)decodedImageWithImage:(UIImage *)image { 16 | if (image.images) { 17 | // Do not decode animated images 18 | return image; 19 | } 20 | 21 | CGImageRef imageRef = image.CGImage; 22 | CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); 23 | CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize}; 24 | 25 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 26 | CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef); 27 | 28 | int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask); 29 | BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone || 30 | infoMask == kCGImageAlphaNoneSkipFirst || 31 | infoMask == kCGImageAlphaNoneSkipLast); 32 | 33 | // CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB. 34 | // https://developer.apple.com/library/mac/#qa/qa1037/_index.html 35 | if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) { 36 | // Unset the old alpha info. 37 | bitmapInfo &= ~kCGBitmapAlphaInfoMask; 38 | 39 | // Set noneSkipFirst. 40 | bitmapInfo |= kCGImageAlphaNoneSkipFirst; 41 | } 42 | // Some PNGs tell us they have alpha but only 3 components. Odd. 43 | else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) { 44 | // Unset the old alpha info. 45 | bitmapInfo &= ~kCGBitmapAlphaInfoMask; 46 | bitmapInfo |= kCGImageAlphaPremultipliedFirst; 47 | } 48 | 49 | // It calculates the bytes-per-row based on the bitsPerComponent and width arguments. 50 | CGContextRef context = CGBitmapContextCreate(NULL, 51 | imageSize.width, 52 | imageSize.height, 53 | CGImageGetBitsPerComponent(imageRef), 54 | 0, 55 | colorSpace, 56 | bitmapInfo); 57 | CGColorSpaceRelease(colorSpace); 58 | 59 | // If failed, return undecompressed image 60 | if (!context) return image; 61 | 62 | CGContextDrawImage(context, imageRect, imageRef); 63 | CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context); 64 | 65 | CGContextRelease(context); 66 | 67 | UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation]; 68 | CGImageRelease(decompressedImageRef); 69 | return decompressedImage; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageDownloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageCompat.h" 11 | #import "SDWebImageOperation.h" 12 | 13 | typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) { 14 | SDWebImageDownloaderLowPriority = 1 << 0, 15 | SDWebImageDownloaderProgressiveDownload = 1 << 1, 16 | 17 | /** 18 | * By default, request prevent the of NSURLCache. With this flag, NSURLCache 19 | * is used with default policies. 20 | */ 21 | SDWebImageDownloaderUseNSURLCache = 1 << 2, 22 | 23 | /** 24 | * Call completion block with nil image/imageData if the image was read from NSURLCache 25 | * (to be combined with `SDWebImageDownloaderUseNSURLCache`). 26 | */ 27 | 28 | SDWebImageDownloaderIgnoreCachedResponse = 1 << 3, 29 | /** 30 | * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for 31 | * extra time in background to let the request finish. If the background task expires the operation will be cancelled. 32 | */ 33 | 34 | SDWebImageDownloaderContinueInBackground = 1 << 4, 35 | 36 | /** 37 | * Handles cookies stored in NSHTTPCookieStore by setting 38 | * NSMutableURLRequest.HTTPShouldHandleCookies = YES; 39 | */ 40 | SDWebImageDownloaderHandleCookies = 1 << 5, 41 | 42 | /** 43 | * Enable to allow untrusted SSL ceriticates. 44 | * Useful for testing purposes. Use with caution in production. 45 | */ 46 | SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6, 47 | 48 | /** 49 | * Put the image in the high priority queue. 50 | */ 51 | SDWebImageDownloaderHighPriority = 1 << 7, 52 | 53 | 54 | }; 55 | 56 | typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { 57 | /** 58 | * Default value. All download operations will execute in queue style (first-in-first-out). 59 | */ 60 | SDWebImageDownloaderFIFOExecutionOrder, 61 | 62 | /** 63 | * All download operations will execute in stack style (last-in-first-out). 64 | */ 65 | SDWebImageDownloaderLIFOExecutionOrder 66 | }; 67 | 68 | extern NSString *const SDWebImageDownloadStartNotification; 69 | extern NSString *const SDWebImageDownloadStopNotification; 70 | 71 | typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize); 72 | 73 | typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished); 74 | 75 | typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers); 76 | 77 | /** 78 | * Asynchronous downloader dedicated and optimized for image loading. 79 | */ 80 | @interface SDWebImageDownloader : NSObject 81 | 82 | @property (assign, nonatomic) NSInteger maxConcurrentDownloads; 83 | 84 | /** 85 | * Shows the current amount of downloads that still need to be downloaded 86 | */ 87 | 88 | @property (readonly, nonatomic) NSUInteger currentDownloadCount; 89 | 90 | 91 | /** 92 | * The timeout value (in seconds) for the download operation. Default: 15.0. 93 | */ 94 | @property (assign, nonatomic) NSTimeInterval downloadTimeout; 95 | 96 | 97 | /** 98 | * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`. 99 | */ 100 | @property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder; 101 | 102 | /** 103 | * Singleton method, returns the shared instance 104 | * 105 | * @return global shared instance of downloader class 106 | */ 107 | + (SDWebImageDownloader *)sharedDownloader; 108 | 109 | /** 110 | * Set username 111 | */ 112 | @property (strong, nonatomic) NSString *username; 113 | 114 | /** 115 | * Set password 116 | */ 117 | @property (strong, nonatomic) NSString *password; 118 | 119 | /** 120 | * Set filter to pick headers for downloading image HTTP request. 121 | * 122 | * This block will be invoked for each downloading image request, returned 123 | * NSDictionary will be used as headers in corresponding HTTP request. 124 | */ 125 | @property (nonatomic, copy) SDWebImageDownloaderHeadersFilterBlock headersFilter; 126 | 127 | /** 128 | * Set a value for a HTTP header to be appended to each download HTTP request. 129 | * 130 | * @param value The value for the header field. Use `nil` value to remove the header. 131 | * @param field The name of the header field to set. 132 | */ 133 | - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field; 134 | 135 | /** 136 | * Returns the value of the specified HTTP header field. 137 | * 138 | * @return The value associated with the header field field, or `nil` if there is no corresponding header field. 139 | */ 140 | - (NSString *)valueForHTTPHeaderField:(NSString *)field; 141 | 142 | /** 143 | * Sets a subclass of `SDWebImageDownloaderOperation` as the default 144 | * `NSOperation` to be used each time SDWebImage constructs a request 145 | * operation to download an image. 146 | * 147 | * @param operationClass The subclass of `SDWebImageDownloaderOperation` to set 148 | * as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`. 149 | */ 150 | - (void)setOperationClass:(Class)operationClass; 151 | 152 | /** 153 | * Creates a SDWebImageDownloader async downloader instance with a given URL 154 | * 155 | * The delegate will be informed when the image is finish downloaded or an error has happen. 156 | * 157 | * @see SDWebImageDownloaderDelegate 158 | * 159 | * @param url The URL to the image to download 160 | * @param options The options to be used for this download 161 | * @param progressBlock A block called repeatedly while the image is downloading 162 | * @param completedBlock A block called once the download is completed. 163 | * If the download succeeded, the image parameter is set, in case of error, 164 | * error parameter is set with the error. The last parameter is always YES 165 | * if SDWebImageDownloaderProgressiveDownload isn't use. With the 166 | * SDWebImageDownloaderProgressiveDownload option, this block is called 167 | * repeatedly with the partial image object and the finished argument set to NO 168 | * before to be called a last time with the full image and finished argument 169 | * set to YES. In case of error, the finished argument is always YES. 170 | * 171 | * @return A cancellable SDWebImageOperation 172 | */ 173 | - (id )downloadImageWithURL:(NSURL *)url 174 | options:(SDWebImageDownloaderOptions)options 175 | progress:(SDWebImageDownloaderProgressBlock)progressBlock 176 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock; 177 | 178 | /** 179 | * Sets the download queue suspension state 180 | */ 181 | - (void)setSuspended:(BOOL)suspended; 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageDownloaderOperation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageDownloader.h" 11 | #import "SDWebImageOperation.h" 12 | 13 | @interface SDWebImageDownloaderOperation : NSOperation 14 | 15 | /** 16 | * The request used by the operation's connection. 17 | */ 18 | @property (strong, nonatomic, readonly) NSURLRequest *request; 19 | 20 | /** 21 | * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. 22 | * 23 | * This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`. 24 | */ 25 | @property (nonatomic, assign) BOOL shouldUseCredentialStorage; 26 | 27 | /** 28 | * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. 29 | * 30 | * This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. 31 | */ 32 | @property (nonatomic, strong) NSURLCredential *credential; 33 | 34 | /** 35 | * The SDWebImageDownloaderOptions for the receiver. 36 | */ 37 | @property (assign, nonatomic, readonly) SDWebImageDownloaderOptions options; 38 | 39 | /** 40 | * Initializes a `SDWebImageDownloaderOperation` object 41 | * 42 | * @see SDWebImageDownloaderOperation 43 | * 44 | * @param request the URL request 45 | * @param options downloader options 46 | * @param progressBlock the block executed when a new chunk of data arrives. 47 | * @note the progress block is executed on a background queue 48 | * @param completedBlock the block executed when the download is done. 49 | * @note the completed block is executed on the main queue for success. If errors are found, there is a chance the block will be executed on a background queue 50 | * @param cancelBlock the block executed if the download (operation) is cancelled 51 | * 52 | * @return the initialized instance 53 | */ 54 | - (id)initWithRequest:(NSURLRequest *)request 55 | options:(SDWebImageDownloaderOptions)options 56 | progress:(SDWebImageDownloaderProgressBlock)progressBlock 57 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock 58 | cancelled:(SDWebImageNoParamsBlock)cancelBlock; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImageOperation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | @protocol SDWebImageOperation 12 | 13 | - (void)cancel; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImagePrefetcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageManager.h" 11 | 12 | @class SDWebImagePrefetcher; 13 | 14 | @protocol SDWebImagePrefetcherDelegate 15 | 16 | @optional 17 | 18 | /** 19 | * Called when an image was prefetched. 20 | * 21 | * @param imagePrefetcher The current image prefetcher 22 | * @param imageURL The image url that was prefetched 23 | * @param finishedCount The total number of images that were prefetched (successful or not) 24 | * @param totalCount The total number of images that were to be prefetched 25 | */ 26 | - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount; 27 | 28 | /** 29 | * Called when all images are prefetched. 30 | * @param imagePrefetcher The current image prefetcher 31 | * @param totalCount The total number of images that were prefetched (whether successful or not) 32 | * @param skippedCount The total number of images that were skipped 33 | */ 34 | - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount; 35 | 36 | @end 37 | 38 | typedef void(^SDWebImagePrefetcherProgressBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls); 39 | typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls); 40 | 41 | /** 42 | * Prefetch some URLs in the cache for future use. Images are downloaded in low priority. 43 | */ 44 | @interface SDWebImagePrefetcher : NSObject 45 | 46 | /** 47 | * The web image manager 48 | */ 49 | @property (strong, nonatomic, readonly) SDWebImageManager *manager; 50 | 51 | /** 52 | * Maximum number of URLs to prefetch at the same time. Defaults to 3. 53 | */ 54 | @property (nonatomic, assign) NSUInteger maxConcurrentDownloads; 55 | 56 | /** 57 | * SDWebImageOptions for prefetcher. Defaults to SDWebImageLowPriority. 58 | */ 59 | @property (nonatomic, assign) SDWebImageOptions options; 60 | 61 | @property (weak, nonatomic) id delegate; 62 | 63 | /** 64 | * Return the global image prefetcher instance. 65 | */ 66 | + (SDWebImagePrefetcher *)sharedImagePrefetcher; 67 | 68 | /** 69 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, 70 | * currently one image is downloaded at a time, 71 | * and skips images for failed downloads and proceed to the next image in the list 72 | * 73 | * @param urls list of URLs to prefetch 74 | */ 75 | - (void)prefetchURLs:(NSArray *)urls; 76 | 77 | /** 78 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, 79 | * currently one image is downloaded at a time, 80 | * and skips images for failed downloads and proceed to the next image in the list 81 | * 82 | * @param urls list of URLs to prefetch 83 | * @param progressBlock block to be called when progress updates; 84 | * first parameter is the number of completed (successful or not) requests, 85 | * second parameter is the total number of images originally requested to be prefetched 86 | * @param completionBlock block to be called when prefetching is completed 87 | * first param is the number of completed (successful or not) requests, 88 | * second parameter is the number of skipped requests 89 | */ 90 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock; 91 | 92 | /** 93 | * Remove and cancel queued list 94 | */ 95 | - (void)cancelPrefetching; 96 | 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/SDWebImagePrefetcher.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDWebImagePrefetcher.h" 10 | 11 | #if (!defined(DEBUG) && !defined (SD_VERBOSE)) || defined(SD_LOG_NONE) 12 | #define NSLog(...) 13 | #endif 14 | 15 | @interface SDWebImagePrefetcher () 16 | 17 | @property (strong, nonatomic) SDWebImageManager *manager; 18 | @property (strong, nonatomic) NSArray *prefetchURLs; 19 | @property (assign, nonatomic) NSUInteger requestedCount; 20 | @property (assign, nonatomic) NSUInteger skippedCount; 21 | @property (assign, nonatomic) NSUInteger finishedCount; 22 | @property (assign, nonatomic) NSTimeInterval startedTime; 23 | @property (copy, nonatomic) SDWebImagePrefetcherCompletionBlock completionBlock; 24 | @property (copy, nonatomic) SDWebImagePrefetcherProgressBlock progressBlock; 25 | 26 | @end 27 | 28 | @implementation SDWebImagePrefetcher 29 | 30 | + (SDWebImagePrefetcher *)sharedImagePrefetcher { 31 | static dispatch_once_t once; 32 | static id instance; 33 | dispatch_once(&once, ^{ 34 | instance = [self new]; 35 | }); 36 | return instance; 37 | } 38 | 39 | - (id)init { 40 | if ((self = [super init])) { 41 | _manager = [SDWebImageManager new]; 42 | _options = SDWebImageLowPriority; 43 | self.maxConcurrentDownloads = 3; 44 | } 45 | return self; 46 | } 47 | 48 | - (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads { 49 | self.manager.imageDownloader.maxConcurrentDownloads = maxConcurrentDownloads; 50 | } 51 | 52 | - (NSUInteger)maxConcurrentDownloads { 53 | return self.manager.imageDownloader.maxConcurrentDownloads; 54 | } 55 | 56 | - (void)startPrefetchingAtIndex:(NSUInteger)index { 57 | if (index >= self.prefetchURLs.count) return; 58 | self.requestedCount++; 59 | [self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 60 | if (!finished) return; 61 | self.finishedCount++; 62 | 63 | if (image) { 64 | if (self.progressBlock) { 65 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]); 66 | } 67 | NSLog(@"Prefetched %@ out of %@", @(self.finishedCount), @(self.prefetchURLs.count)); 68 | } 69 | else { 70 | if (self.progressBlock) { 71 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]); 72 | } 73 | NSLog(@"Prefetched %@ out of %@ (Failed)", @(self.finishedCount), @(self.prefetchURLs.count)); 74 | 75 | // Add last failed 76 | self.skippedCount++; 77 | } 78 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) { 79 | [self.delegate imagePrefetcher:self 80 | didPrefetchURL:self.prefetchURLs[index] 81 | finishedCount:self.finishedCount 82 | totalCount:self.prefetchURLs.count 83 | ]; 84 | } 85 | 86 | if (self.prefetchURLs.count > self.requestedCount) { 87 | dispatch_async(dispatch_get_main_queue(), ^{ 88 | [self startPrefetchingAtIndex:self.requestedCount]; 89 | }); 90 | } 91 | else if (self.finishedCount == self.requestedCount) { 92 | [self reportStatus]; 93 | if (self.completionBlock) { 94 | self.completionBlock(self.finishedCount, self.skippedCount); 95 | self.completionBlock = nil; 96 | } 97 | } 98 | }]; 99 | } 100 | 101 | - (void)reportStatus { 102 | NSUInteger total = [self.prefetchURLs count]; 103 | NSLog(@"Finished prefetching (%@ successful, %@ skipped, timeElasped %.2f)", @(total - self.skippedCount), @(self.skippedCount), CFAbsoluteTimeGetCurrent() - self.startedTime); 104 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) { 105 | [self.delegate imagePrefetcher:self 106 | didFinishWithTotalCount:(total - self.skippedCount) 107 | skippedCount:self.skippedCount 108 | ]; 109 | } 110 | } 111 | 112 | - (void)prefetchURLs:(NSArray *)urls { 113 | [self prefetchURLs:urls progress:nil completed:nil]; 114 | } 115 | 116 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock { 117 | [self cancelPrefetching]; // Prevent duplicate prefetch request 118 | self.startedTime = CFAbsoluteTimeGetCurrent(); 119 | self.prefetchURLs = urls; 120 | self.completionBlock = completionBlock; 121 | self.progressBlock = progressBlock; 122 | 123 | if(urls.count == 0){ 124 | if(completionBlock){ 125 | completionBlock(0,0); 126 | } 127 | }else{ 128 | // Starts prefetching from the very first image on the list with the max allowed concurrency 129 | NSUInteger listCount = self.prefetchURLs.count; 130 | for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) { 131 | [self startPrefetchingAtIndex:i]; 132 | } 133 | } 134 | } 135 | 136 | - (void)cancelPrefetching { 137 | self.prefetchURLs = nil; 138 | self.skippedCount = 0; 139 | self.requestedCount = 0; 140 | self.finishedCount = 0; 141 | [self.manager cancelAll]; 142 | } 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIButton+WebCache.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIButton+WebCache.h" 10 | #import "objc/runtime.h" 11 | #import "UIView+WebCacheOperation.h" 12 | 13 | static char imageURLStorageKey; 14 | 15 | @implementation UIButton (WebCache) 16 | 17 | - (NSURL *)sd_currentImageURL { 18 | NSURL *url = self.imageURLStorage[@(self.state)]; 19 | 20 | if (!url) { 21 | url = self.imageURLStorage[@(UIControlStateNormal)]; 22 | } 23 | 24 | return url; 25 | } 26 | 27 | - (NSURL *)sd_imageURLForState:(UIControlState)state { 28 | return self.imageURLStorage[@(state)]; 29 | } 30 | 31 | - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state { 32 | [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil]; 33 | } 34 | 35 | - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder { 36 | [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil]; 37 | } 38 | 39 | - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 40 | [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; 41 | } 42 | 43 | - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock { 44 | [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock]; 45 | } 46 | 47 | - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { 48 | [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock]; 49 | } 50 | 51 | - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 52 | 53 | [self setImage:placeholder forState:state]; 54 | [self sd_cancelImageLoadForState:state]; 55 | 56 | if (!url) { 57 | [self.imageURLStorage removeObjectForKey:@(state)]; 58 | 59 | dispatch_main_async_safe(^{ 60 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 61 | if (completedBlock) { 62 | completedBlock(nil, error, SDImageCacheTypeNone, url); 63 | } 64 | }); 65 | 66 | return; 67 | } 68 | 69 | self.imageURLStorage[@(state)] = url; 70 | 71 | __weak UIButton *wself = self; 72 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 73 | if (!wself) return; 74 | dispatch_main_sync_safe(^{ 75 | __strong UIButton *sself = wself; 76 | if (!sself) return; 77 | if (image) { 78 | [sself setImage:image forState:state]; 79 | } 80 | if (completedBlock && finished) { 81 | completedBlock(image, error, cacheType, url); 82 | } 83 | }); 84 | }]; 85 | [self sd_setImageLoadOperation:operation forState:state]; 86 | } 87 | 88 | - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state { 89 | [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil]; 90 | } 91 | 92 | - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder { 93 | [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil]; 94 | } 95 | 96 | - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 97 | [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; 98 | } 99 | 100 | - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock { 101 | [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock]; 102 | } 103 | 104 | - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { 105 | [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock]; 106 | } 107 | 108 | - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 109 | [self sd_cancelImageLoadForState:state]; 110 | 111 | [self setBackgroundImage:placeholder forState:state]; 112 | 113 | if (url) { 114 | __weak UIButton *wself = self; 115 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 116 | if (!wself) return; 117 | dispatch_main_sync_safe(^{ 118 | __strong UIButton *sself = wself; 119 | if (!sself) return; 120 | if (image) { 121 | [sself setBackgroundImage:image forState:state]; 122 | } 123 | if (completedBlock && finished) { 124 | completedBlock(image, error, cacheType, url); 125 | } 126 | }); 127 | }]; 128 | [self sd_setBackgroundImageLoadOperation:operation forState:state]; 129 | } else { 130 | dispatch_main_async_safe(^{ 131 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 132 | if (completedBlock) { 133 | completedBlock(nil, error, SDImageCacheTypeNone, url); 134 | } 135 | }); 136 | } 137 | } 138 | 139 | - (void)sd_setImageLoadOperation:(id)operation forState:(UIControlState)state { 140 | [self sd_setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]]; 141 | } 142 | 143 | - (void)sd_cancelImageLoadForState:(UIControlState)state { 144 | [self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]]; 145 | } 146 | 147 | - (void)sd_setBackgroundImageLoadOperation:(id)operation forState:(UIControlState)state { 148 | [self sd_setImageLoadOperation:operation forKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]]; 149 | } 150 | 151 | - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state { 152 | [self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]]; 153 | } 154 | 155 | - (NSMutableDictionary *)imageURLStorage { 156 | NSMutableDictionary *storage = objc_getAssociatedObject(self, &imageURLStorageKey); 157 | if (!storage) 158 | { 159 | storage = [NSMutableDictionary dictionary]; 160 | objc_setAssociatedObject(self, &imageURLStorageKey, storage, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 161 | } 162 | 163 | return storage; 164 | } 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImage+GIF.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GIF.h 3 | // LBGIFImage 4 | // 5 | // Created by Laurin Brandner on 06.01.12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (GIF) 12 | 13 | + (UIImage *)sd_animatedGIFNamed:(NSString *)name; 14 | 15 | + (UIImage *)sd_animatedGIFWithData:(NSData *)data; 16 | 17 | - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImage+GIF.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GIF.m 3 | // LBGIFImage 4 | // 5 | // Created by Laurin Brandner on 06.01.12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "UIImage+GIF.h" 10 | #import 11 | 12 | @implementation UIImage (GIF) 13 | 14 | + (UIImage *)sd_animatedGIFWithData:(NSData *)data { 15 | if (!data) { 16 | return nil; 17 | } 18 | 19 | CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); 20 | 21 | size_t count = CGImageSourceGetCount(source); 22 | 23 | UIImage *animatedImage; 24 | 25 | if (count <= 1) { 26 | animatedImage = [[UIImage alloc] initWithData:data]; 27 | } 28 | else { 29 | NSMutableArray *images = [NSMutableArray array]; 30 | 31 | NSTimeInterval duration = 0.0f; 32 | 33 | for (size_t i = 0; i < count; i++) { 34 | CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); 35 | 36 | duration += [self sd_frameDurationAtIndex:i source:source]; 37 | 38 | [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; 39 | 40 | CGImageRelease(image); 41 | } 42 | 43 | if (!duration) { 44 | duration = (1.0f / 10.0f) * count; 45 | } 46 | 47 | animatedImage = [UIImage animatedImageWithImages:images duration:duration]; 48 | } 49 | 50 | CFRelease(source); 51 | 52 | return animatedImage; 53 | } 54 | 55 | + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { 56 | float frameDuration = 0.1f; 57 | CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); 58 | NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; 59 | NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; 60 | 61 | NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; 62 | if (delayTimeUnclampedProp) { 63 | frameDuration = [delayTimeUnclampedProp floatValue]; 64 | } 65 | else { 66 | 67 | NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; 68 | if (delayTimeProp) { 69 | frameDuration = [delayTimeProp floatValue]; 70 | } 71 | } 72 | 73 | // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. 74 | // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify 75 | // a duration of <= 10 ms. See and 76 | // for more information. 77 | 78 | if (frameDuration < 0.011f) { 79 | frameDuration = 0.100f; 80 | } 81 | 82 | CFRelease(cfFrameProperties); 83 | return frameDuration; 84 | } 85 | 86 | + (UIImage *)sd_animatedGIFNamed:(NSString *)name { 87 | CGFloat scale = [UIScreen mainScreen].scale; 88 | 89 | if (scale > 1.0f) { 90 | NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"]; 91 | 92 | NSData *data = [NSData dataWithContentsOfFile:retinaPath]; 93 | 94 | if (data) { 95 | return [UIImage sd_animatedGIFWithData:data]; 96 | } 97 | 98 | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; 99 | 100 | data = [NSData dataWithContentsOfFile:path]; 101 | 102 | if (data) { 103 | return [UIImage sd_animatedGIFWithData:data]; 104 | } 105 | 106 | return [UIImage imageNamed:name]; 107 | } 108 | else { 109 | NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; 110 | 111 | NSData *data = [NSData dataWithContentsOfFile:path]; 112 | 113 | if (data) { 114 | return [UIImage sd_animatedGIFWithData:data]; 115 | } 116 | 117 | return [UIImage imageNamed:name]; 118 | } 119 | } 120 | 121 | - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size { 122 | if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { 123 | return self; 124 | } 125 | 126 | CGSize scaledSize = size; 127 | CGPoint thumbnailPoint = CGPointZero; 128 | 129 | CGFloat widthFactor = size.width / self.size.width; 130 | CGFloat heightFactor = size.height / self.size.height; 131 | CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor; 132 | scaledSize.width = self.size.width * scaleFactor; 133 | scaledSize.height = self.size.height * scaleFactor; 134 | 135 | if (widthFactor > heightFactor) { 136 | thumbnailPoint.y = (size.height - scaledSize.height) * 0.5; 137 | } 138 | else if (widthFactor < heightFactor) { 139 | thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; 140 | } 141 | 142 | NSMutableArray *scaledImages = [NSMutableArray array]; 143 | 144 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 145 | 146 | for (UIImage *image in self.images) { 147 | [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)]; 148 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 149 | 150 | [scaledImages addObject:newImage]; 151 | } 152 | 153 | UIGraphicsEndImageContext(); 154 | 155 | return [UIImage animatedImageWithImages:scaledImages duration:self.duration]; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImage+MultiFormat.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+MultiFormat.h 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (MultiFormat) 12 | 13 | + (UIImage *)sd_imageWithData:(NSData *)data; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImage+MultiFormat.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+MultiFormat.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #import "UIImage+MultiFormat.h" 10 | #import "UIImage+GIF.h" 11 | #import "NSData+ImageContentType.h" 12 | #import 13 | 14 | #ifdef SD_WEBP 15 | #import "UIImage+WebP.h" 16 | #endif 17 | 18 | @implementation UIImage (MultiFormat) 19 | 20 | + (UIImage *)sd_imageWithData:(NSData *)data { 21 | UIImage *image; 22 | NSString *imageContentType = [NSData sd_contentTypeForImageData:data]; 23 | if ([imageContentType isEqualToString:@"image/gif"]) { 24 | image = [UIImage sd_animatedGIFWithData:data]; 25 | } 26 | #ifdef SD_WEBP 27 | else if ([imageContentType isEqualToString:@"image/webp"]) 28 | { 29 | image = [UIImage sd_imageWithWebPData:data]; 30 | } 31 | #endif 32 | else { 33 | image = [[UIImage alloc] initWithData:data]; 34 | UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data]; 35 | if (orientation != UIImageOrientationUp) { 36 | image = [UIImage imageWithCGImage:image.CGImage 37 | scale:image.scale 38 | orientation:orientation]; 39 | } 40 | } 41 | 42 | 43 | return image; 44 | } 45 | 46 | 47 | +(UIImageOrientation)sd_imageOrientationFromImageData:(NSData *)imageData { 48 | UIImageOrientation result = UIImageOrientationUp; 49 | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); 50 | if (imageSource) { 51 | CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); 52 | if (properties) { 53 | CFTypeRef val; 54 | int exifOrientation; 55 | val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation); 56 | if (val) { 57 | CFNumberGetValue(val, kCFNumberIntType, &exifOrientation); 58 | result = [self sd_exifOrientationToiOSOrientation:exifOrientation]; 59 | } // else - if it's not set it remains at up 60 | CFRelease((CFTypeRef) properties); 61 | } else { 62 | //NSLog(@"NO PROPERTIES, FAIL"); 63 | } 64 | CFRelease(imageSource); 65 | } 66 | return result; 67 | } 68 | 69 | #pragma mark EXIF orientation tag converter 70 | // Convert an EXIF image orientation to an iOS one. 71 | // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html 72 | + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation { 73 | UIImageOrientation orientation = UIImageOrientationUp; 74 | switch (exifOrientation) { 75 | case 1: 76 | orientation = UIImageOrientationUp; 77 | break; 78 | 79 | case 3: 80 | orientation = UIImageOrientationDown; 81 | break; 82 | 83 | case 8: 84 | orientation = UIImageOrientationLeft; 85 | break; 86 | 87 | case 6: 88 | orientation = UIImageOrientationRight; 89 | break; 90 | 91 | case 2: 92 | orientation = UIImageOrientationUpMirrored; 93 | break; 94 | 95 | case 4: 96 | orientation = UIImageOrientationDownMirrored; 97 | break; 98 | 99 | case 5: 100 | orientation = UIImageOrientationLeftMirrored; 101 | break; 102 | 103 | case 7: 104 | orientation = UIImageOrientationRightMirrored; 105 | break; 106 | default: 107 | break; 108 | } 109 | return orientation; 110 | } 111 | 112 | 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImage+WebP.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+WebP.h 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #ifdef SD_WEBP 10 | 11 | #import 12 | 13 | // Fix for issue #416 Undefined symbols for architecture armv7 since WebP introduction when deploying to device 14 | void WebPInitPremultiplyNEON(void); 15 | 16 | void WebPInitUpsamplersNEON(void); 17 | 18 | void VP8DspInitNEON(void); 19 | 20 | @interface UIImage (WebP) 21 | 22 | + (UIImage *)sd_imageWithWebPData:(NSData *)data; 23 | 24 | @end 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImage+WebP.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+WebP.m 3 | // SDWebImage 4 | // 5 | // Created by Olivier Poitrey on 07/06/13. 6 | // Copyright (c) 2013 Dailymotion. All rights reserved. 7 | // 8 | 9 | #ifdef SD_WEBP 10 | #import "UIImage+WebP.h" 11 | #import "webp/decode.h" 12 | 13 | // Callback for CGDataProviderRelease 14 | static void FreeImageData(void *info, const void *data, size_t size) 15 | { 16 | free((void *)data); 17 | } 18 | 19 | @implementation UIImage (WebP) 20 | 21 | + (UIImage *)sd_imageWithWebPData:(NSData *)data { 22 | WebPDecoderConfig config; 23 | if (!WebPInitDecoderConfig(&config)) { 24 | return nil; 25 | } 26 | 27 | if (WebPGetFeatures(data.bytes, data.length, &config.input) != VP8_STATUS_OK) { 28 | return nil; 29 | } 30 | 31 | config.output.colorspace = config.input.has_alpha ? MODE_rgbA : MODE_RGB; 32 | config.options.use_threads = 1; 33 | 34 | // Decode the WebP image data into a RGBA value array. 35 | if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK) { 36 | return nil; 37 | } 38 | 39 | int width = config.input.width; 40 | int height = config.input.height; 41 | if (config.options.use_scaling) { 42 | width = config.options.scaled_width; 43 | height = config.options.scaled_height; 44 | } 45 | 46 | // Construct a UIImage from the decoded RGBA value array. 47 | CGDataProviderRef provider = 48 | CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData); 49 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 50 | CGBitmapInfo bitmapInfo = config.input.has_alpha ? kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast : 0; 51 | size_t components = config.input.has_alpha ? 4 : 3; 52 | CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 53 | CGImageRef imageRef = CGImageCreate(width, height, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 54 | 55 | CGColorSpaceRelease(colorSpaceRef); 56 | CGDataProviderRelease(provider); 57 | 58 | UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; 59 | CGImageRelease(imageRef); 60 | 61 | return image; 62 | } 63 | 64 | @end 65 | 66 | #if !COCOAPODS 67 | // Functions to resolve some undefined symbols when using WebP and force_load flag 68 | void WebPInitPremultiplyNEON(void) {} 69 | void WebPInitUpsamplersNEON(void) {} 70 | void VP8DspInitNEON(void) {} 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImageView+HighlightedWebCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageCompat.h" 11 | #import "SDWebImageManager.h" 12 | 13 | /** 14 | * Integrates SDWebImage async downloading and caching of remote images with UIImageView for highlighted state. 15 | */ 16 | @interface UIImageView (HighlightedWebCache) 17 | 18 | /** 19 | * Set the imageView `highlightedImage` with an `url`. 20 | * 21 | * The download is asynchronous and cached. 22 | * 23 | * @param url The url for the image. 24 | */ 25 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url; 26 | 27 | /** 28 | * Set the imageView `highlightedImage` with an `url` and custom options. 29 | * 30 | * The download is asynchronous and cached. 31 | * 32 | * @param url The url for the image. 33 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 34 | */ 35 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options; 36 | 37 | /** 38 | * Set the imageView `highlightedImage` with an `url`. 39 | * 40 | * The download is asynchronous and cached. 41 | * 42 | * @param url The url for the image. 43 | * @param completedBlock A block called when operation has been completed. This block has no return value 44 | * and takes the requested UIImage as first parameter. In case of error the image parameter 45 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 46 | * indicating if the image was retrived from the local cache or from the network. 47 | * The fourth parameter is the original image url. 48 | */ 49 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; 50 | 51 | /** 52 | * Set the imageView `highlightedImage` with an `url` and custom options. 53 | * 54 | * The download is asynchronous and cached. 55 | * 56 | * @param url The url for the image. 57 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 58 | * @param completedBlock A block called when operation has been completed. This block has no return value 59 | * and takes the requested UIImage as first parameter. In case of error the image parameter 60 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 61 | * indicating if the image was retrived from the local cache or from the network. 62 | * The fourth parameter is the original image url. 63 | */ 64 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; 65 | 66 | /** 67 | * Set the imageView `highlightedImage` with an `url` and custom options. 68 | * 69 | * The download is asynchronous and cached. 70 | * 71 | * @param url The url for the image. 72 | * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. 73 | * @param progressBlock A block called while image is downloading 74 | * @param completedBlock A block called when operation has been completed. This block has no return value 75 | * and takes the requested UIImage as first parameter. In case of error the image parameter 76 | * is nil and the second parameter may contain an NSError. The third parameter is a Boolean 77 | * indicating if the image was retrived from the local cache or from the network. 78 | * The fourth parameter is the original image url. 79 | */ 80 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; 81 | 82 | /** 83 | * Cancel the current download 84 | */ 85 | - (void)sd_cancelCurrentHighlightedImageLoad; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImageView+HighlightedWebCache.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIImageView+HighlightedWebCache.h" 10 | #import "UIView+WebCacheOperation.h" 11 | 12 | #define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage" 13 | 14 | @implementation UIImageView (HighlightedWebCache) 15 | 16 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url { 17 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil]; 18 | } 19 | 20 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options { 21 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil]; 22 | } 23 | 24 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { 25 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock]; 26 | } 27 | 28 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 29 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock]; 30 | } 31 | 32 | - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { 33 | [self sd_cancelCurrentHighlightedImageLoad]; 34 | 35 | if (url) { 36 | __weak UIImageView *wself = self; 37 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 38 | if (!wself) return; 39 | dispatch_main_sync_safe (^ 40 | { 41 | if (!wself) return; 42 | if (image) { 43 | wself.highlightedImage = image; 44 | [wself setNeedsLayout]; 45 | } 46 | if (completedBlock && finished) { 47 | completedBlock(image, error, cacheType, url); 48 | } 49 | }); 50 | }]; 51 | [self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey]; 52 | } else { 53 | dispatch_main_async_safe(^{ 54 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 55 | if (completedBlock) { 56 | completedBlock(nil, error, SDImageCacheTypeNone, url); 57 | } 58 | }); 59 | } 60 | } 61 | 62 | - (void)sd_cancelCurrentHighlightedImageLoad { 63 | [self sd_cancelImageLoadOperationWithKey:UIImageViewHighlightedWebCacheOperationKey]; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIImageView+WebCache.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIImageView+WebCache.h" 10 | #import "objc/runtime.h" 11 | #import "UIView+WebCacheOperation.h" 12 | 13 | static char imageURLKey; 14 | 15 | @implementation UIImageView (WebCache) 16 | 17 | - (void)sd_setImageWithURL:(NSURL *)url { 18 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil]; 19 | } 20 | 21 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder { 22 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil]; 23 | } 24 | 25 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options { 26 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; 27 | } 28 | 29 | - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock { 30 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock]; 31 | } 32 | 33 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock { 34 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock]; 35 | } 36 | 37 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { 38 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock]; 39 | } 40 | 41 | - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { 42 | [self sd_cancelCurrentImageLoad]; 43 | objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 44 | 45 | if (!(options & SDWebImageDelayPlaceholder)) { 46 | dispatch_main_async_safe(^{ 47 | self.image = placeholder; 48 | }); 49 | } 50 | 51 | if (url) { 52 | __weak UIImageView *wself = self; 53 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 54 | if (!wself) return; 55 | dispatch_main_sync_safe(^{ 56 | if (!wself) return; 57 | if (image) { 58 | wself.image = image; 59 | [wself setNeedsLayout]; 60 | } else { 61 | if ((options & SDWebImageDelayPlaceholder)) { 62 | wself.image = placeholder; 63 | [wself setNeedsLayout]; 64 | } 65 | } 66 | if (completedBlock && finished) { 67 | completedBlock(image, error, cacheType, url); 68 | } 69 | }); 70 | }]; 71 | [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"]; 72 | } else { 73 | dispatch_main_async_safe(^{ 74 | NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; 75 | if (completedBlock) { 76 | completedBlock(nil, error, SDImageCacheTypeNone, url); 77 | } 78 | }); 79 | } 80 | } 81 | 82 | - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { 83 | NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url]; 84 | UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key]; 85 | 86 | [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock]; 87 | } 88 | 89 | - (NSURL *)sd_imageURL { 90 | return objc_getAssociatedObject(self, &imageURLKey); 91 | } 92 | 93 | - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs { 94 | [self sd_cancelCurrentAnimationImagesLoad]; 95 | __weak UIImageView *wself = self; 96 | 97 | NSMutableArray *operationsArray = [[NSMutableArray alloc] init]; 98 | 99 | for (NSURL *logoImageURL in arrayOfURLs) { 100 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 101 | if (!wself) return; 102 | dispatch_main_sync_safe(^{ 103 | __strong UIImageView *sself = wself; 104 | [sself stopAnimating]; 105 | if (sself && image) { 106 | NSMutableArray *currentImages = [[sself animationImages] mutableCopy]; 107 | if (!currentImages) { 108 | currentImages = [[NSMutableArray alloc] init]; 109 | } 110 | [currentImages addObject:image]; 111 | 112 | sself.animationImages = currentImages; 113 | [sself setNeedsLayout]; 114 | } 115 | [sself startAnimating]; 116 | }); 117 | }]; 118 | [operationsArray addObject:operation]; 119 | } 120 | 121 | [self sd_setImageLoadOperation:[NSArray arrayWithArray:operationsArray] forKey:@"UIImageViewAnimationImages"]; 122 | } 123 | 124 | - (void)sd_cancelCurrentImageLoad { 125 | [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"]; 126 | } 127 | 128 | - (void)sd_cancelCurrentAnimationImagesLoad { 129 | [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; 130 | } 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIView+WebCacheOperation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | #import "SDWebImageManager.h" 11 | 12 | @interface UIView (WebCacheOperation) 13 | 14 | /** 15 | * Set the image load operation (storage in a UIView based dictionary) 16 | * 17 | * @param operation the operation 18 | * @param key key for storing the operation 19 | */ 20 | - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key; 21 | 22 | /** 23 | * Cancel all operations for the current UIView and key 24 | * 25 | * @param key key for identifying the operations 26 | */ 27 | - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key; 28 | 29 | /** 30 | * Just remove the operations corresponding to the current UIView and key without cancelling them 31 | * 32 | * @param key key for identifying the operations 33 | */ 34 | - (void)sd_removeImageLoadOperationWithKey:(NSString *)key; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ZZPhotoKit/SDWebImage/UIView+WebCacheOperation.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "UIView+WebCacheOperation.h" 10 | #import "objc/runtime.h" 11 | 12 | static char loadOperationKey; 13 | 14 | @implementation UIView (WebCacheOperation) 15 | 16 | - (NSMutableDictionary *)operationDictionary { 17 | NSMutableDictionary *operations = objc_getAssociatedObject(self, &loadOperationKey); 18 | if (operations) { 19 | return operations; 20 | } 21 | operations = [NSMutableDictionary dictionary]; 22 | objc_setAssociatedObject(self, &loadOperationKey, operations, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | return operations; 24 | } 25 | 26 | - (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key { 27 | [self sd_cancelImageLoadOperationWithKey:key]; 28 | NSMutableDictionary *operationDictionary = [self operationDictionary]; 29 | [operationDictionary setObject:operation forKey:key]; 30 | } 31 | 32 | - (void)sd_cancelImageLoadOperationWithKey:(NSString *)key { 33 | // Cancel in progress downloader from queue 34 | NSMutableDictionary *operationDictionary = [self operationDictionary]; 35 | id operations = [operationDictionary objectForKey:key]; 36 | if (operations) { 37 | if ([operations isKindOfClass:[NSArray class]]) { 38 | for (id operation in operations) { 39 | if (operation) { 40 | [operation cancel]; 41 | } 42 | } 43 | } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){ 44 | [(id) operations cancel]; 45 | } 46 | [operationDictionary removeObjectForKey:key]; 47 | } 48 | } 49 | 50 | - (void)sd_removeImageLoadOperationWithKey:(NSString *)key { 51 | NSMutableDictionary *operationDictionary = [self operationDictionary]; 52 | [operationDictionary removeObjectForKey:key]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /ZZPhotoKit/SVProgressHUD/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/SVProgressHUD/.DS_Store -------------------------------------------------------------------------------- /ZZPhotoKit/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /ZZPhotoKit/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "ZZPhotoKit.h" 11 | #import "PicsCell.h" 12 | 13 | # 14 | 15 | @interface ViewController () 16 | 17 | @property(strong,nonatomic) UILabel *firstlab; 18 | @property(strong,nonatomic) UIImageView *imageView; 19 | @property(strong,nonatomic) UITableView *tableView; 20 | @property(strong,nonatomic) NSArray *array; 21 | 22 | @property(strong,nonatomic) UICollectionView *collectionView; 23 | @property(strong,nonatomic) UIButton *addBtn; 24 | @property(copy ,nonatomic) NSArray *picArray; 25 | 26 | @end 27 | 28 | @implementation ViewController 29 | -(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 30 | { 31 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 32 | if (self) { 33 | self.navigationItem.title = @"ZZPhotoKit"; 34 | } 35 | return self; 36 | } 37 | 38 | 39 | -(UIButton *)addBtn 40 | { 41 | if (!_addBtn) { 42 | CGFloat photoSize = ([UIScreen mainScreen].bounds.size.width - 30) / 4; 43 | _addBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, photoSize, photoSize)]; 44 | [_addBtn setImage:[UIImage imageNamed:@"photo_add.png"] forState:UIControlStateNormal]; 45 | [_addBtn addTarget:self action:@selector(addPhotoMethod) forControlEvents:UIControlEventTouchUpInside]; 46 | } 47 | return _addBtn; 48 | } 49 | 50 | 51 | 52 | - (void)viewDidLoad { 53 | [super viewDidLoad]; 54 | 55 | self.edgesForExtendedLayout = UIRectEdgeNone; 56 | _array = @[@"相册选择",@"相机"]; 57 | 58 | _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, ZZ_VW, 100)]; 59 | _tableView.dataSource = self; 60 | _tableView.delegate = self; 61 | _tableView.scrollEnabled = NO; 62 | 63 | [self.view addSubview:_tableView]; 64 | 65 | 66 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init]; 67 | 68 | CGFloat photoSize = (self.view.frame.size.width - 50) / 3; 69 | flowLayout.minimumInteritemSpacing = 10.0;//item 之间的行的距离 70 | flowLayout.minimumLineSpacing = 10.0;//item 之间竖的距离 71 | flowLayout.itemSize = (CGSize){photoSize,photoSize}; 72 | // self.sectionInset = UIEdgeInsetsMake(0, 2, 0, 0); 73 | flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; 74 | 75 | _collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(10, 170, ZZ_VW - 20, photoSize * 3) collectionViewLayout:flowLayout]; 76 | [_collectionView registerClass:[PicsCell class] forCellWithReuseIdentifier:@"PhotoCell"]; 77 | _collectionView.delegate = self; 78 | _collectionView.dataSource = self; 79 | _collectionView.backgroundColor = [UIColor whiteColor]; 80 | [_collectionView setUserInteractionEnabled:YES]; 81 | [self.view addSubview:_collectionView]; 82 | 83 | } 84 | -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 85 | { 86 | return 1; 87 | } 88 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 89 | { 90 | return _array.count; 91 | } 92 | -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 93 | { 94 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; 95 | cell.backgroundColor = [UIColor redColor]; 96 | if (!cell) { 97 | cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; 98 | } 99 | cell.textLabel.text = [_array objectAtIndex:indexPath.row]; 100 | return cell; 101 | } 102 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 103 | { 104 | return 50; 105 | } 106 | 107 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 108 | { 109 | if (indexPath.row == 0) { 110 | 111 | 112 | 113 | ZZPhotoController *photoController = [[ZZPhotoController alloc]init]; 114 | photoController.selectPhotoOfMax = 8; 115 | //设置相册中完成按钮旁边小圆点颜色。 116 | // photoController.roundColor = [UIColor greenColor]; 117 | 118 | [photoController showIn:self result:^(id responseObject){ 119 | 120 | 121 | self.picArray = (NSArray *)responseObject; 122 | // NSLog(@"重载"); 123 | [_collectionView reloadData]; 124 | 125 | }]; 126 | 127 | 128 | }else if(indexPath.row == 1){ 129 | ZZCameraController *cameraController = [[ZZCameraController alloc]init]; 130 | cameraController.takePhotoOfMax = 8; 131 | 132 | cameraController.isSaveLocal = NO; 133 | [cameraController showIn:self result:^(id responseObject){ 134 | 135 | NSLog(@"%@",responseObject); 136 | 137 | self.picArray = (NSArray *)responseObject; 138 | [_collectionView reloadData]; 139 | }]; 140 | } 141 | } 142 | 143 | 144 | 145 | #pragma mark --- ZZBrowserPickerDelegate 146 | -(NSInteger)zzbrowserPickerPhotoNum:(ZZBrowserPickerViewController *)controller 147 | { 148 | return 5; 149 | } 150 | 151 | -(NSArray *)zzbrowserPickerPhotoContent:(ZZBrowserPickerViewController *)controller 152 | { 153 | NSArray *array = @[ 154 | @"http://pic86.nipic.com/file/20151229/11592367_090842563000_2.jpg", 155 | [UIImage imageNamed:@"scv2.jpg"], 156 | [UIImage imageNamed:@"scv3.jpg"], 157 | [UIImage imageNamed:@"scv4.jpg"], 158 | [UIImage imageNamed:@"scv5.jpg"], 159 | ]; 160 | return array; 161 | } 162 | 163 | 164 | -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 165 | { 166 | 167 | return 1; 168 | } 169 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 170 | { 171 | return self.picArray.count; 172 | } 173 | 174 | -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 175 | { 176 | PicsCell *photoCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PhotoCell" forIndexPath:indexPath]; 177 | if (!photoCell) { 178 | photoCell = [[PicsCell alloc]init]; 179 | } 180 | if ([[self.picArray objectAtIndex:indexPath.row] isKindOfClass:[ZZPhoto class]]) { 181 | 182 | //从数组里面把model取出来 183 | ZZPhoto *photo = [self.picArray objectAtIndex:indexPath.row]; 184 | 185 | //用photo对象中的originImage属性来展示图片 186 | photoCell.photo.image = photo.originImage; 187 | 188 | 189 | }else if([[self.picArray objectAtIndex:indexPath.row] isKindOfClass:[ZZCamera class]]){ 190 | 191 | ZZCamera *camera = [self.picArray objectAtIndex:indexPath.row]; 192 | photoCell.photo.image = camera.image; 193 | 194 | } 195 | 196 | 197 | return photoCell; 198 | } 199 | 200 | - (void)didReceiveMemoryWarning { 201 | [super didReceiveMemoryWarning]; 202 | // Dispose of any resources that can be recreated. 203 | } 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Other/ZZAlumAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZAlumAnimation.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZAlumAnimation : NSObject 12 | 13 | +(ZZAlumAnimation *)sharedAnimation; 14 | 15 | -(void) roundAnimation:(UILabel *)label; 16 | 17 | -(void) selectAnimation:(UIButton *)button; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Other/ZZAlumAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZAlumAnimation.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZAlumAnimation.h" 10 | 11 | @implementation ZZAlumAnimation 12 | 13 | +(ZZAlumAnimation *)sharedAnimation 14 | { 15 | static ZZAlumAnimation *animation = nil; 16 | if (animation == nil) { 17 | animation = [[ZZAlumAnimation alloc]init]; 18 | } 19 | return animation; 20 | } 21 | 22 | -(void)roundAnimation:(UILabel *)label 23 | { 24 | CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 25 | animation.duration = 0.7; 26 | 27 | NSMutableArray *values = [NSMutableArray array]; 28 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)]]; 29 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)]]; 30 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9, 0.9, 1.0)]]; 31 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]]; 32 | animation.values = values; 33 | [label.layer addAnimation:animation forKey:nil]; 34 | } 35 | 36 | -(void)selectAnimation:(UIButton *)button 37 | { 38 | CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 39 | animation.duration = 0.5; 40 | 41 | NSMutableArray *values = [NSMutableArray array]; 42 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)]]; 43 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)]]; 44 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9, 0.9, 1.0)]]; 45 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]]; 46 | animation.values = values; 47 | [button.layer addAnimation:animation forKey:nil]; 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/back_button_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/back_button_normal.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/back_button_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/back_button_normal@2x.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/camera_focus_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/camera_focus_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/change_camera_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/change_camera_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/flash_close_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/flash_close_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/flash_open_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/flash_open_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/no_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/no_data.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/photo_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/photo_add.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/remove_btn_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/remove_btn_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/select_no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/select_no.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/select_yes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/select_yes.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/take_photo_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/take_photo_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/take_photo_pic@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/take_photo_pic@2x.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/trash_btn_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/trash_btn_pic.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/Resources/zz_alumb_rightCell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/ZZPhotoKit/ZZPhotoKit/Public/Resources/zz_alumb_rightCell.png -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/Public/ZZResourceConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZResourceConfig.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #ifndef ZZResourceConfig_h 10 | #define ZZResourceConfig_h 11 | /////配置文件///// 12 | 13 | 14 | /* 15 | 公共文件 16 | */ 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import "UIImageView+WebCache.h" 22 | 23 | #import 24 | #import 25 | #import 26 | #import 27 | 28 | 29 | /* 30 | 控制器 31 | */ 32 | #define ZZ_VW (self.view.frame.size.width) 33 | #define ZZ_VH (self.view.frame.size.height) 34 | 35 | #define ZZ_SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) 36 | #define ZZ_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) 37 | 38 | /* 39 | 颜色 40 | */ 41 | #define ZZ_RGBA(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a] 42 | #define ZZ_RGB(r,g,b) ZZ_RGBA(r,g,b,1.0f) 43 | 44 | /* 45 | 图片 46 | */ 47 | 48 | // 相册列表页面右边箭头图片 49 | #define PhotoListRightBtn [UIImage imageNamed:@"zz_alumb_rightCell.png"] 50 | // 相册列表页面,当没有数据时使用图片 51 | #define NOPhoto_Data_Pic [UIImage imageNamed:@"no_data.png"] 52 | // 图片选中状态图片 53 | #define Pic_Btn_Selected [UIImage imageNamed:@"select_yes.png"] 54 | // 图片未选中状态图片 55 | #define Pic_btn_UnSelected [UIImage imageNamed:@"select_no.png"] 56 | // 拍照图片 57 | #define TakePhoto_Btn_Pic [UIImage imageNamed:@"take_photo_pic.png"] 58 | // 闪光灯按钮图片 59 | #define Flash_Open_Btn_Pic [UIImage imageNamed:@"flash_open_pic.png"] 60 | #define Flash_close_Btn_Pic [UIImage imageNamed:@"flash_close_pic.png"] 61 | // 切换前置后置摄像头按钮 62 | #define Change_Btn_Pic [UIImage imageNamed:@"change_camera_pic.png"] 63 | // 删除图片按钮 64 | #define Remove_Btn_Pic [UIImage imageNamed:@"remove_btn_pic.png"] 65 | 66 | /* 67 | 文字 68 | */ 69 | // 相册详细页面底部Footer显示文字 70 | #define Total_Photo_Num @"%lu 张照片" 71 | #define Total_Video_Num @"%lu 个视频" 72 | #define Alert_Max_Selected @"最多只能选择%lu张图片" 73 | #define Alert_Max_TakePhoto @"最多连拍张数为%lu张图片" 74 | 75 | 76 | #endif /* ZZResourceConfig_h */ 77 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZBrowser/ZZBrowserPickerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZBrowserPickerCell.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/23. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | 12 | @protocol ZZBrowserPickerCellDelegate 13 | 14 | -(void) clickZoomView; 15 | 16 | @end 17 | 18 | @interface ZZBrowserPickerCell : UICollectionViewCell 19 | 20 | @property (nonatomic, strong) UIImageView *pics; 21 | 22 | @property (nonatomic, weak) iddelegate; 23 | 24 | -(void)loadPHAssetItemForPics:(PHAsset *)assetItem; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZBrowser/ZZBrowserPickerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZBrowserPickerCell.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/23. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZBrowserPickerCell.h" 10 | 11 | @interface ZZBrowserPickerCell() 12 | { 13 | CGFloat _browser_width; 14 | CGFloat _browser_height; 15 | } 16 | @property (nonatomic, strong) UIScrollView *scaleView; 17 | 18 | @end 19 | 20 | @implementation ZZBrowserPickerCell 21 | 22 | -(instancetype)initWithFrame:(CGRect)frame 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) { 26 | 27 | _browser_width = frame.size.width; 28 | _browser_height = frame.size.height; 29 | 30 | _scaleView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, _browser_width, _browser_height)]; 31 | _scaleView.delegate = self; 32 | _scaleView.maximumZoomScale = 2.5; 33 | _scaleView.minimumZoomScale = 1.0; 34 | _scaleView.bouncesZoom = YES; 35 | _scaleView.multipleTouchEnabled = YES; 36 | _scaleView.delegate = self; 37 | _scaleView.scrollsToTop = NO; 38 | _scaleView.showsHorizontalScrollIndicator = NO; 39 | _scaleView.showsVerticalScrollIndicator = NO; 40 | _scaleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 41 | _scaleView.delaysContentTouches = NO; 42 | _scaleView.canCancelContentTouches = YES; 43 | _scaleView.alwaysBounceVertical = NO; 44 | _scaleView.userInteractionEnabled = YES; 45 | [self.contentView addSubview:_scaleView]; 46 | 47 | 48 | _pics = [[UIImageView alloc]init]; 49 | _pics.contentMode = UIViewContentModeScaleAspectFit; 50 | [_scaleView addSubview:_pics]; 51 | 52 | 53 | UITapGestureRecognizer *tapScaleFingerOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleFingerEvent:)]; 54 | tapScaleFingerOne.delegate = self; 55 | tapScaleFingerOne.numberOfTapsRequired = 1; 56 | [_scaleView addGestureRecognizer:tapScaleFingerOne]; 57 | 58 | UITapGestureRecognizer *singleFingerOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleFingerEvent:)]; 59 | singleFingerOne.delegate = self; 60 | singleFingerOne.numberOfTapsRequired = 1; 61 | [_pics addGestureRecognizer:singleFingerOne]; 62 | 63 | 64 | UITapGestureRecognizer *singleFingerTwo = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleFingerEvent:)]; 65 | singleFingerTwo.delegate = self; 66 | singleFingerTwo.numberOfTapsRequired = 2; 67 | [_pics addGestureRecognizer:singleFingerTwo]; 68 | 69 | } 70 | return self; 71 | } 72 | 73 | -(void)loadPHAssetItemForPics:(PHAsset *)assetItem 74 | { 75 | PHAsset *phAsset = (PHAsset *)assetItem; 76 | 77 | CGFloat photoWidth = [UIScreen mainScreen].bounds.size.width; 78 | 79 | CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight; 80 | CGFloat multiple = [UIScreen mainScreen].scale; 81 | CGFloat pixelWidth = photoWidth * multiple; 82 | CGFloat pixelHeight = pixelWidth / aspectRatio; 83 | 84 | PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init]; 85 | option.resizeMode = PHImageRequestOptionsResizeModeFast; 86 | [[PHImageManager defaultManager] requestImageForAsset:phAsset targetSize:CGSizeMake(pixelWidth, pixelHeight) contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 87 | 88 | BOOL downloadFinined = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]; 89 | 90 | //设置BOOL判断,确定返回高清照片 91 | if (downloadFinined) { 92 | 93 | if (result != nil) { 94 | [self changeFrameWithImage:result]; 95 | self.pics.image = result; 96 | } 97 | } 98 | 99 | }]; 100 | } 101 | 102 | -(void)changeFrameWithImage:(UIImage *)image 103 | { 104 | CGFloat height = image.size.height / image.size.width * _browser_width; 105 | self.pics.frame = CGRectMake(0, 0, _browser_width, height); 106 | self.pics.center = CGPointMake(_browser_width / 2, _browser_height / 2); 107 | _scaleView.contentSize = CGSizeMake(_browser_width, MAX(self.pics.frame.size.height, _browser_height)); 108 | } 109 | 110 | -(void)setNeedsDisplay 111 | { 112 | [_scaleView setZoomScale:1.0 animated:NO]; 113 | } 114 | 115 | -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 116 | { 117 | return _pics; 118 | } 119 | 120 | -(void)scrollViewDidZoom:(UIScrollView *)scrollView 121 | { 122 | CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)? 123 | (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0; 124 | CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)? 125 | (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0; 126 | _pics.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, 127 | scrollView.contentSize.height * 0.5 + offsetY); 128 | } 129 | 130 | - (void)handleSingleFingerEvent:(UITapGestureRecognizer *)sender 131 | { 132 | if (sender.numberOfTapsRequired == 1) { 133 | if ([self.delegate respondsToSelector:@selector(clickZoomView)]) { 134 | [self.delegate clickZoomView]; 135 | } 136 | }else if(sender.numberOfTapsRequired == 2){ 137 | 138 | 139 | 140 | } 141 | } 142 | 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZBrowser/ZZBrowserPickerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZBrowserPickerViewController.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/23. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | #import "ZZResourceConfig.h" 12 | 13 | typedef NS_ENUM(NSInteger, ShowAnimation){ 14 | ShowAnimationOfPush, 15 | ShowAnimationOfPresent 16 | 17 | }; 18 | @class ZZBrowserPickerViewController; 19 | 20 | @protocol ZZBrowserPickerDelegate 21 | 22 | @required 23 | -(NSInteger)zzbrowserPickerPhotoNum:(ZZBrowserPickerViewController *)controller; 24 | -(NSArray *)zzbrowserPickerPhotoContent:(ZZBrowserPickerViewController *)controller; 25 | 26 | @optional 27 | -(void)zzbrowerPickerPhotoRemove:(NSInteger) indexPath; 28 | 29 | @end 30 | 31 | @interface ZZBrowserPickerViewController : UIViewController 32 | 33 | @property (assign, nonatomic) id delegate; 34 | 35 | //是否开启动画效果 36 | @property (assign, nonatomic) BOOL isOpenAnimation; 37 | 38 | @property (assign, nonatomic) NSInteger showAnimation; 39 | //滚动到指定位置(滚动到那张图片,通过下面属性) 40 | @property (strong, nonatomic) NSIndexPath *indexPath; 41 | 42 | -(void)reloadData; 43 | 44 | -(void)showIn:(UIViewController *)controller animation:(ShowAnimation)animation; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZBrowser/ZZPageControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPageControl.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/31. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZPageControl : UIView 12 | 13 | @property (assign,nonatomic) NSInteger currentPage; 14 | @property (strong,nonatomic) UILabel *pageControl; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZBrowser/ZZPageControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPageControl.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/31. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZPageControl.h" 10 | 11 | @implementation ZZPageControl 12 | 13 | -(instancetype)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | 18 | _pageControl = [[UILabel alloc]initWithFrame:CGRectMake(5, 3, self.frame.size.width - 10, self.frame.size.height - 6)]; 19 | _pageControl.backgroundColor = [UIColor clearColor]; 20 | _pageControl.textAlignment = NSTextAlignmentCenter; 21 | [self addSubview:_pageControl]; 22 | } 23 | return self; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Controller/ZZCameraBrowerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraBrowerViewController.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/27. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ZZCameraBrowerViewController; 12 | 13 | @protocol ZZCameraBrowerDataSource 14 | 15 | @required 16 | -(NSInteger)zzbrowserPickerPhotoNum:(ZZCameraBrowerViewController *)controller; 17 | -(NSArray *)zzbrowserPickerPhotoContent:(ZZCameraBrowerViewController *)controller; 18 | 19 | @end 20 | 21 | @interface ZZCameraBrowerViewController : UIViewController 22 | 23 | @property (nonatomic, weak) id delegate; 24 | 25 | //滚动到指定位置(滚动到那张图片,通过下面属性) 26 | @property (nonatomic, strong) NSIndexPath *indexPath; 27 | 28 | -(void)reloadData; 29 | 30 | -(void)showIn:(UIViewController *)controller; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Controller/ZZCameraBrowerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraBrowerViewController.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/27. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZCameraBrowerViewController.h" 10 | #import "ZZCameraBrowerCell.h" 11 | #import "ZZPageControl.h" 12 | #import "ZZCamera.h" 13 | 14 | @interface ZZCameraBrowerViewController () 15 | 16 | @property (nonatomic, strong) UICollectionView *picBrowse; 17 | @property (nonatomic, strong) NSMutableArray *photoDataArray; 18 | @property (nonatomic, strong) ZZPageControl *pageControl; 19 | @property (nonatomic, assign) NSInteger numberOfItems; 20 | 21 | @end 22 | 23 | @implementation ZZCameraBrowerViewController 24 | 25 | 26 | -(void)setupCollectionViewUI 27 | { 28 | self.edgesForExtendedLayout = UIRectEdgeNone; 29 | /* 30 | * 创建核心内容 UICollectionView 31 | */ 32 | self.view.backgroundColor = [UIColor blackColor]; 33 | 34 | 35 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 36 | flowLayout.itemSize = (CGSize){self.view.frame.size.width,self.view.frame.size.height}; 37 | flowLayout.minimumLineSpacing = 0.0f; 38 | flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 39 | 40 | _picBrowse = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout]; 41 | _picBrowse.backgroundColor = [UIColor clearColor]; 42 | _picBrowse.pagingEnabled = YES; 43 | 44 | _picBrowse.showsHorizontalScrollIndicator = NO; 45 | _picBrowse.showsVerticalScrollIndicator = NO; 46 | [_picBrowse registerClass:[ZZCameraBrowerCell class] forCellWithReuseIdentifier:NSStringFromClass([ZZCameraBrowerCell class])]; 47 | _picBrowse.dataSource = self; 48 | _picBrowse.delegate = self; 49 | _picBrowse.translatesAutoresizingMaskIntoConstraints = NO; 50 | 51 | 52 | [self.view addSubview:_picBrowse]; 53 | 54 | NSLayoutConstraint *list_top = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_picBrowse attribute:NSLayoutAttributeTop multiplier:1 constant:0.0f]; 55 | 56 | NSLayoutConstraint *list_bottom = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_picBrowse attribute:NSLayoutAttributeBottom multiplier:1 constant:0.0f]; 57 | 58 | NSLayoutConstraint *list_left = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_picBrowse attribute:NSLayoutAttributeLeft multiplier:1 constant:0.0f]; 59 | 60 | NSLayoutConstraint *list_right = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_picBrowse attribute:NSLayoutAttributeRight multiplier:1 constant:0.0f]; 61 | 62 | [self.view addConstraints:@[list_top,list_bottom,list_left,list_right]]; 63 | 64 | } 65 | 66 | -(void)viewDidLayoutSubviews 67 | { 68 | [super viewDidLayoutSubviews]; 69 | if (self.indexPath != nil) { 70 | [_picBrowse scrollToItemAtIndexPath:self.indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 71 | } 72 | } 73 | 74 | -(void)setPageControlUI 75 | { 76 | _pageControl = [[ZZPageControl alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 80, self.view.frame.size.width, 30)]; 77 | _pageControl.currentPage = 0; 78 | _pageControl.backgroundColor = [UIColor clearColor]; 79 | _pageControl.pageControl.textColor = [UIColor whiteColor]; 80 | [self.view addSubview:_pageControl]; 81 | 82 | //照片总数通过delegate获取 83 | _numberOfItems = [self.delegate zzbrowserPickerPhotoNum:self]; 84 | 85 | //判断是否需要滚动到指定图片 86 | if (self.indexPath != nil) { 87 | _pageControl.pageControl.text = [NSString stringWithFormat:@"%ld / %ld",(long)self.indexPath.row + 1,(long)_numberOfItems]; 88 | }else{ 89 | _pageControl.pageControl.text = [NSString stringWithFormat:@"%d / %ld",1,(long)_numberOfItems]; 90 | } 91 | 92 | } 93 | 94 | -(NSMutableArray *)photoDataArray{ 95 | if (!_photoDataArray) { 96 | _photoDataArray = [NSMutableArray array]; 97 | } 98 | return _photoDataArray; 99 | } 100 | 101 | - (void)viewDidLoad { 102 | [super viewDidLoad]; 103 | // Do any additional setup after loading the view. 104 | 105 | [self setupCollectionViewUI]; 106 | 107 | [self setPageControlUI]; 108 | 109 | [self loadPhotoData]; 110 | 111 | if ([self.delegate respondsToSelector:@selector(zzbrowserPickerPhotoContent:)]) { 112 | [self.photoDataArray addObjectsFromArray:[self.delegate zzbrowserPickerPhotoContent:self]]; 113 | } 114 | } 115 | 116 | -(void)loadPhotoData 117 | { 118 | if ([self.delegate respondsToSelector:@selector(zzbrowserPickerPhotoContent:)]) { 119 | [self.photoDataArray addObjectsFromArray:[self.delegate zzbrowserPickerPhotoContent:self]]; 120 | } 121 | } 122 | 123 | /* 124 | * 更新数据刷新方法 125 | */ 126 | 127 | -(void)reloadData 128 | { 129 | 130 | [_picBrowse reloadData]; 131 | //照片总数通过delegate获取 132 | if ([self.delegate respondsToSelector:@selector(zzbrowserPickerPhotoNum:)]) { 133 | _numberOfItems = [self.delegate zzbrowserPickerPhotoNum:self]; 134 | } 135 | 136 | //判断是否需要滚动到指定图片 137 | if (self.indexPath != nil) { 138 | _pageControl.pageControl.text = [NSString stringWithFormat:@"%ld / %ld",(long)self.indexPath.row + 1,(long)_numberOfItems]; 139 | }else{ 140 | _pageControl.pageControl.text = [NSString stringWithFormat:@"%d / %ld",1,(long)_numberOfItems]; 141 | } 142 | } 143 | 144 | #pragma mark --- UICollectionviewDelegate or dataSource 145 | -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 146 | { 147 | return 1; 148 | } 149 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 150 | { 151 | return [self.delegate zzbrowserPickerPhotoNum:self]; 152 | } 153 | 154 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 155 | { 156 | ZZCameraBrowerCell *browerCell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([ZZCameraBrowerCell class]) forIndexPath:indexPath]; 157 | 158 | browerCell.delegate = self; 159 | 160 | if ([[_photoDataArray objectAtIndex:indexPath.row] isKindOfClass:[ZZCamera class]]){ 161 | ZZCamera *photo = [_photoDataArray objectAtIndex:indexPath.row]; 162 | [browerCell loadPicData:photo.image]; 163 | } 164 | 165 | return browerCell; 166 | } 167 | 168 | - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { 169 | if ([cell isKindOfClass:[ZZCameraBrowerCell class]]) { 170 | [(ZZCameraBrowerCell *)cell recoverSubview]; 171 | } 172 | } 173 | 174 | - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { 175 | if ([cell isKindOfClass:[ZZCameraBrowerCell class]]) { 176 | [(ZZCameraBrowerCell *)cell recoverSubview]; 177 | } 178 | } 179 | 180 | 181 | -(void)clickSingleFingerAtScreen 182 | { 183 | [self dismissViewControllerAnimated:YES completion:nil]; 184 | } 185 | 186 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 187 | { 188 | int itemIndex = (scrollView.contentOffset.x + self.picBrowse.frame.size.width * 0.5) / self.picBrowse.frame.size.width; 189 | if (!self.numberOfItems) return; 190 | int indexOnPageControl = itemIndex % self.numberOfItems; 191 | 192 | _pageControl.pageControl.text = [NSString stringWithFormat:@"%d / %ld",indexOnPageControl+1,(long)_numberOfItems]; 193 | self.pageControl.currentPage = indexOnPageControl; 194 | } 195 | 196 | -(void)showIn:(UIViewController *)controller 197 | { 198 | [controller presentViewController:self animated:YES completion:nil]; 199 | } 200 | 201 | - (void)didReceiveMemoryWarning { 202 | [super didReceiveMemoryWarning]; 203 | // Dispose of any resources that can be recreated. 204 | } 205 | 206 | 207 | 208 | @end 209 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Controller/ZZCameraController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraController.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/18. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | 12 | typedef void(^ZZCameraResult)(id responseObject); 13 | 14 | @interface ZZCameraController : NSObject 15 | 16 | /* 17 | * 设置是否将拍完过后的照片直接保存到相册 18 | */ 19 | @property (assign, nonatomic) BOOL isSaveLocal; 20 | 21 | /* 22 | * 设置最多连拍张数 23 | */ 24 | @property (assign, nonatomic) NSInteger takePhotoOfMax; 25 | 26 | 27 | /* 28 | * 设置相机页面主题颜色,默认为黑色 29 | */ 30 | @property (strong, nonatomic) UIColor *themeColor; 31 | 32 | -(void)showIn:(UIViewController *)controller result:(ZZCameraResult)result; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Controller/ZZCameraController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraController.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/18. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZCameraController.h" 10 | #import "ZZCameraPickerViewController.h" 11 | @interface ZZCameraController() 12 | 13 | @property (strong,nonatomic) ZZCameraPickerViewController *cameraPickerController; 14 | 15 | @end 16 | 17 | @implementation ZZCameraController 18 | 19 | -(ZZCameraPickerViewController *)cameraPickerController 20 | { 21 | if (!_cameraPickerController) { 22 | _cameraPickerController = [[ZZCameraPickerViewController alloc]init]; 23 | } 24 | return _cameraPickerController; 25 | } 26 | 27 | -(void)showIn:(UIViewController *)controller result:(ZZCameraResult)result 28 | { 29 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; 30 | 31 | if (status == AVAuthorizationStatusNotDetermined) { 32 | //相机进行授权 33 | /* * * 第一次安装应用时直接进行这个判断进行授权 * * */ 34 | [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { 35 | if (granted) { 36 | dispatch_async(dispatch_get_main_queue(), ^{ 37 | [self showController:controller result:result]; 38 | }); 39 | } 40 | }]; 41 | }else if (status == AVAuthorizationStatusAuthorized){ 42 | [self showController:controller result:result]; 43 | }else if (status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied){ 44 | [self showAlertViewToController:controller]; 45 | } 46 | } 47 | 48 | -(void)showController:(UIViewController *)controller result:(ZZCameraResult)result 49 | { 50 | self.cameraPickerController.CameraResult = result; 51 | //设置连拍最大张数 52 | self.cameraPickerController.takePhotoOfMax = self.takePhotoOfMax; 53 | //设置返回图片类型 54 | self.cameraPickerController.isSavelocal = self.isSaveLocal; 55 | self.cameraPickerController.themeColor = self.themeColor; 56 | [controller presentViewController:self.cameraPickerController animated:YES completion:nil]; 57 | } 58 | 59 | -(void)showAlertViewToController:(UIViewController *)controller 60 | { 61 | NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 62 | // app名称 63 | NSString *app_Name = [infoDictionary objectForKey:@"CFBundleDisplayName"]; 64 | 65 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:[NSString stringWithFormat:@"请在iPhone的“设置->隐私->照片”开启%@访问你的相机",app_Name] preferredStyle:UIAlertControllerStyleAlert]; 66 | 67 | UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){ 68 | 69 | }]; 70 | 71 | [alert addAction:action1]; 72 | [controller presentViewController:alert animated:YES completion:nil]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Controller/ZZCameraPickerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraPickerViewController.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/18. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | 12 | @interface ZZCameraPickerViewController : UIViewController 13 | 14 | @property (nonatomic, assign) BOOL isSavelocal; 15 | 16 | @property (nonatomic, assign) NSInteger takePhotoOfMax; 17 | 18 | @property (nonatomic, strong) UIColor *themeColor; 19 | 20 | @property (nonatomic, copy) void (^CameraResult)(id responseObject); 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Model/ZZCamera.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCamera.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/25. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZCamera : NSObject 12 | 13 | /** 14 | 照片 15 | */ 16 | @property (nonatomic, strong) UIImage *image; 17 | 18 | /** 19 | 照片保存到相册中的时间 20 | */ 21 | @property (nonatomic, copy) NSDate *createDate; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/Model/ZZCamera.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCamera.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/25. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZCamera.h" 10 | 11 | @implementation ZZCamera 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/View/ZZCameraBrowerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraBrowerCell.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/10/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol ZZCameraBrowerCellDelegate 12 | 13 | - (void) clickSingleFingerAtScreen; 14 | 15 | @end 16 | 17 | @interface ZZCameraBrowerCell : UICollectionViewCell 18 | 19 | @property (nonatomic, weak) iddelegate; 20 | 21 | -(void) loadPicData:(UIImage *) image; 22 | 23 | -(void) recoverSubview; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/View/ZZCameraBrowerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraBrowerCell.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/10/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZCameraBrowerCell.h" 10 | 11 | @interface ZZCameraBrowerCell() 12 | { 13 | CGFloat _browser_width; 14 | CGFloat _browser_height; 15 | } 16 | @property (nonatomic, strong) UIScrollView *scaleView; 17 | @property (nonatomic, strong) UIImageView *photo_image_view; 18 | @end 19 | 20 | @implementation ZZCameraBrowerCell 21 | 22 | -(instancetype)initWithFrame:(CGRect)frame 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) { 26 | 27 | _browser_width = frame.size.width; 28 | _browser_height = frame.size.height; 29 | 30 | _scaleView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, _browser_width, _browser_height)]; 31 | _scaleView.delegate = self; 32 | _scaleView.maximumZoomScale = 2.5; 33 | _scaleView.minimumZoomScale = 1.0; 34 | _scaleView.bouncesZoom = YES; 35 | _scaleView.multipleTouchEnabled = YES; 36 | _scaleView.delegate = self; 37 | _scaleView.scrollsToTop = NO; 38 | _scaleView.showsHorizontalScrollIndicator = NO; 39 | _scaleView.showsVerticalScrollIndicator = NO; 40 | _scaleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 41 | _scaleView.delaysContentTouches = NO; 42 | _scaleView.canCancelContentTouches = YES; 43 | _scaleView.alwaysBounceVertical = NO; 44 | [self.contentView addSubview:_scaleView]; 45 | 46 | _photo_image_view = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, _browser_width, _browser_height)]; 47 | _photo_image_view.contentMode = UIViewContentModeScaleAspectFit; 48 | _photo_image_view.userInteractionEnabled = YES; 49 | [_scaleView addSubview:_photo_image_view]; 50 | 51 | UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapHandle:)]; 52 | [_photo_image_view addGestureRecognizer:singleTap]; 53 | 54 | UITapGestureRecognizer *doubleTap= [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapHandle:)]; 55 | doubleTap.delegate = self; 56 | doubleTap.numberOfTapsRequired = 2; 57 | [_photo_image_view addGestureRecognizer:doubleTap]; 58 | 59 | [singleTap requireGestureRecognizerToFail:doubleTap]; 60 | } 61 | return self; 62 | } 63 | 64 | 65 | -(void)changeFrameWithImage:(UIImage *)image 66 | { 67 | CGFloat height = image.size.height / image.size.width * _browser_width; 68 | self.photo_image_view.frame = CGRectMake(0, 0, _browser_width, height); 69 | self.photo_image_view.center = CGPointMake(_browser_width / 2, _browser_height / 2); 70 | _scaleView.contentSize = CGSizeMake(_browser_width, MAX(self.photo_image_view.frame.size.height, _browser_height)); 71 | } 72 | 73 | -(void)loadPicData:(UIImage *)image 74 | { 75 | if (image != nil) { 76 | [self changeFrameWithImage:image]; 77 | _photo_image_view.image = image; 78 | } 79 | } 80 | 81 | -(void)recoverSubview 82 | { 83 | [_scaleView setZoomScale:1.0 animated:NO]; 84 | } 85 | 86 | -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 87 | { 88 | return _photo_image_view; 89 | } 90 | 91 | -(void)scrollViewDidZoom:(UIScrollView *)scrollView 92 | { 93 | CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)? 94 | (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0; 95 | CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)? 96 | (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0; 97 | _photo_image_view.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, 98 | scrollView.contentSize.height * 0.5 + offsetY); 99 | } 100 | 101 | -(void)singleTapHandle:(UITapGestureRecognizer *)sender 102 | { 103 | if ([self.delegate respondsToSelector:@selector(clickSingleFingerAtScreen)]) { 104 | [self.delegate clickSingleFingerAtScreen]; 105 | } 106 | } 107 | 108 | 109 | - (void)doubleTapHandle:(UITapGestureRecognizer *)sender 110 | { 111 | if (_scaleView.zoomScale > 1.0) { 112 | [_scaleView setZoomScale:1.0 animated:YES]; 113 | } else { 114 | CGPoint touchPoint = [sender locationInView:self.photo_image_view]; 115 | CGFloat maxScale = _scaleView.maximumZoomScale; 116 | CGFloat xsize = self.frame.size.width / maxScale; 117 | CGFloat ysize = self.frame.size.height / maxScale; 118 | [_scaleView zoomToRect:CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize) animated:YES]; 119 | } 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/View/ZZCameraFocusView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraFocusView.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/21. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ZZCameraFocusView; 12 | 13 | @protocol ZZCameraFocusDelegate 14 | 15 | @optional 16 | -(void) cameraFocusOptionsWithPoint:(CGPoint)point; 17 | 18 | @end 19 | 20 | @interface ZZCameraFocusView : UIView 21 | 22 | @property (nonatomic,weak) id delegate; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/View/ZZCameraFocusView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraFocusView.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/21. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZCameraFocusView.h" 10 | 11 | @interface ZZCameraFocusView() 12 | 13 | @property (strong, nonatomic) UIImageView *focus; 14 | @property (strong, nonatomic) NSTimer *timer; 15 | 16 | @end 17 | 18 | @implementation ZZCameraFocusView 19 | 20 | -(instancetype)initWithFrame:(CGRect)frame 21 | { 22 | self = [super initWithFrame:frame]; 23 | if (self) { 24 | self.backgroundColor = [UIColor clearColor]; 25 | 26 | _focus = [[UIImageView alloc]init]; 27 | _focus.image = [UIImage imageNamed:@"camera_focus_pic.png"]; 28 | } 29 | return self; 30 | } 31 | 32 | -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 33 | { 34 | UITouch *touch = [touches anyObject]; 35 | CGPoint point = [touch locationInView:touch.view]; 36 | _focus.frame = CGRectMake(0, 0, 80, 80); 37 | _focus.center = point; 38 | [self addSubview:_focus]; 39 | 40 | [self shakeToShow:_focus]; 41 | 42 | _timer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(hideFocusView) userInfo:nil repeats:YES]; 43 | if ([self.delegate respondsToSelector:@selector(cameraFocusOptionsWithPoint:)]) { 44 | [self.delegate cameraFocusOptionsWithPoint:point]; 45 | } 46 | } 47 | 48 | - (void) shakeToShow:(UIView*)aView{ 49 | CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 50 | animation.duration = 0.5; 51 | 52 | NSMutableArray *values = [NSMutableArray array]; 53 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)]]; 54 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)]]; 55 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9, 0.9, 1.0)]]; 56 | [values addObject:[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]]; 57 | animation.values = values; 58 | [aView.layer addAnimation:animation forKey:nil]; 59 | } 60 | 61 | -(void) hideFocusView 62 | { 63 | [_focus removeFromSuperview]; 64 | [_timer invalidate]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/View/ZZCameraPickerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraPickerCell.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/18. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZCameraPickerCell : UICollectionViewCell 12 | 13 | @property(strong,nonatomic) UIImageView *pics; 14 | @property(strong,nonatomic) UIButton *removeBtn; 15 | 16 | @property(copy ,nonatomic) void(^deleteBlock)(); 17 | 18 | -(void)loadPhotoDatas:(UIImage *)image; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZCamera/View/ZZCameraPickerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZCameraPickerCell.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/18. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZCameraPickerCell.h" 10 | 11 | 12 | 13 | @implementation ZZCameraPickerCell 14 | 15 | -(instancetype)initWithFrame:(CGRect)frame 16 | { 17 | self = [super initWithFrame:frame]; 18 | if (self) { 19 | 20 | 21 | _pics = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, (ZZ_SCREEN_WIDTH - 60) / 5, (ZZ_SCREEN_WIDTH - 60) / 5)]; 22 | _pics.contentMode = UIViewContentModeScaleAspectFill; 23 | [self.contentView addSubview:_pics]; 24 | 25 | 26 | _removeBtn = [[UIButton alloc]initWithFrame:CGRectMake((ZZ_SCREEN_WIDTH - 60) / 5 -20, 0, 20, 20)]; 27 | [_removeBtn setImage:Remove_Btn_Pic forState:UIControlStateNormal]; 28 | [_removeBtn addTarget:self action:@selector(clickRemoveButtonMethod:) forControlEvents:UIControlEventTouchUpInside]; 29 | [self.contentView addSubview:_removeBtn]; 30 | 31 | } 32 | return self; 33 | 34 | } 35 | 36 | //载入数据 37 | -(void)loadPhotoDatas:(UIImage *)image 38 | { 39 | _pics.image = image; 40 | 41 | } 42 | 43 | -(void)clickRemoveButtonMethod:(UIButton *)button 44 | { 45 | self.deleteBlock(); 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoBrowerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoBrowerViewController.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/27. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | 12 | 13 | 14 | @interface ZZPhotoBrowerViewController : UIViewController 15 | 16 | @property (nonatomic, copy) NSArray *photoData; 17 | 18 | @property (nonatomic, assign) NSInteger scrollIndex; 19 | 20 | -(void) showIn:(UIViewController *)controller; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoBrowerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoBrowerViewController.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/27. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoBrowerViewController.h" 10 | #import "ZZPhotoBrowerCell.h" 11 | #import "ZZPageControl.h" 12 | #import "ZZPhoto.h" 13 | 14 | 15 | @interface ZZPhotoBrowerViewController () 16 | 17 | @property (nonatomic, strong) UICollectionView *picBrowse; 18 | @property (nonatomic, assign) NSInteger numberOfItems; 19 | @property (nonatomic, strong) UIBarButtonItem *backBarButton; 20 | @end 21 | 22 | @implementation ZZPhotoBrowerViewController 23 | 24 | -(UIBarButtonItem *)backBarButton 25 | { 26 | if (!_backBarButton) { 27 | UIButton *back_btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 45, 44)]; 28 | [back_btn setImage:[UIImage imageNamed:@"back_button_normal.png"] forState:UIControlStateNormal]; 29 | [back_btn setImage:[UIImage imageNamed:@"back_button_high.png"] forState:UIControlStateHighlighted]; 30 | back_btn.frame = CGRectMake(0, 0, 45, 44); 31 | [back_btn addTarget:self action:@selector(backItemMethod) forControlEvents:UIControlEventTouchUpInside]; 32 | 33 | _backBarButton = [[UIBarButtonItem alloc] initWithCustomView:back_btn]; 34 | } 35 | return _backBarButton; 36 | } 37 | 38 | -(void)backItemMethod 39 | { 40 | [self.navigationController popViewControllerAnimated:YES]; 41 | 42 | } 43 | 44 | -(void) makeCollectionViewUI 45 | { 46 | self.edgesForExtendedLayout = UIRectEdgeNone; 47 | /* 48 | * 创建核心内容 UICollectionView 49 | */ 50 | self.view.backgroundColor = [UIColor blackColor]; 51 | 52 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 53 | flowLayout.itemSize = (CGSize){self.view.frame.size.width,self.view.frame.size.height-64}; 54 | flowLayout.minimumLineSpacing = 0.0f; 55 | flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 56 | 57 | _picBrowse = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout]; 58 | _picBrowse.backgroundColor = [UIColor clearColor]; 59 | _picBrowse.pagingEnabled = YES; 60 | 61 | _picBrowse.showsHorizontalScrollIndicator = NO; 62 | _picBrowse.showsVerticalScrollIndicator = NO; 63 | [_picBrowse registerClass:[ZZPhotoBrowerCell class] forCellWithReuseIdentifier:NSStringFromClass([ZZPhotoBrowerCell class])]; 64 | _picBrowse.dataSource = self; 65 | _picBrowse.delegate = self; 66 | _picBrowse.translatesAutoresizingMaskIntoConstraints = NO; 67 | [self.view addSubview:_picBrowse]; 68 | 69 | NSLayoutConstraint *list_top = [NSLayoutConstraint constraintWithItem:_picBrowse attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:0.0f]; 70 | 71 | NSLayoutConstraint *list_bottom = [NSLayoutConstraint constraintWithItem:_picBrowse attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0.0f]; 72 | 73 | NSLayoutConstraint *list_left = [NSLayoutConstraint constraintWithItem:_picBrowse attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:0.0f]; 74 | 75 | NSLayoutConstraint *list_right = [NSLayoutConstraint constraintWithItem:_picBrowse attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:0.0f]; 76 | 77 | [self.view addConstraints:@[list_top,list_bottom,list_left,list_right]]; 78 | 79 | } 80 | 81 | - (void) viewDidLoad { 82 | [super viewDidLoad]; 83 | // Do any additional setup after loading the view. 84 | 85 | self.navigationItem.title = @"预览"; 86 | self.navigationItem.leftBarButtonItem = self.backBarButton; 87 | 88 | [self makeCollectionViewUI]; 89 | 90 | } 91 | 92 | -(void) viewDidLayoutSubviews 93 | { 94 | [super viewDidLayoutSubviews]; 95 | 96 | //滚动到指定位置 97 | 98 | [_picBrowse scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:_scrollIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:NO]; 99 | } 100 | 101 | #pragma mark --- UICollectionviewDelegate or dataSource 102 | -(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView 103 | { 104 | return 1; 105 | } 106 | -(NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 107 | { 108 | return _photoData.count; 109 | } 110 | 111 | -(UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 112 | { 113 | ZZPhotoBrowerCell *browerCell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([ZZPhotoBrowerCell class]) forIndexPath:indexPath]; 114 | 115 | if ([[_photoData objectAtIndex:indexPath.row] isKindOfClass:[ZZPhoto class]]) { 116 | //加载相册中的数据时实用 117 | ZZPhoto *photo = [_photoData objectAtIndex:indexPath.row]; 118 | [browerCell loadPHAssetItemForPics:photo.asset]; 119 | } 120 | 121 | return browerCell; 122 | } 123 | 124 | - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { 125 | if ([cell isKindOfClass:[ZZPhotoBrowerCell class]]) { 126 | [(ZZPhotoBrowerCell *)cell recoverSubview]; 127 | } 128 | } 129 | 130 | - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { 131 | if ([cell isKindOfClass:[ZZPhotoBrowerCell class]]) { 132 | [(ZZPhotoBrowerCell *)cell recoverSubview]; 133 | } 134 | } 135 | 136 | 137 | -(void) showIn:(UIViewController *)controller 138 | { 139 | [controller.navigationController pushViewController:self animated:YES]; 140 | } 141 | 142 | - (void)didReceiveMemoryWarning { 143 | [super didReceiveMemoryWarning]; 144 | // Dispose of any resources that can be recreated. 145 | } 146 | 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoController.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/16. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | /* 12 | * 设置Block 13 | */ 14 | typedef void (^ZZPhotoResult)(id responseObject); 15 | 16 | 17 | @interface ZZPhotoController : NSObject 18 | /* 19 | * 设置圆点颜色 20 | */ 21 | @property(strong,nonatomic) UIColor *roundColor; 22 | /* 23 | * 选择照片的最多张数 24 | */ 25 | @property(assign,nonatomic) NSInteger selectPhotoOfMax; 26 | /* 27 | * 设置回调方法 28 | */ 29 | -(void)showIn:(UIViewController *)controller result:(ZZPhotoResult)result; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoController.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/16. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoController.h" 10 | #import "ZZPhotoListViewController.h" 11 | #import "ZZPhotoPickerViewController.h" 12 | 13 | @interface ZZPhotoController() 14 | 15 | @property(strong,nonatomic) ZZPhotoListViewController *photoListController; 16 | @property(strong,nonatomic) UINavigationController *photoListNavigationController; 17 | @property(strong,nonatomic) ZZPhotoPickerViewController *photoPickerController; 18 | 19 | @end 20 | 21 | @implementation ZZPhotoController 22 | 23 | #pragma mark ---- 懒加载控制器 24 | -(ZZPhotoListViewController *)photoListController{ 25 | if (!_photoListController) { 26 | _photoListController = [[ZZPhotoListViewController alloc]init]; 27 | } 28 | return _photoListController; 29 | } 30 | 31 | -(UINavigationController *)photoListNavigationController{ 32 | if (!_photoListNavigationController) { 33 | _photoListNavigationController = [[UINavigationController alloc]initWithRootViewController:self.photoListController]; 34 | } 35 | return _photoListNavigationController; 36 | } 37 | 38 | -(ZZPhotoPickerViewController *)photoPickerController{ 39 | if (!_photoPickerController) { 40 | _photoPickerController = [[ZZPhotoPickerViewController alloc]init]; 41 | } 42 | return _photoPickerController; 43 | } 44 | 45 | #pragma mark ---- 弹出控制器 46 | -(void)showIn:(UIViewController *)controller result:(ZZPhotoResult)result{ 47 | 48 | //相册权限判断 49 | PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; 50 | if (status == PHAuthorizationStatusDenied) { 51 | //相册权限未开启 52 | [self showAlertViewToController:controller]; 53 | 54 | }else if(status == PHAuthorizationStatusNotDetermined){ 55 | //相册进行授权 56 | /* * * 第一次安装应用时直接进行这个判断进行授权 * * */ 57 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status){ 58 | //授权后直接打开照片库 59 | if (status == PHAuthorizationStatusAuthorized){ 60 | dispatch_async(dispatch_get_main_queue(), ^{ 61 | [self showController:controller result:result]; 62 | }); 63 | 64 | } 65 | }]; 66 | }else if (status == PHAuthorizationStatusAuthorized){ 67 | [self showController:controller result:result]; 68 | } 69 | } 70 | 71 | -(void)showController:(UIViewController *)controller result:(ZZPhotoResult)result 72 | { 73 | //授权完成,打开相册 74 | 75 | self.photoListController.photoResult = result; 76 | //先向presentViewController控制器ZZPhotoListViewController,此控制器为全部相册控制器 77 | 78 | /* * * 同时设定最多选择照片的张数 * * */ 79 | self.photoListController.selectNum = _selectPhotoOfMax; 80 | 81 | [self showPhotoList:controller]; 82 | 83 | //Block传值 84 | self.photoPickerController.PhotoResult = result; 85 | self.photoPickerController.isAlubSeclect = NO; 86 | self.photoPickerController.roundColor = self.roundColor; 87 | /* * * 同时设定最多选择照片的张数 * * */ 88 | self.photoPickerController.selectNum = _selectPhotoOfMax; 89 | 90 | //然后再执行pushViewController控制器ZZPhotoPickerViewController 91 | //此控制器为详情相册,显示某个相册中的详细照片 92 | [self showPhotoPicker:self.photoListController.navigationController]; 93 | } 94 | 95 | -(void)showPhotoList:(UIViewController *)controller 96 | { 97 | [controller presentViewController:self.photoListNavigationController animated:YES completion:nil]; 98 | } 99 | 100 | -(void)showPhotoPicker:(UINavigationController *)navigationController 101 | { 102 | //此处注意Animated == NO,关闭动画效果。则直接进入了详细页面。 103 | [navigationController pushViewController:self.photoPickerController animated:NO]; 104 | } 105 | 106 | -(void)showAlertViewToController:(UIViewController *)controller 107 | { 108 | NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 109 | // app名称 110 | NSString *app_Name = [infoDictionary objectForKey:@"CFBundleDisplayName"]; 111 | 112 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:[NSString stringWithFormat:@"请在iPhone的“设置->隐私->照片”开启%@访问你的手机相册",app_Name] preferredStyle:UIAlertControllerStyleAlert]; 113 | 114 | UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){ 115 | 116 | }]; 117 | 118 | [alert addAction:action1]; 119 | [controller presentViewController:alert animated:YES completion:nil]; 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoListViewController.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/17. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZPhotoListViewController : UIViewController 12 | 13 | @property (nonatomic, assign) NSInteger selectNum; 14 | @property (nonatomic, copy) void (^photoResult)(id responseObject); 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoListViewController.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/17. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoListViewController.h" 10 | #import "ZZPhotoDatas.h" 11 | #import "ZZPhotoListCell.h" 12 | #import "ZZPhotoPickerViewController.h" 13 | #import 14 | #import "ZZPhotoListModel.h" 15 | 16 | @interface ZZPhotoListViewController () 17 | 18 | @property (nonatomic, strong) UITableView *alumbTable; 19 | @property (nonatomic, strong) PHPhotoLibrary *assetsLibrary; 20 | @property (nonatomic, copy) NSArray *alubms; 21 | @property (nonatomic, strong) UIBarButtonItem *closeBtn; 22 | @property (nonatomic, strong) ZZPhotoDatas *datas; 23 | @property (nonatomic, strong) ZZPhotoPickerViewController *photoPickerViewController; 24 | @end 25 | 26 | @implementation ZZPhotoListViewController 27 | 28 | 29 | -(UIBarButtonItem *)closeBtn{ 30 | if (!_closeBtn) { 31 | UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 50, 44)]; 32 | [button addTarget:self action:@selector(close) forControlEvents:UIControlEventTouchUpInside]; 33 | button.titleLabel.font = [UIFont systemFontOfSize:17.0f]; 34 | [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 35 | [button setTitle:@"关闭" forState:UIControlStateNormal]; 36 | [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 37 | 38 | _closeBtn = [[UIBarButtonItem alloc] initWithCustomView:button]; 39 | } 40 | return _closeBtn; 41 | } 42 | 43 | -(void)close{ 44 | [self dismissViewControllerAnimated:YES completion:nil]; 45 | } 46 | 47 | #pragma mark --- 懒加载 48 | -(ZZPhotoDatas *)datas{ 49 | if (!_datas) { 50 | _datas = [[ZZPhotoDatas alloc]init]; 51 | } 52 | return _datas; 53 | } 54 | 55 | -(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 56 | { 57 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 58 | if (self) { 59 | 60 | self.navigationItem.title = @"相册"; 61 | } 62 | return self; 63 | } 64 | 65 | - (void)viewDidLoad { 66 | [super viewDidLoad]; 67 | // Do any additional setup after loading the view. 68 | 69 | self.navigationItem.rightBarButtonItem = self.closeBtn; 70 | self.edgesForExtendedLayout = UIRectEdgeNone; 71 | 72 | _photoPickerViewController = [ZZPhotoPickerViewController new]; 73 | 74 | [self makeAlumListUI]; 75 | 76 | 77 | [self.datas fetchPhotoListDatasCompletion:^(NSArray *data) { 78 | self.alubms = data; 79 | }]; 80 | } 81 | 82 | -(void)viewWillAppear:(BOOL)animated 83 | { 84 | [super viewWillAppear:animated]; 85 | [self.alumbTable deselectRowAtIndexPath:[self.alumbTable indexPathForSelectedRow] animated:YES]; 86 | } 87 | 88 | -(void) makeAlumListUI 89 | { 90 | _alumbTable = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain]; 91 | _alumbTable.delegate = self; 92 | _alumbTable.dataSource = self; 93 | _alumbTable.separatorStyle = NO; 94 | _alumbTable.translatesAutoresizingMaskIntoConstraints = NO; 95 | [self.view addSubview:_alumbTable]; 96 | 97 | NSLayoutConstraint *list_top = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_alumbTable attribute:NSLayoutAttributeTop multiplier:1 constant:0.0f]; 98 | 99 | NSLayoutConstraint *list_bottom = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_alumbTable attribute:NSLayoutAttributeBottom multiplier:1 constant:0.0f]; 100 | 101 | NSLayoutConstraint *list_left = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_alumbTable attribute:NSLayoutAttributeLeft multiplier:1 constant:0.0f]; 102 | 103 | NSLayoutConstraint *list_right = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_alumbTable attribute:NSLayoutAttributeRight multiplier:1 constant:0.0f]; 104 | 105 | [self.view addConstraints:@[list_top,list_bottom,list_left,list_right]]; 106 | } 107 | 108 | #pragma mark --- UITableView协议方法 109 | -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 110 | { 111 | return 1; 112 | } 113 | 114 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 115 | { 116 | return self.alubms.count; 117 | } 118 | 119 | -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 120 | { 121 | ZZPhotoListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ZZPhotoListCell"]; 122 | if (!cell) { 123 | cell = [[ZZPhotoListCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"ZZPhotoListCell"]; 124 | } 125 | 126 | [cell loadPhotoListData:[self.alubms objectAtIndex:indexPath.row]]; 127 | 128 | return cell; 129 | } 130 | 131 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 132 | { 133 | return 70; 134 | } 135 | 136 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 137 | { 138 | _photoPickerViewController.PhotoResult = self.photoResult; 139 | _photoPickerViewController.selectNum = self.selectNum; 140 | ZZPhotoListModel *listmodel = [self.alubms objectAtIndex:indexPath.row]; 141 | _photoPickerViewController.alumbModel = listmodel; 142 | _photoPickerViewController.navigationItem.title = listmodel.title; 143 | _photoPickerViewController.isAlubSeclect = YES; 144 | [self.navigationController pushViewController:_photoPickerViewController animated:YES]; 145 | } 146 | 147 | - (void)didReceiveMemoryWarning { 148 | [super didReceiveMemoryWarning]; 149 | // Dispose of any resources that can be recreated. 150 | } 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Controller/ZZPhotoPickerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoPickerViewController.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/7/7. 6 | // Copyright (c) 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | #import "ZZPhotoListModel.h" 12 | 13 | @interface ZZPhotoPickerViewController : UIViewController 14 | 15 | @property (nonatomic, copy) void (^PhotoResult)(id responseObject); 16 | @property (nonatomic, assign) BOOL isAlubSeclect; 17 | @property (nonatomic, strong) UIColor *roundColor; 18 | @property (nonatomic, assign) NSInteger selectNum; 19 | @property (nonatomic, strong) ZZPhotoListModel *alumbModel; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Model/ZZPhoto.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhoto.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/25. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZPhoto : NSObject 12 | 13 | /** 14 | 资源 15 | */ 16 | @property (nonatomic, strong) PHAsset *asset; 17 | /** 18 | 原尺寸图片 19 | */ 20 | @property (nonatomic, strong) UIImage *originImage; 21 | /** 22 | 照片在手机中的路径 23 | */ 24 | @property (nonatomic, strong) NSURL *imageUrl; 25 | /** 26 | 照片保存到相册中的时间 27 | */ 28 | @property (nonatomic, copy) NSDate *createDate; 29 | /** 30 | 判断该图片是否选中 31 | */ 32 | @property (nonatomic, assign) BOOL isSelect; 33 | 34 | +(UIImage *) fetchThumbImageWithAsset:(PHAsset *)asset; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Model/ZZPhoto.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhoto.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/25. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhoto.h" 10 | 11 | @implementation ZZPhoto 12 | 13 | +(UIImage *) fetchThumbImageWithAsset:(PHAsset *)asset 14 | { 15 | __block UIImage *thumbImage; 16 | [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(200, 200) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage *result, NSDictionary *info){ 17 | BOOL downloadFinined = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]; 18 | 19 | //设置BOOL判断,确定返回高清照片 20 | if (downloadFinined) { 21 | 22 | thumbImage = result; 23 | } 24 | 25 | }]; 26 | 27 | return thumbImage; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Model/ZZPhotoDatas.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoDatas.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/17. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZPhotoDatas : NSObject 12 | /** 13 | 获取全部相册 14 | 15 | @return array 集合 16 | */ 17 | - (void) fetchPhotoListDatasCompletion:(void(^)(NSArray *data))completion; 18 | 19 | /** 20 | 获取某个相册的全部照片实体 21 | 22 | @param collection 相册集合 23 | 24 | @return 相册中全部实体 25 | */ 26 | - (PHFetchResult *) GetFetchResult:(PHAssetCollection *)collection; 27 | 28 | /** 29 | 获取图片实体,并把图片结果存放到数组中,返回值数组 30 | 31 | @param fetchResult 32 | 33 | @return array 集合 34 | */ 35 | - (void)fetchPhotoAssets:(PHFetchResult *)fetchResult completion:(void(^)(NSArray *data))completion; 36 | 37 | /** 38 | 获取相机胶卷中的结果集 39 | 40 | @return 集合 41 | */ 42 | - (PHFetchResult *) fetchCameraRollFetchResult; 43 | 44 | /** 45 | 回调方法使用数组 46 | 47 | @param asset 照片实体 48 | @param complection 回调方法 49 | */ 50 | - (void) fetchImageObject:(id)asset complection:(void (^)(UIImage *,NSURL *))complection; 51 | 52 | /** 53 | 检测是否为iCloud资源 54 | 55 | @param asset 照片实体 56 | 57 | @return 是否 58 | */ 59 | - (BOOL) CheckIsiCloudAsset:(PHAsset *)asset; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Model/ZZPhotoListModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoListModel.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZPhotoListModel : NSObject 12 | 13 | /** 14 | 照片总数 15 | */ 16 | @property (nonatomic, assign) NSInteger count; 17 | 18 | /** 19 | 集合中最后一个实体 20 | */ 21 | @property (nonatomic, strong) PHAsset *lastObject; 22 | /** 23 | 相册名称 24 | */ 25 | @property (nonatomic, copy) NSString *title; 26 | /** 27 | 结果集 28 | */ 29 | @property (nonatomic, strong) PHFetchResult *fetchResult; 30 | /** 31 | 照片实体集合 32 | */ 33 | @property (nonatomic, strong) PHAssetCollection *assetCollection; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/Model/ZZPhotoListModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoListModel.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/5/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoListModel.h" 10 | 11 | @implementation ZZPhotoListModel 12 | 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoAlert.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoAlert.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/8/28. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZPhotoAlert : UIView 12 | 13 | +(ZZPhotoAlert *) sharedAlert; 14 | 15 | -(void) showPhotoAlert; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoAlert.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoAlert.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/8/28. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoAlert.h" 10 | #import "ZZResourceConfig.h" 11 | @implementation ZZPhotoAlert 12 | 13 | +(ZZPhotoAlert *)sharedAlert 14 | { 15 | static ZZPhotoAlert *photoAlert = nil; 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | photoAlert = [[ZZPhotoAlert alloc]init]; 19 | }); 20 | return photoAlert; 21 | } 22 | 23 | -(instancetype)initWithFrame:(CGRect)frame 24 | { 25 | self = [super initWithFrame:frame]; 26 | if (self) { 27 | 28 | self.frame = CGRectMake(0, 0, ZZ_SCREEN_WIDTH, ZZ_SCREEN_HEIGHT); 29 | 30 | 31 | 32 | } 33 | return self; 34 | } 35 | 36 | -(void) showPhotoAlert 37 | { 38 | [[UIApplication sharedApplication].keyWindow addSubview:self]; 39 | 40 | UILabel *alertlabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,0,0)]; 41 | 42 | alertlabel.textColor = [UIColor whiteColor]; 43 | 44 | alertlabel.textAlignment = NSTextAlignmentCenter; 45 | 46 | [alertlabel setNumberOfLines:0]; 47 | 48 | NSString *alertText = @"温馨提示\n该图片尚未从iCloud中下载\n下载到本地后重试"; 49 | 50 | alertlabel.text = alertText; 51 | 52 | alertlabel.textAlignment = NSTextAlignmentCenter; 53 | 54 | UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:16]; 55 | 56 | alertlabel.font = font; 57 | 58 | CGSize labelsize = [alertText sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font,NSFontAttributeName, nil]]; 59 | 60 | 61 | [alertlabel setFrame:CGRectMake(8, 8, labelsize.width, labelsize.height)]; 62 | 63 | UIView * alertView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, labelsize.width + 16, labelsize.height +16)]; 64 | 65 | alertView.center = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, [UIScreen mainScreen].bounds.size.height / 2); 66 | 67 | alertView.backgroundColor = [UIColor blackColor]; 68 | 69 | alertView.alpha = 1; 70 | 71 | alertView.layer.masksToBounds = YES; 72 | 73 | alertView.layer.cornerRadius = 4; 74 | 75 | [alertView addSubview:alertlabel]; 76 | 77 | [self addSubview:alertView]; 78 | 79 | [UIView animateWithDuration:3.0f 80 | delay:0 81 | options:UIViewAnimationCurveEaseIn | UIViewAnimationOptionAllowUserInteraction 82 | animations:^{ 83 | 84 | alertView.alpha = 0; 85 | 86 | } 87 | completion:^(BOOL finished){ 88 | if(alertView.alpha == 0) { 89 | 90 | [self removeFromSuperview]; 91 | 92 | } 93 | }]; 94 | 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoBrowerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoBrowerCell.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/10/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | 12 | @interface ZZPhotoBrowerCell : UICollectionViewCell 13 | 14 | -(void)loadPHAssetItemForPics:(PHAsset *)assetItem; 15 | 16 | -(void)recoverSubview; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoBrowerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoBrowerCell.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/10/19. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoBrowerCell.h" 10 | 11 | @interface ZZPhotoBrowerCell() 12 | { 13 | CGFloat _browser_width; 14 | CGFloat _browser_height; 15 | } 16 | @property (nonatomic, strong) UIScrollView *scaleView; 17 | 18 | @property (nonatomic, strong) UIImageView *photo_image_view; 19 | 20 | @end 21 | 22 | @implementation ZZPhotoBrowerCell 23 | 24 | -(instancetype)initWithFrame:(CGRect)frame 25 | { 26 | self = [super initWithFrame:frame]; 27 | if (self) { 28 | 29 | _browser_width = frame.size.width; 30 | _browser_height = frame.size.height; 31 | 32 | _scaleView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, _browser_width, _browser_height)]; 33 | _scaleView.delegate = self; 34 | _scaleView.maximumZoomScale = 2.5; 35 | _scaleView.minimumZoomScale = 1.0; 36 | _scaleView.bouncesZoom = YES; 37 | _scaleView.multipleTouchEnabled = YES; 38 | _scaleView.delegate = self; 39 | _scaleView.scrollsToTop = NO; 40 | _scaleView.showsHorizontalScrollIndicator = NO; 41 | _scaleView.showsVerticalScrollIndicator = NO; 42 | _scaleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 43 | _scaleView.delaysContentTouches = NO; 44 | _scaleView.canCancelContentTouches = YES; 45 | _scaleView.alwaysBounceVertical = NO; 46 | _scaleView.userInteractionEnabled = YES; 47 | [self.contentView addSubview:_scaleView]; 48 | 49 | _photo_image_view = [[UIImageView alloc]init]; 50 | _photo_image_view.userInteractionEnabled = YES; 51 | _photo_image_view.contentMode = UIViewContentModeScaleAspectFit; 52 | [_scaleView addSubview:_photo_image_view]; 53 | 54 | UITapGestureRecognizer *singleFingerOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleFingerEvent:)]; 55 | singleFingerOne.delegate = self; 56 | singleFingerOne.numberOfTapsRequired = 1; 57 | [_photo_image_view addGestureRecognizer:singleFingerOne]; 58 | 59 | 60 | UITapGestureRecognizer *singleFingerTwo = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleFingerEvent:)]; 61 | singleFingerTwo.delegate = self; 62 | singleFingerTwo.numberOfTapsRequired = 2; 63 | [_photo_image_view addGestureRecognizer:singleFingerTwo]; 64 | 65 | } 66 | return self; 67 | } 68 | 69 | -(void)loadPHAssetItemForPics:(PHAsset *)assetItem 70 | { 71 | __weak typeof (self) weakSelf = self; 72 | PHAsset *phAsset = (PHAsset *)assetItem; 73 | CGFloat photoWidth = [UIScreen mainScreen].bounds.size.width; 74 | CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight; 75 | CGFloat multiple = [UIScreen mainScreen].scale; 76 | CGFloat pixelWidth = photoWidth * multiple; 77 | CGFloat pixelHeight = pixelWidth / aspectRatio; 78 | 79 | PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init]; 80 | option.resizeMode = PHImageRequestOptionsResizeModeFast; 81 | 82 | [[PHImageManager defaultManager] requestImageForAsset:phAsset targetSize:CGSizeMake(pixelWidth, pixelHeight) contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 83 | 84 | BOOL downloadFinined = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]; 85 | 86 | if (downloadFinined) { 87 | 88 | if (result != nil) { 89 | [weakSelf changeFrameWithImage:result]; 90 | weakSelf.photo_image_view.image = result; 91 | } 92 | } 93 | 94 | }]; 95 | } 96 | 97 | -(void)changeFrameWithImage:(UIImage *)image 98 | { 99 | CGFloat height = image.size.height / image.size.width * _browser_width; 100 | self.photo_image_view.frame = CGRectMake(0, 0, _browser_width, height); 101 | self.photo_image_view.center = CGPointMake(_browser_width / 2, _browser_height / 2); 102 | _scaleView.contentSize = CGSizeMake(_browser_width, MAX(self.photo_image_view.frame.size.height, _browser_height)); 103 | } 104 | 105 | -(void)recoverSubview 106 | { 107 | [_scaleView setZoomScale:1.0 animated:NO]; 108 | } 109 | 110 | -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 111 | { 112 | return _photo_image_view; 113 | } 114 | 115 | -(void)scrollViewDidZoom:(UIScrollView *)scrollView 116 | { 117 | CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)? 118 | (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0; 119 | CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)? 120 | (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0; 121 | _photo_image_view.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, 122 | scrollView.contentSize.height * 0.5 + offsetY); 123 | } 124 | 125 | - (void)handleSingleFingerEvent:(UITapGestureRecognizer *)sender 126 | { 127 | if (sender.numberOfTapsRequired == 1) { 128 | 129 | }else if(sender.numberOfTapsRequired == 2){ 130 | 131 | if (_scaleView.zoomScale > 1.0) { 132 | [_scaleView setZoomScale:1.0 animated:YES]; 133 | } else { 134 | CGPoint touchPoint = [sender locationInView:self.photo_image_view]; 135 | CGFloat maxScale = _scaleView.maximumZoomScale; 136 | CGFloat xsize = self.frame.size.width / maxScale; 137 | CGFloat ysize = self.frame.size.height / maxScale; 138 | [_scaleView zoomToRect:CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize) animated:YES]; 139 | } 140 | 141 | } 142 | } 143 | 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoHud.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoHud.h 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/14. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZPhotoHud : UIView 12 | 13 | +(ZZPhotoHud *)sharedHud; 14 | 15 | +(void)showActiveHud; 16 | +(void)hideActiveHud; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoHud.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoHud.m 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/14. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoHud.h" 10 | 11 | @interface ZZPhotoHud() 12 | 13 | @property (strong ,nonatomic) UIView *hudView; 14 | @property (strong ,nonatomic) UIActivityIndicatorView *indicatorView; 15 | @property (strong ,nonatomic) UILabel *hudLabel; 16 | 17 | @end 18 | 19 | @implementation ZZPhotoHud 20 | 21 | +(ZZPhotoHud *)sharedHud 22 | { 23 | static ZZPhotoHud *_photoHud = nil; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | _photoHud = [[ZZPhotoHud alloc]init]; 27 | }); 28 | return _photoHud; 29 | } 30 | 31 | -(instancetype)init 32 | { 33 | self = [super init]; 34 | if (self) { 35 | 36 | } 37 | return self; 38 | } 39 | 40 | -(void)show 41 | { 42 | [[UIApplication sharedApplication].keyWindow addSubview:self]; 43 | 44 | [self makeInitUI]; 45 | 46 | [self makeHudUI]; 47 | } 48 | 49 | -(void) makeInitUI 50 | { 51 | //清楚整个背景颜色 52 | self.backgroundColor = [UIColor clearColor]; 53 | self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height); 54 | } 55 | 56 | -(void) makeHudUI 57 | { 58 | _hudView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 120, 90)]; 59 | _hudView.center = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, [UIScreen mainScreen].bounds.size.height / 2); 60 | _hudView.layer.cornerRadius = 8; 61 | _hudView.clipsToBounds = YES; 62 | _hudView.backgroundColor = [UIColor blackColor]; 63 | _hudView.alpha = 0.8; 64 | [self addSubview:_hudView]; 65 | 66 | _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 67 | _indicatorView.frame = CGRectMake(45, 15, 30, 30); 68 | [_hudView addSubview:_indicatorView]; 69 | [_indicatorView startAnimating]; 70 | 71 | _hudLabel = [[UILabel alloc] init]; 72 | _hudLabel.frame = CGRectMake(0,40, 120, 50); 73 | _hudLabel.textAlignment = NSTextAlignmentCenter; 74 | _hudLabel.text = @"图片处理中..."; 75 | _hudLabel.font = [UIFont systemFontOfSize:15]; 76 | _hudLabel.textColor = [UIColor whiteColor]; 77 | [_hudView addSubview:_hudLabel]; 78 | } 79 | 80 | -(void) removeHudUI; 81 | { 82 | [self removeFromSuperview]; 83 | [_indicatorView stopAnimating]; 84 | } 85 | 86 | +(void)showActiveHud 87 | { 88 | [[self sharedHud] show]; 89 | } 90 | 91 | +(void)hideActiveHud 92 | { 93 | [[self sharedHud] removeHudUI]; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoListCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoListCell.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/17. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | @interface ZZPhotoListCell : UITableViewCell 12 | /* 13 | * 相册图片,显示相册的最后一张图片 14 | */ 15 | @property(strong,nonatomic) UIImageView *coverImage; 16 | /* 17 | * 相册标题,显示相册的标题 18 | */ 19 | @property(strong,nonatomic) UILabel *title; 20 | /* 21 | * 相册副标题,显示相册中含有多少张图片 22 | */ 23 | @property(strong,nonatomic) UILabel *subTitle; 24 | 25 | /* 26 | * 加载数据方法 27 | */ 28 | 29 | -(void)loadPhotoListData:(PHAssetCollection *)assetItem; 30 | @end 31 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoListCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoListCell.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/12/17. 6 | // Copyright © 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoListCell.h" 10 | #import "ZZPhotoListModel.h" 11 | @implementation ZZPhotoListCell 12 | 13 | -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 14 | { 15 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 16 | if (self) { 17 | 18 | _coverImage = [[UIImageView alloc]initWithFrame:CGRectMake(10, 5, 60, 60)]; 19 | 20 | _coverImage.layer.masksToBounds = YES; 21 | 22 | _coverImage.contentMode = UIViewContentModeScaleAspectFill; 23 | 24 | [self.contentView addSubview:_coverImage]; 25 | 26 | CGFloat labelWidth = [UIScreen mainScreen].bounds.size.width - 90; 27 | 28 | _title = [[UILabel alloc]initWithFrame:CGRectMake(80, 5, labelWidth, 25)]; 29 | 30 | _title.textColor = [UIColor blackColor]; 31 | 32 | [self.contentView addSubview:_title]; 33 | 34 | _subTitle = [[UILabel alloc]initWithFrame:CGRectMake(80, 40, labelWidth, 25)]; 35 | 36 | _subTitle.textColor = [UIColor blackColor]; 37 | 38 | [self.contentView addSubview:_subTitle]; 39 | 40 | CGFloat right = [UIScreen mainScreen].bounds.size.width; 41 | 42 | UIImageView *right_Cell = [[UIImageView alloc]initWithFrame:CGRectMake(right - 29, 25, 9, 20)]; 43 | 44 | right_Cell.image = PhotoListRightBtn; 45 | 46 | [self.contentView addSubview:right_Cell]; 47 | 48 | } 49 | return self; 50 | } 51 | 52 | 53 | -(void)loadPhotoListData:(ZZPhotoListModel *)listmodel 54 | { 55 | if ([listmodel isKindOfClass:[ZZPhotoListModel class]]) { 56 | 57 | [[PHImageManager defaultManager] requestImageForAsset:listmodel.lastObject targetSize:CGSizeMake(200,200) contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage *result, NSDictionary *info) 58 | { 59 | if (result == nil) { 60 | self.coverImage.image = NOPhoto_Data_Pic; 61 | }else{ 62 | self.coverImage.image = result; 63 | } 64 | 65 | }]; 66 | self.title.text = listmodel.title; 67 | self.subTitle.text = [NSString stringWithFormat:@"%lu",(unsigned long)listmodel.count]; 68 | } 69 | } 70 | @end 71 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoPickerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoPickerCell.h 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/7/7. 6 | // Copyright (c) 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ZZResourceConfig.h" 11 | #import "ZZPhoto.h" 12 | 13 | @interface ZZPhotoPickerCell : UICollectionViewCell 14 | 15 | @property(strong,nonatomic) UIImageView *photo; 16 | @property(strong,nonatomic) UIButton *selectBtn; 17 | 18 | @property(copy ,nonatomic) void(^selectBlock)(); 19 | 20 | @property(assign,nonatomic) BOOL isSelect; 21 | 22 | -(void)loadPhotoData:(ZZPhoto *)photo; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoPickerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoPickerCell.m 3 | // ZZFramework 4 | // 5 | // Created by Yuan on 15/7/7. 6 | // Copyright (c) 2015年 zzl. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoPickerCell.h" 10 | #import "ZZAlumAnimation.h" 11 | @implementation ZZPhotoPickerCell 12 | -(instancetype)initWithFrame:(CGRect)frame 13 | { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | 17 | 18 | _photo = [[UIImageView alloc]initWithFrame:self.bounds]; 19 | 20 | _photo.layer.masksToBounds = YES; 21 | 22 | _photo.contentMode = UIViewContentModeScaleAspectFill; 23 | 24 | [self.contentView addSubview:_photo]; 25 | 26 | 27 | CGFloat btnSize = self.frame.size.width / 4; 28 | 29 | _selectBtn = [[UIButton alloc]initWithFrame:CGRectMake(self.frame.size.width - btnSize - 5, 5, btnSize, btnSize)]; 30 | [_selectBtn addTarget:self action:@selector(selectPhotoButtonMethod:) forControlEvents:UIControlEventTouchUpInside]; 31 | [self.contentView addSubview:_selectBtn]; 32 | 33 | } 34 | return self; 35 | } 36 | 37 | -(void) selectPhotoButtonMethod:(UIButton *)sender 38 | { 39 | [[ZZAlumAnimation sharedAnimation] selectAnimation:sender]; 40 | self.selectBlock(); 41 | 42 | } 43 | 44 | -(void)setIsSelect:(BOOL)isSelect 45 | { 46 | if (isSelect == YES) { 47 | [_selectBtn setImage:Pic_Btn_Selected forState:UIControlStateNormal]; 48 | }else{ 49 | [_selectBtn setImage:Pic_btn_UnSelected forState:UIControlStateNormal]; 50 | } 51 | } 52 | 53 | 54 | -(void)loadPhotoData:(ZZPhoto *)photo 55 | { 56 | if (photo.isSelect == YES) { 57 | [_selectBtn setImage:Pic_Btn_Selected forState:UIControlStateNormal]; 58 | }else{ 59 | [_selectBtn setImage:Pic_btn_UnSelected forState:UIControlStateNormal]; 60 | } 61 | 62 | if ([photo isKindOfClass:[ZZPhoto class]]) { 63 | 64 | [[PHImageManager defaultManager] requestImageForAsset:photo.asset targetSize:CGSizeMake(200, 200) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage *result, NSDictionary *info){ 65 | 66 | self.photo.image = result; 67 | 68 | }]; 69 | 70 | } 71 | } 72 | @end 73 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoPickerFooterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoPickerFooterView.h 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/10/12. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZPhotoPickerFooterView : UICollectionReusableView 12 | 13 | @property (nonatomic, assign) NSInteger total_photo_num; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhoto/View/ZZPhotoPickerFooterView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoPickerFooterView.m 3 | // ZZPhotoKit 4 | // 5 | // Created by 袁亮 on 16/10/12. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import "ZZPhotoPickerFooterView.h" 10 | #import "ZZResourceConfig.h" 11 | 12 | @interface ZZPhotoPickerFooterView() 13 | 14 | @property (nonatomic, strong) UILabel *totalNumLabel; 15 | 16 | @end 17 | 18 | @implementation ZZPhotoPickerFooterView 19 | 20 | -(instancetype)initWithFrame:(CGRect)frame 21 | { 22 | self = [super initWithFrame:frame]; 23 | if (self) { 24 | 25 | [self makeFooterViewUI]; 26 | 27 | } 28 | return self; 29 | } 30 | 31 | -(void) makeFooterViewUI 32 | { 33 | _totalNumLabel = [[UILabel alloc]initWithFrame:CGRectZero]; 34 | _totalNumLabel.textColor = [UIColor blackColor]; 35 | _totalNumLabel.textAlignment = NSTextAlignmentCenter; 36 | _totalNumLabel.translatesAutoresizingMaskIntoConstraints = NO; 37 | [self addSubview:_totalNumLabel]; 38 | 39 | NSLayoutConstraint *total_label_left = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_totalNumLabel attribute:NSLayoutAttributeLeft multiplier:1 constant:0.0f]; 40 | 41 | NSLayoutConstraint *total_label_right = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_totalNumLabel attribute:NSLayoutAttributeRight multiplier:1 constant:0.0f]; 42 | 43 | NSLayoutConstraint *total_label_top = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_totalNumLabel attribute:NSLayoutAttributeTop multiplier:1 constant:0.0f]; 44 | 45 | NSLayoutConstraint *total_label_bottom = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_totalNumLabel attribute:NSLayoutAttributeBottom multiplier:1 constant:0.0f]; 46 | 47 | 48 | [self addConstraints:@[total_label_left,total_label_right,total_label_top,total_label_bottom]]; 49 | 50 | } 51 | 52 | -(void)setTotal_photo_num:(NSInteger)total_photo_num 53 | { 54 | _totalNumLabel.text = [NSString stringWithFormat:Total_Photo_Num,total_photo_num]; 55 | } 56 | 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /ZZPhotoKit/ZZPhotoKit/ZZPhotoKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoKit.h 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/14. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #ifndef ZZPhotoKit_h 10 | #define ZZPhotoKit_h 11 | 12 | #import "ZZPhotoController.h" 13 | #import "ZZCameraController.h" 14 | #import "ZZBrowserPickerViewController.h" 15 | 16 | #import "ZZPhoto.h" 17 | #import "ZZCamera.h" 18 | 19 | /* 20 | # ZZPhotoKit 21 | ##说明 22 | 23 | * 此开源目前接近于成熟状态,不喜欢的大神们还望轻虐。 24 | * 注意此框架只支持 IOS 8.0 及以上系统使用。 25 | * 注意由于工作原因后续不做IOS7适配了,IOS7占有率也比较低了,所以也不考虑后续再做了。 26 | * 这次升级了版本之后以后可能不会有太大变动的。 27 | * 相册多选基于最新的 Photos 框架。 28 | * 相机连续拍摄基于AVFundation 框架。 29 | * 图片浏览器支持 SDWebImage 加载图片 30 | * 欢迎大家使用,欢迎大家Star 31 | 32 | ###告诉我您的APP,使用到我框架的把APP名字告诉我,谢谢哦。单纯看看使用率。(*^__^*) 33 | ###有什么不明白的地方,或者哪里需要改进的可以联系我 34 | ###联系方式 35 | ###关注微博:袁亮_ QQ:412016060 36 | 37 | */ 38 | 39 | 40 | #endif /* ZZPhotoKit_h */ 41 | -------------------------------------------------------------------------------- /ZZPhotoKit/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ZZPhotoKit 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ZZPhotoKitTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ZZPhotoKitTests/ZZPhotoKitTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoKitTests.m 3 | // ZZPhotoKitTests 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZPhotoKitTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ZZPhotoKitTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ZZPhotoKitUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ZZPhotoKitUITests/ZZPhotoKitUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZZPhotoKitUITests.m 3 | // ZZPhotoKitUITests 4 | // 5 | // Created by Yuan on 16/1/4. 6 | // Copyright © 2016年 Ace. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZZPhotoKitUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ZZPhotoKitUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /image/demonstrate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/image/demonstrate.gif -------------------------------------------------------------------------------- /image/examplepic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/image/examplepic.png -------------------------------------------------------------------------------- /image/object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/image/object.png -------------------------------------------------------------------------------- /image/privacy_use.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/image/privacy_use.png -------------------------------------------------------------------------------- /image/zz_camera_intro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Glianze/ZZPhotoKit/bcb48e9983fa5458189ae6267eb018d554787301/image/zz_camera_intro.jpg --------------------------------------------------------------------------------