├── .gitignore
└── TestPhotoKit
├── Direction.h
├── TestPhotoKit.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── TestPhotoKit.xcscmblueprint
├── TestPhotoKit
├── AlbumCell.h
├── AlbumCell.m
├── AlbumCell.xib
├── AlbumController.h
├── AlbumController.m
├── AppDelegate.h
├── AppDelegate.m
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Contents.json
│ ├── asset_selectedOrigion_normal.imageset
│ │ ├── Contents.json
│ │ ├── asset_selectedOrigion_normal@2x.png
│ │ └── asset_selectedOrigion_normal@3x.png
│ ├── asset_selectedOrigion_selected.imageset
│ │ ├── Contents.json
│ │ ├── asset_selectedOrigion_selected@2x.png
│ │ └── asset_selectedOrigion_selected@3x.png
│ ├── imagesBrowse_back.imageset
│ │ ├── Contents.json
│ │ ├── imagesBrowse_back@2x.png
│ │ └── imagesBrowse_back@3x.png
│ ├── message_oeuvre_btn_normal.imageset
│ │ ├── Contents.json
│ │ ├── message_oeuvre_btn_normal@2x.png
│ │ └── message_oeuvre_btn_normal@3x.png
│ └── message_oeuvre_btn_selected.imageset
│ │ ├── Contents.json
│ │ ├── message_oeuvre_btn_selected@2x.png
│ │ └── message_oeuvre_btn_selected@3x.png
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── ContainView.h
├── ContainView.m
├── E8DE84D6-A559-4081-8EFC-BA4542890307.png
├── Info.plist
├── ShowAlbumViewController.h
├── ShowAlbumViewController.m
├── ShowSmartAblumTableViewController.h
├── ShowSmartAblumTableViewController.m
├── ViewController.h
├── ViewController.m
├── imagesShow
│ ├── WZMediaFetcher
│ │ ├── NSObject+WZCommon.h
│ │ ├── NSObject+WZCommon.m
│ │ ├── WZMediaFetcher.h
│ │ ├── WZMediaFetcher.m
│ │ ├── WZToast.h
│ │ └── WZToast.m
│ ├── WZPhotoBrowser
│ │ ├── WZAssetBrowseController
│ │ │ ├── WZAssetBrowseController.h
│ │ │ ├── WZAssetBrowseController.m
│ │ │ ├── WZAssetBrowseNavigationView.h
│ │ │ ├── WZAssetBrowseNavigationView.m
│ │ │ ├── WZAssetBrowseToolView.h
│ │ │ └── WZAssetBrowseToolView.m
│ │ ├── WZImageBrowseController.h
│ │ ├── WZImageBrowseController.m
│ │ ├── WZImageContainerController.h
│ │ ├── WZImageContainerController.m
│ │ ├── WZImageScrollView.h
│ │ ├── WZImageScrollView.m
│ │ ├── WZRemoteImagesBrowseController
│ │ │ ├── WZRemoteImageBrowseController.h
│ │ │ ├── WZRemoteImageBrowseController.m
│ │ │ ├── WZRemoteImageNavigationView.h
│ │ │ └── WZRemoteImageNavigationView.m
│ │ ├── WZRoundRenderLayer.h
│ │ └── WZRoundRenderLayer.m
│ └── WZPhotoPicker
│ │ ├── WZMediaAssetBaseCell.h
│ │ ├── WZMediaAssetBaseCell.m
│ │ ├── WZPhotoCatalogueController.h
│ │ ├── WZPhotoCatalogueController.m
│ │ ├── WZPhotoPickerController.h
│ │ └── WZPhotoPickerController.m
└── main.m
├── TestPhotoKitUITests
├── Info.plist
└── TestPhotoKitUITests.m
└── ThirdLibrary
└── SDWebImage
├── 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
├── UIImageView+HighlightedWebCache.h
├── UIImageView+HighlightedWebCache.m
├── UIImageView+WebCache.h
├── UIImageView+WebCache.m
├── UIView+WebCacheOperation.h
└── UIView+WebCacheOperation.m
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | # CocoaPods
31 | #
32 | # We recommend against adding the Pods directory to your .gitignore. However
33 | # you should judge for yourself, the pros and cons are mentioned at:
34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
35 | #
36 | # Pods/
37 |
38 | # Carthage
39 | #
40 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
41 | # Carthage/Checkouts
42 |
43 | Carthage/Build
44 |
45 | # fastlane
46 | #
47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48 | # screenshots whenever they are needed.
49 | # For more information about the recommended setup visit:
50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
51 |
52 | fastlane/report.xml
53 | fastlane/screenshots
54 |
55 | #Code Injection
56 | #
57 | # After new code Injection tools there's a generated folder /iOSInjectionProject
58 | # https://github.com/johnno1962/injectionforxcode
59 |
60 | iOSInjectionProject/
61 |
--------------------------------------------------------------------------------
/TestPhotoKit/Direction.h:
--------------------------------------------------------------------------------
1 | //
2 | // Direction.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 13/10/17.
6 | // Copyright © 2017年 admin. All rights reserved.
7 | //
8 |
9 | #ifndef Direction_h
10 | #define Direction_h
11 |
12 |
13 | /*
14 | fetch : image、video、audio、gif
15 | image : editing
16 | video : cliping mixture
17 | gif : mixture split
18 | auido : transform into words、clip、mix
19 |
20 | network:
21 | iCloud 部分
22 |
23 | */
24 |
25 |
26 | #endif /* Direction_h */
27 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit.xcodeproj/project.xcworkspace/xcshareddata/TestPhotoKit.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
3 | "824315d4-9642-4b1d-9f8f-75b6ef73f7b3" : {
4 |
5 | }
6 | },
7 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
8 | "824315d4-9642-4b1d-9f8f-75b6ef73f7b3" : 0
9 | },
10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "72138AA8-62E7-4DB1-89EB-2FA71FCDF10A",
11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 | "824315d4-9642-4b1d-9f8f-75b6ef73f7b3" : "..\/.."
13 | },
14 | "DVTSourceControlWorkspaceBlueprintNameKey" : "TestPhotoKit",
15 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
16 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "TestPhotoKit.xcodeproj",
17 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
18 | {
19 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "http:\/\/14.18.242.139:8088\/repos\/yueyueApp",
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Subversion",
21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "824315d4-9642-4b1d-9f8f-75b6ef73f7b3"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AlbumCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // AlbumCell.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AlbumCell : UICollectionViewCell
12 | @property (weak, nonatomic) IBOutlet UIImageView *photoImageView;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AlbumCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // AlbumCell.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import "AlbumCell.h"
10 |
11 | @implementation AlbumCell
12 |
13 | - (void)awakeFromNib {
14 | [super awakeFromNib];
15 | // Initialization code
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AlbumCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AlbumController.h:
--------------------------------------------------------------------------------
1 | //
2 | // AlbumController.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AlbumController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AlbumController.m:
--------------------------------------------------------------------------------
1 | //
2 | // AlbumController.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import "AlbumController.h"
10 | #import "ContainView.h"
11 | #import
12 | #import
13 |
14 | @interface AlbumController ()
15 | @property (nonatomic, strong) ContainView *containView;
16 | @property (nonatomic, strong) PHImageRequestOptions *options;
17 | @property (nonatomic, strong) PHFetchResult *assets;
18 |
19 | @end
20 |
21 | @implementation AlbumController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | [self setupViews];
26 | [self getAllPhotosFromAlbum];
27 |
28 | #pragma mark - 获取video 这段代码这个VC没有使用
29 | PHFetchResult *assetsResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeVideo options:nil];
30 | PHVideoRequestOptions *options2 = [[PHVideoRequestOptions alloc] init];
31 | options2.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
32 | [options2 setNetworkAccessAllowed:true];
33 | for (PHAsset *a in assetsResult) {
34 | [[PHImageManager defaultManager] requestAVAssetForVideo:a options:options2 resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
35 | NSLog(@"%@",info);
36 | NSLog(@"%@",audioMix);
37 | NSLog(@"%@",((AVURLAsset*)asset).URL);//asset为AVURLAsset类型 可直接获取相应视频的相对地址
38 | // NSString *path = ((AVURLAsset*)asset).URL.path;//
39 | }];
40 | }
41 | }
42 |
43 | - (void)setupViews {
44 | self.view.backgroundColor = [UIColor whiteColor];
45 | self.containView =[[ContainView alloc] initWithFrame:self.view.bounds delegate:self];
46 | [self.view addSubview:self.containView];
47 | }
48 |
49 | //从系统中捕获所有相片
50 | - (void)getAllPhotosFromAlbum {
51 | self.options = [[PHImageRequestOptions alloc] init];//请求选项设置
52 | self.options.resizeMode = PHImageRequestOptionsResizeModeExact;//自定义图片大小的加载模式
53 | self.options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
54 | self.options.synchronous = YES;//是否同步加载
55 |
56 | //容器类
57 | self.assets = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil]; //得到所有图片
58 | /*
59 | PHAssetMediaType:
60 | PHAssetMediaTypeUnknown = 0,//在这个配置下,请求不会返回任何东西
61 | PHAssetMediaTypeImage = 1,//图片
62 | PHAssetMediaTypeVideo = 2,//视频
63 | PHAssetMediaTypeAudio = 3,//音频
64 | */
65 | [self.containView.collectionView reloadData];
66 | }
67 |
68 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
69 | return self.assets.count;
70 | }
71 |
72 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
73 | AlbumCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ALBUMCELLID forIndexPath:indexPath];
74 | // cell.backgroundColor= [UIColor redColor];
75 |
76 | //9.0可用
77 | CGSizeMake(self.assets[indexPath.row].pixelWidth, self.assets[indexPath.row].pixelHeight);
78 |
79 | [self adjustGIFWithAsset2:self.assets[indexPath.row]];
80 | [[PHImageManager defaultManager] requestImageForAsset:self.assets[indexPath.row] targetSize: CGSizeMake(110, 110) contentMode:PHImageContentModeDefault options:self.options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
81 | cell.photoImageView.contentMode = UIViewContentModeScaleAspectFit;
82 | cell.photoImageView.image = result;
83 | //// NSLog(@"%@",result);
84 | // NSLog(@"%ld",self.num);
85 | // NSLog(@"%@",info.allKeys);
86 | // NSLog(@"---------------------------------------------------------------");
87 | }];
88 | return cell;
89 | }
90 |
91 |
92 | /** 关于localIdentifier:
93 | * 我们可以在第一次获取到相册中的 GIF 的时候,将其获取到的所有 GIF 的 localIdentifier 记录下来。这样,下次启动的时候,就可以通过这些 localIdentifier 来直接获取 GIF 资源
94 | * PHAsset fetchAssetsWithLocalIdentifiers:<#(nonnull NSArray *)#> options:<#(nullable PHFetchOptions *)#>
95 | */
96 | #pragma mark - 判断资源是不是GIF :(资源类型判别可以为UI提供一些图片类型的指示)
97 | ////方法1 iOS 9.0
98 | - (BOOL)adjustGIFWithAsset:(PHAsset *)asset {
99 | if ([asset isKindOfClass:[PHAsset class]]) {
100 | //每个asset 都有一个或者多个PHAssetResource(如:被编辑保存过的aseet会有若干个resource, 且被修改后的GIF类型的asset得uniformTypeIdentifier 会发生改变变成了public.jpeg 类型,所以修改多地GIF的就不再是GIF了,所以要对比最后一个resource的类型)
101 | NSArray* tmpArr = [PHAssetResource assetResourcesForAsset:asset];
102 | if (tmpArr.count) {
103 | PHAssetResource *resource = tmpArr.lastObject;
104 | if (resource.uniformTypeIdentifier.length) {
105 | return UTTypeConformsTo( (__bridge CFStringRef)resource.uniformTypeIdentifier, kUTTypeGIF);
106 | }
107 | }
108 | }
109 | return false;
110 | }
111 |
112 | //方法2
113 | - (BOOL)adjustGIFWithAsset2:(PHAsset *)asset {
114 | PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
115 | options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
116 | options.resizeMode = PHImageRequestOptionsResizeModeFast;
117 | [options setSynchronous:true];//同步
118 | __block NSString *dataUTIStr = nil;
119 | if ([asset isKindOfClass:[PHAsset class]]) {
120 | [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
121 | dataUTIStr = dataUTI;
122 | }];
123 | }
124 | if (dataUTIStr.length) {
125 | return UTTypeConformsTo( (__bridge CFStringRef)dataUTIStr, kUTTypeGIF);
126 | }
127 | return false;
128 | }
129 |
130 | /**mov转mp4格式 最好设一个block 转完码之后的回调*/
131 | -(void)convertMovWithSourceURL:(NSURL *)sourceUrl fileName:(NSString *)fileName saveExportFilePath:(NSString *)path
132 | {
133 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
134 | [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
135 | }
136 | AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:sourceUrl options:nil];
137 | NSArray *compatiblePresets=[AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];//输出模式标识符的集合
138 | if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality]) {
139 |
140 | AVAssetExportSession *exportSession=[[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];
141 | NSString *resultPath = [path stringByAppendingFormat:@"/%@.mp4",fileName];
142 | exportSession.outputURL=[NSURL fileURLWithPath:resultPath];//输出路径
143 | exportSession.outputFileType = AVFileTypeMPEG4;//输出类型
144 | exportSession.shouldOptimizeForNetworkUse = YES;//为网络使用时做出最佳调整
145 |
146 | [exportSession exportAsynchronouslyWithCompletionHandler:^(void){//异步输出转码视频
147 | switch (exportSession.status) {
148 | case AVAssetExportSessionStatusCancelled:
149 | NSLog(@"转码状态:取消转码");
150 | break;
151 | case AVAssetExportSessionStatusUnknown:
152 | NSLog(@"转码状态:未知");
153 | break;
154 | case AVAssetExportSessionStatusWaiting:
155 | NSLog(@"转码状态:等待转码");
156 | break;
157 | case AVAssetExportSessionStatusExporting:
158 | NSLog(@"转码状态:正在转码");
159 | break;
160 | case AVAssetExportSessionStatusCompleted:
161 | {
162 | NSLog(@"转码状态:完成转码");
163 | NSArray *files=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
164 | for (NSString *fn in files) {
165 | if ([resultPath isEqualToString:fn]) {
166 | NSLog(@"转码状态:完成转码 文件存在");
167 | }
168 | }
169 | break;
170 | }
171 | case AVAssetExportSessionStatusFailed:
172 | NSLog(@"转码状态:转码失败");
173 | NSLog(@"%@",exportSession.error.description);
174 | break;
175 | }
176 | }];
177 | }
178 | }
179 |
180 | @end
181 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. 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 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // 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.
25 | // 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.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // 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.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // 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.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_normal.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "asset_selectedOrigion_normal@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "asset_selectedOrigion_normal@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_normal.imageset/asset_selectedOrigion_normal@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_normal.imageset/asset_selectedOrigion_normal@2x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_normal.imageset/asset_selectedOrigion_normal@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_normal.imageset/asset_selectedOrigion_normal@3x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "asset_selectedOrigion_selected@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "asset_selectedOrigion_selected@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_selected.imageset/asset_selectedOrigion_selected@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_selected.imageset/asset_selectedOrigion_selected@2x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_selected.imageset/asset_selectedOrigion_selected@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/asset_selectedOrigion_selected.imageset/asset_selectedOrigion_selected@3x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/imagesBrowse_back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "imagesBrowse_back@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "imagesBrowse_back@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/imagesBrowse_back.imageset/imagesBrowse_back@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/imagesBrowse_back.imageset/imagesBrowse_back@2x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/imagesBrowse_back.imageset/imagesBrowse_back@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/imagesBrowse_back.imageset/imagesBrowse_back@3x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_normal.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "message_oeuvre_btn_normal@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "message_oeuvre_btn_normal@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_normal.imageset/message_oeuvre_btn_normal@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_normal.imageset/message_oeuvre_btn_normal@2x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_normal.imageset/message_oeuvre_btn_normal@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_normal.imageset/message_oeuvre_btn_normal@3x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "message_oeuvre_btn_selected@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "message_oeuvre_btn_selected@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_selected.imageset/message_oeuvre_btn_selected@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_selected.imageset/message_oeuvre_btn_selected@2x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_selected.imageset/message_oeuvre_btn_selected@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/Assets.xcassets/message_oeuvre_btn_selected.imageset/message_oeuvre_btn_selected@3x.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
30 |
37 |
44 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ContainView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ContainView.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AlbumCell.h"
11 | #define ALBUMCELLID @"AlbumCellIdentifier"
12 | @interface ContainView : UIView
13 | @property (nonatomic, strong) UICollectionView *collectionView;
14 | - (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ContainView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ContainView.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import "ContainView.h"
10 | @interface ContainView()
11 |
12 | @property (nonatomic, weak) id delegate;
13 | @end
14 |
15 | @implementation ContainView
16 |
17 | - (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate {
18 | if (self = [super initWithFrame:frame]) {
19 | self.delegate = delegate;
20 | [self setupViews];
21 |
22 | }
23 | return self;
24 | }
25 | - (UICollectionView *)collectionView {
26 | if (!_collectionView) {
27 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
28 | layout.minimumInteritemSpacing = 0;
29 | _collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout];
30 | _collectionView.delegate = _delegate;
31 | _collectionView.dataSource = _delegate;
32 | [_collectionView registerNib:[UINib nibWithNibName:@"AlbumCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:ALBUMCELLID];
33 | _collectionView.backgroundColor = [UIColor whiteColor];
34 | }
35 | return _collectionView;
36 | }
37 |
38 | - (void)setupViews {
39 | [self addSubview:self.collectionView];
40 | }
41 | @end
42 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/E8DE84D6-A559-4081-8EFC-BA4542890307.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wizetLee/TestPhotoKit/8a2404f78b381559fb8003ff2f23ebdbad156a77/TestPhotoKit/TestPhotoKit/E8DE84D6-A559-4081-8EFC-BA4542890307.png
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleAllowMixedLocalizations
6 |
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 |
32 | NSPhotoLibraryUsageDescription
33 | available
34 | UILaunchStoryboardName
35 | LaunchScreen
36 | UIMainStoryboardFile
37 | Main
38 | UIRequiredDeviceCapabilities
39 |
40 | armv7
41 |
42 | UISupportedInterfaceOrientations
43 |
44 | UIInterfaceOrientationPortrait
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ShowAlbumViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ShowAlbumViewController.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | @interface ShowAlbumViewController : UICollectionViewController
12 | @property (nonatomic, strong) PHFetchResult *assets;
13 | @end
14 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ShowAlbumViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShowAlbumViewController.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import "ShowAlbumViewController.h"
10 |
11 | @interface ShowAlbumViewController ()
12 |
13 | @end
14 |
15 | @implementation ShowAlbumViewController
16 |
17 | static NSString * const reuseIdentifier = @"Cell";
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 | self.collectionView.backgroundColor = [UIColor whiteColor];
22 | self.collectionView.delegate = self;
23 | self.collectionView.dataSource = self;
24 | [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
25 | }
26 |
27 |
28 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
29 | return 1;
30 | }
31 |
32 |
33 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
34 | return self.assets.count;
35 | }
36 |
37 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
38 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
39 | for (UIView *view in cell.subviews ) {
40 | [view removeFromSuperview];
41 | }
42 |
43 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.contentView.frame];
44 | imageView.contentMode = UIViewContentModeScaleToFill;
45 | [cell addSubview:imageView];
46 |
47 |
48 |
49 | PHImageRequestOptions *imageOptions = [[PHImageRequestOptions alloc] init];
50 | imageOptions.synchronous = NO;//YES 一定是同步 NO不一定是异步
51 | imageOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
52 | /*
53 | PHImageRequestOptionsResizeModeNone // 不调整大小
54 | PHImageRequestOptionsResizeModeFast // 由系统去安排,情况不定:有时你设置的size比较低,会根据你设的size,有时又会比
55 | PHImageRequestOptionsResizeModeExact// 保证精确到自定义size :此处精确的前提得用PHImageContentModeAspectFill
56 | */
57 |
58 | //simageOptions.version = PHImageRequestOptionsVersionCurrent;//版本 iOS8.0之后出的图片编辑extension,可以根据次枚举获取原图或者是经编辑过的图片,
59 | /*PHImageRequestOptionsVersion:
60 | PHImageRequestOptionsVersionCurrent = 0, //当前的(编辑过?经过编辑的图:原图)
61 | PHImageRequestOptionsVersionUnadjusted, //经过编辑的图
62 | PHImageRequestOptionsVersionOriginal //原始图片
63 | */
64 |
65 | // imageOptions.networkAccessAllowed = YES;//用于开启iClould中下载图片
66 | // imageOptions.progressHandler //iClould下载进度的回调
67 |
68 | imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;//imageOptions.synchronous = NO的情况下最终决定是否是异步
69 | NSLog(@"%ld",indexPath.row);
70 |
71 | //返回一个 PHImageRequestID
72 | //在异步请求时可以根据这个ID去取消请求,同步就没办法了..
73 | [[PHImageManager defaultManager] requestImageForAsset:self.assets[indexPath.row] targetSize:CGSizeMake(120,120) contentMode:PHImageContentModeAspectFit options:imageOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
74 | /*
75 | 最终产生图片的size是有 imageOptions.resizeMode(即PHImageRequestOptions) 以及 PHImageContentMode 决定的,当然也有我们设定的size
76 | 优先级而言
77 | PHImageRequestOptions > PHImageContentMode
78 | */
79 |
80 | //这个handler 并非在主线程上执行,所以如果有UI的更新操作就得手动添加到主线程中
81 | // dispatch_async(dispatch_get_main_queue(), ^{ //update UI });
82 | imageView.image = result;
83 | NSLog(@"%@",result);
84 | NSLog(@"%@",info);
85 | }];
86 |
87 | /*注意这个info字典 有时这个info甚至为null 慎用
88 | 里面的key是比较奇怪的
89 | 尽量不要用里面的key
90 | 因为这个key 会变动: 当我们最终获取到的图片的size的高/宽 没有一个达到能原有的图片size的高/宽时
91 | 部分key 会消失 如 PHImageFileSandboxExtensionTokenKey , PHImageFileURLKey
92 | */
93 |
94 |
95 | /*
96 | 在PHImageContentModeAspectFill 下 图片size 有一个分水岭 {125,125} {126,126}
97 | 当imageOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
98 | 时: 设置size 小于{125,125}时,你得到的图片size 将会是设置的1/2
99 |
100 | 而在PHImageContentModeAspectFit 分水岭 {120,120} {121,121}
101 | */
102 | return cell;
103 | }
104 |
105 | @end
106 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ShowSmartAblumTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ShowSmartAblumTableViewController.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 17/6/12.
6 | // Copyright © 2017年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ShowSmartAblumTableViewController : UITableViewController
12 |
13 | @property (nonatomic, assign) NSInteger albumCount;
14 | @property (nonatomic, strong) NSMutableArray *albumNameArr;
15 | @property (nonatomic, strong) NSMutableArray *albumAssetsArr;
16 | - (instancetype)initWithAlbumCount:(NSInteger)albumCount;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ShowSmartAblumTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShowSmartAblumTableViewController.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 17/6/12.
6 | // Copyright © 2017年 admin. All rights reserved.
7 | //
8 |
9 | #import "ShowSmartAblumTableViewController.h"
10 | #import
11 | #import "ShowAlbumViewController.h"
12 |
13 | #define CELLID @"cellID"
14 |
15 | @interface ShowSmartAblumTableViewController ()
16 |
17 | @end
18 |
19 | @implementation ShowSmartAblumTableViewController
20 |
21 | #pragma mark - Initialize
22 |
23 | - (instancetype)initWithAlbumCount:(NSInteger)albumCount {
24 | if (self =[super initWithStyle:UITableViewStylePlain]) {
25 | self.albumCount = albumCount;
26 | }
27 | return self;
28 | }
29 |
30 | #pragma mark - Lifecycle
31 |
32 | - (void)viewDidLoad {
33 | [super viewDidLoad];
34 | self.view.backgroundColor = [UIColor whiteColor];
35 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CELLID];
36 | }
37 |
38 | #pragma mark - - Table view data source
39 |
40 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
41 | return 1;
42 | }
43 |
44 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
45 | return self.self.albumNameArr.count;
46 | }
47 |
48 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
49 |
50 | UITableViewCell * cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CELLID];
51 | cell.textLabel.text = self.albumNameArr[indexPath.row];
52 | cell.detailTextLabel.text = [NSString stringWithFormat:@"%ld张",((PHFetchResult *)self.albumAssetsArr[indexPath.row]).count];
53 |
54 | return cell;
55 | }
56 |
57 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
58 | if (self.albumAssetsArr[indexPath.row] && ((PHFetchResult *)self.albumAssetsArr[indexPath.row]).count >0) {
59 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
60 | layout.minimumInteritemSpacing = 0;
61 | ShowAlbumViewController *SAVC = [[ShowAlbumViewController alloc] initWithCollectionViewLayout:layout];
62 | SAVC.assets = self.albumAssetsArr[indexPath.row];
63 | [self.navigationController pushViewController:SAVC animated:YES];
64 | }
65 | }
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ShowSmartAblumTableViewController.h"
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZMediaFetcher/NSObject+WZCommon.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+WZCommon.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/19.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 |
13 | /**
14 | * 作用于系统的权限 设置等
15 | */
16 | @interface NSObject (WZCommon)
17 |
18 |
19 | /**
20 | 获取相册权限
21 | @param handler 获取权限结果
22 | */
23 | + (void)requestPhotosLibraryAuthorization:(void(^)(BOOL ownAuthorization))handler;
24 |
25 |
26 | /**
27 | 进入app设置页面
28 | */
29 | + (void)openAppSettings;
30 |
31 |
32 | /**
33 | 颜色转图片
34 |
35 | @param color 颜色
36 | @return 图片
37 | */
38 | + (UIImage *)imageWithColor:(UIColor *)color;
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZMediaFetcher/NSObject+WZCommon.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+WZCommon.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/19.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "NSObject+WZCommon.h"
10 |
11 | @implementation NSObject (WZCommon)
12 |
13 | /**
14 | 获取相册权限
15 | @param handler 获取权限结果
16 | */
17 | + (void)requestPhotosLibraryAuthorization:(void(^)(BOOL ownAuthorization))handler {
18 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
19 | if (handler) {
20 | BOOL boolean = false;
21 | if (status == PHAuthorizationStatusAuthorized) {
22 | boolean = true;
23 | }
24 | handler(boolean);
25 | }
26 | }];
27 | }
28 |
29 | /**
30 | 进入app设置页面
31 | */
32 | + (void)openAppSettings {
33 | NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
34 | if([[UIApplication sharedApplication] canOpenURL:url]) {
35 | NSURL*url =[NSURL URLWithString:UIApplicationOpenSettingsURLString];
36 | [[UIApplication sharedApplication] openURL:url];
37 | } else {
38 | NSLog(@"无法打开设置");
39 | }
40 | }
41 |
42 | /************************************************/
43 | //颜色转图
44 | + (UIImage *)imageWithColor:(UIColor *)color
45 | {
46 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
47 | UIGraphicsBeginImageContext(rect.size);
48 | CGContextRef context = UIGraphicsGetCurrentContext();
49 |
50 | CGContextSetFillColorWithColor(context, [color CGColor]);
51 | CGContextFillRect(context, rect);
52 |
53 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
54 | UIGraphicsEndImageContext();
55 |
56 | return image;
57 | }
58 | @end
59 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZMediaFetcher/WZMediaFetcher.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZMediaFetcher.h
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/7.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import "NSObject+WZCommon.h"
12 | #define WZMEDIAASSET_CUSTOMSIZE CGSizeMake(2000, 2000) //大图限定的尺寸
13 |
14 | #define WZMEDIAASSET_THUMBNAILSIZE CGSizeMake(250, 250) //缩略图限定的尺寸
15 |
16 | #define MACRO_COLOR_HEX_ALPHA(hexValue, alpha) [UIColor colorWithRed:((float)((hexValue & 0xFF0000) >> 16))/255.0 green:((float)((hexValue & 0xFF00) >> 8))/255.0 blue:((float)(hexValue & 0xFF))/255.0 alpha:alpha]
17 | #define MACRO_COLOR_HEX(hexValue) MACRO_COLOR_HEX_ALPHA(hexValue, 1.0)
18 |
19 | @class WZMediaAsset;
20 | @protocol WZProtocolMediaAsset
21 |
22 | @optional
23 |
24 | /**
25 | * 选中图片的自定义资源集合的回调
26 | *
27 | * @param assets 自定义资源集合
28 | */
29 | - (void)fetchAssets:(NSArray *)assets;
30 |
31 | //同步获取图片数据 images + loading + end + callback
32 | /**
33 | * 选中图片集合的回调
34 | *
35 | * @param images 图片集合
36 | */
37 | - (void)fetchImages:(NSArray *)images;
38 |
39 | @end
40 |
41 | /**
42 | * media类型枚举
43 | */
44 | typedef NS_ENUM(NSUInteger, WZMediaType) {
45 | /**
46 | * 未知类型(默认)
47 | */
48 | WZMediaTypeUnknow = 0,
49 | /**
50 | * 图片类型
51 | */
52 | WZMediaTypePhoto = 1,
53 | /**
54 | * 视频类型
55 | */
56 | WZMediaTypeVideo = 2,
57 | /**
58 | * 音频类型
59 | */
60 | WZMediaTypeAudio = 3,
61 | };
62 |
63 | #pragma mark - WZMediaAsset
64 | @interface WZMediaAsset : NSObject
65 |
66 | @property (nonatomic, assign) BOOL selected;//是否已被选中
67 | @property (nonatomic, assign) BOOL origion;//是否应显示原尺寸图片
68 |
69 | @property (nonatomic, strong) PHAsset *asset;//元数据资源
70 | @property (nonatomic, assign) WZMediaType mediaType;//meida 类型 video image 等
71 |
72 | ///大小由宏定义
73 | @property (nonatomic, strong) UIImage *imageClear;//清晰图(原尺寸图片或者是大图{2000, 200s0})
74 | @property (nonatomic, strong) UIImage *imageThumbnail;//缩略图{250, 250}
75 |
76 | @property (nonatomic, strong) NSURL *remoteMediaURL;//用于获取远程资源的URL
77 | @property (nonatomic, strong) NSString *clearPath;//保存到本地的清晰图的路径
78 |
79 | /**
80 | * 获取缩略图
81 | *
82 | * @param synchronous 是否同步
83 | * @param handler 图片回调
84 | */
85 | - (void)fetchThumbnailImageSynchronous:(BOOL)synchronous handler:(void (^)(UIImage *image))handler;
86 |
87 | /**
88 | * 获取原尺寸图
89 | *
90 | * @param synchronous 是否同步
91 | * @param handler 图片回调
92 | */
93 | - (void)fetchOrigionImageSynchronous:(BOOL)synchronous handler:(void (^)(UIImage *image))handler;
94 |
95 | @end
96 |
97 | #pragma mark - WZMediaAssetCollection
98 | @interface WZMediaAssetCollection : NSObject
99 |
100 | @property (nonatomic, strong) NSArray * mediaAssetArray;//数据载体
101 | @property (nonatomic, strong) PHAssetCollection *assetCollection;//相册的载体
102 | @property (nonatomic, strong) NSString *title;//相册的title
103 | @property (nonatomic, strong) WZMediaAsset *coverAssset;//封面资源 默认是 assetMArray 首个元素
104 |
105 | /**
106 | * 自定义封面资源
107 | *
108 | * @param mediaAsset 自定义的封面资源
109 | * @param handler 回调所得到的封面图
110 | */
111 | - (void)customCoverWithMediaAsset:(WZMediaAsset *)mediaAsset withCoverHandler:(void(^)(UIImage *image))handler;
112 |
113 | /**
114 | * 封面图的回调
115 | *
116 | * @param handler 回调所得到的封面图
117 | */
118 | - (void)coverHandler:(void(^)(UIImage *image))handler;
119 |
120 | @end
121 |
122 | #pragma mark - WZMediaFetcher
123 | @interface WZMediaFetcher : NSObject
124 |
125 | //扩展 获取视频 以及 特定音频的资源组合
126 | //获取所需要的资源集合的集合
127 |
128 | //获取最普通的资源集合
129 | + (NSMutableArray *)fetchAssetCollection;
130 |
131 | //获取拥有所有图片的胶卷集合
132 | + (NSArray *)allImagesAssets;
133 |
134 | //获取拥有所有视频的集合
135 | + (NSArray *)allVideosAssets;
136 |
137 |
138 |
139 | //获取个人自定义创建的相册(也就是我的相簿)的集合<只有图片类型>
140 | + (NSArray *)customMediaAssetCollectionOnlyImageAsset;
141 | //获取个人自定义创建的相册(也就是我的相簿)的集合<只有视频类型>
142 | + (NSArray *)customMediaAssetCollectionOnlyVideoAsset;
143 | //获取个人自定义创建的相册(也就是我的相簿)的集合<也有视频/图片类型>
144 | + (NSArray *)customMediaAssetCollectionOnlyImageHybirdVideoAsset;
145 |
146 |
147 | #pragma mark - Fetch Picture
148 |
149 | /**
150 | * 获取目标资源的缩略图 size为WZMEDIAASSET_THUMBNAILSIZE
151 | *
152 | * @param mediaAsset 目标资源
153 | * @param synchronous 是否同步获取
154 | * @param handler 返回图片的block
155 | *
156 | * @return 资源ID
157 | */
158 | + (int32_t)fetchThumbnailWithAsset:(PHAsset *)mediaAsset synchronous:(BOOL)synchronous handler:(void(^)(UIImage *thumbnail))handler ;
159 |
160 | /**
161 | * 获取目标资源的原尺寸图
162 | *
163 | * @param mediaAsset 目标资源
164 | * @param synchronous 是否同步获取
165 | * @param handler 返回图片的block
166 | *
167 | * @return 资源ID
168 | */
169 | + (int32_t)fetchOrigionWith:(PHAsset *)mediaAsset synchronous:(BOOL)synchronous handler:(void(^)(UIImage *origion))handler;
170 |
171 | /**
172 | * 获取目标资源的图 自定义size
173 | *
174 | * @param mediaAsset 目标资源
175 | * @param costumSize 自定义size
176 | * @param synchronous 是否同步获取
177 | * @param handler 返回图片的block
178 | *
179 | * @return 资源ID
180 | */
181 | + (int32_t)fetchImageWithAsset:(PHAsset *)mediaAsset costumSize:(CGSize)customSize synchronous:(BOOL)synchronous handler:(void(^)(UIImage *origion))handler;
182 |
183 | /**
184 | * 获取目标资源的原尺寸图
185 | *
186 | * @param asset 目标资源
187 | * @param synchronous 是否同步获取
188 | * @param handler data形式 图片方向 图片的详情info
189 | *
190 | * @return 资源ID
191 | */
192 | + (int32_t)fetchImageWithAsset:(PHAsset *)asset synchronous:(BOOL)synchronous handler:(void (^)(NSData * imageData, NSString * dataUTI, UIImageOrientation orientation, NSDictionary * info))handler;
193 |
194 | #pragma mark - Fetch Video
195 | //+ (int32_t)fetchVideoWith:(PHAsset *)asset
196 |
197 |
198 | #pragma mark - Fetch Audio
199 |
200 | @end
201 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZMediaFetcher/WZToast.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZToast.h
3 |
4 |
5 |
6 | #import
7 | typedef NS_ENUM(NSUInteger, WZToastPositionType) {
8 | WZToastPositionTypeMiddle = 0,
9 | WZToastPositionTypeTop = 1,
10 | WZToastPositionTypeBottom = 2,
11 | };
12 |
13 | @interface WZToast : UIView
14 |
15 |
16 | + (void)toastWithContent:(NSString *)content;
17 |
18 | + (void)toastWithContent:(NSString *)content duration:(NSTimeInterval)duration;
19 |
20 | + (void)toastWithContent:(NSString *)content position:(WZToastPositionType)position;
21 |
22 | + (void)toastWithContent:(NSString *)content
23 | position:(WZToastPositionType)position
24 | duration:(NSTimeInterval)duration;
25 |
26 | + (void)toastWithContent:(NSString *)content
27 | position:(WZToastPositionType)position
28 | customOriginY:(CGFloat)customOriginY;
29 |
30 | + (void)toastWithContent:(NSString *)content
31 | position:(WZToastPositionType)position
32 | customOrigin:(CGPoint)customOrigin;
33 | @end
34 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZMediaFetcher/WZToast.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZToast.m
3 |
4 |
5 | #import "WZToast.h"
6 |
7 | @implementation WZToast
8 |
9 | + (void)toastWithContent:(NSString *)content {
10 | [WZToast toastWithContent:content position:WZToastPositionTypeMiddle];
11 | }
12 |
13 | + (void)toastWithContent:(NSString *)content duration:(NSTimeInterval)duration {
14 | [WZToast toastWithContent:content position:WZToastPositionTypeMiddle duration:duration];
15 | }
16 |
17 | + (void)toastWithContent:(NSString *)content position:(WZToastPositionType)position {
18 | [WZToast toastWithContent:content position:position duration:1.5];
19 | }
20 |
21 | + (void)toastWithContent:(NSString *)content
22 | position:(WZToastPositionType)position
23 | duration:(NSTimeInterval)duration {
24 | [WZToast toastWithContent:content position:position duration:duration customOriginY:false customOriginYMake:0 customOrigin:false customOriginMake:CGPointZero];
25 | }
26 |
27 | + (void)toastWithContent:(NSString *)content
28 | position:(WZToastPositionType)position
29 | customOriginY:(CGFloat)customOriginY {
30 | [WZToast toastWithContent:content position:position duration:1.5 customOriginY:true customOriginYMake:customOriginY customOrigin:false customOriginMake:CGPointZero];
31 | }
32 |
33 | + (void)toastWithContent:(NSString *)content
34 | position:(WZToastPositionType)position
35 | customOrigin:(CGPoint)customOrigin {
36 | [WZToast toastWithContent:content position:position duration:1.5 customOriginY:false customOriginYMake:0 customOrigin:true customOriginMake:customOrigin];
37 | }
38 |
39 | + (void)toastWithContent:(NSString *)content
40 | position:(WZToastPositionType)position
41 | duration:(NSTimeInterval)duration
42 | customOriginY:(BOOL)customOriginY
43 | customOriginYMake:(CGFloat)customOriginYMake
44 | customOrigin:(BOOL)customOrigin
45 | customOriginMake:(CGPoint)customOriginMake
46 | {
47 | WZToast *toastView = [[WZToast alloc] init];
48 | toastView.alpha = 0.0;
49 | toastView.layer.cornerRadius = 10.0;
50 | toastView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
51 |
52 | //structure layout
53 | if ([content isKindOfClass:[NSString class]] && ![content isEqualToString:@""]) {
54 |
55 | UILabel *toastLabel = [[UILabel alloc] init];
56 | toastLabel.textColor = [UIColor whiteColor];
57 | toastLabel.backgroundColor = [UIColor clearColor];
58 | toastLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
59 | toastLabel.text = content;
60 | toastLabel.textAlignment = NSTextAlignmentCenter;
61 | toastLabel.numberOfLines = 0;
62 | UIWindow *forefrontWindow = [WZToast getFrontWindow];
63 | [toastView addSubview:toastLabel];
64 | [forefrontWindow addSubview:toastView];
65 |
66 |
67 | //structure detail
68 | CGFloat labelLRSpacingSum = 30;
69 | CGFloat labelTBSpacingSum = 30;
70 | CGFloat labelH = [toastLabel sizeThatFits:CGSizeZero].height + 30;
71 | CGFloat labelW = [toastLabel sizeThatFits:CGSizeZero].width;
72 | CGFloat boundingSpacing = 40.0;
73 |
74 | CGFloat toastRestrictW = [UIScreen mainScreen].bounds.size.width - boundingSpacing * 2.0;
75 |
76 | if (labelW > toastRestrictW) {
77 | CGFloat calculatelabelW = toastRestrictW - labelLRSpacingSum;
78 | labelH = [toastLabel sizeThatFits:CGSizeMake(calculatelabelW - labelLRSpacingSum, 0)].height
79 | + labelTBSpacingSum
80 | - 4.0;
81 | labelW = [toastLabel sizeThatFits:CGSizeMake(calculatelabelW - labelLRSpacingSum, 0)].width;
82 | }
83 | toastLabel.frame = CGRectMake(labelLRSpacingSum / 2.0
84 | , 0.0
85 | , labelW
86 | , labelH);
87 | CGFloat toastW = labelW + labelLRSpacingSum;
88 | CGFloat toastH = labelH;
89 | CGFloat toastX = ([UIScreen mainScreen].bounds.size.width - toastW) / 2.0;
90 | CGFloat toastY = ([UIScreen mainScreen].bounds.size.height - toastH) / 2.0;
91 |
92 | //Y坐标的计算
93 | switch (position) {
94 | break;
95 | case WZToastPositionTypeTop:
96 | {
97 | toastY = 100.0;
98 | }
99 | break;
100 |
101 | case WZToastPositionTypeBottom:
102 | {
103 | toastY = [UIScreen mainScreen].bounds.size.height - toastH - 100.0;
104 | }
105 | break;
106 | default/*WZToastPositionTypeMiddle*/:
107 | break;
108 | }
109 |
110 |
111 | if (customOriginY) {
112 | toastY = customOriginYMake;
113 | }
114 |
115 | if (customOrigin) {
116 | toastX = customOriginMake.x;
117 | toastY = customOriginMake.y;
118 | }
119 |
120 | // style normal middle
121 | toastView.frame = CGRectMake(toastX
122 | ,toastY
123 | , toastW
124 | , toastH);
125 |
126 | //part of effect
127 | [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
128 | toastView.alpha = 1.0;
129 | } completion:^(BOOL finished) {
130 | [UIView animateWithDuration:0.8 delay:0.5 + 0.25 options:UIViewAnimationOptionAllowUserInteraction animations:^{
131 | toastView.alpha = 0.0;
132 | } completion:^(BOOL finished) {
133 | [toastView removeFromSuperview];
134 | }];
135 | }];
136 | }
137 | }
138 |
139 | + (UIWindow *)getFrontWindow {
140 | UIWindow *frontWindow = nil;
141 | NSEnumerator *frontToBackWindows = [[UIApplication sharedApplication].windows reverseObjectEnumerator];
142 | for (UIWindow *window in frontToBackWindows) {
143 | BOOL isWindowOnMainScreen = (window.screen == [UIScreen mainScreen]); //当前屏幕
144 | BOOL isWindowVisible = (!window.hidden && window.alpha > 0.001); //透明度
145 | BOOL isWindowNormalLevel = (window.windowLevel == UIWindowLevelNormal); //
146 | if (isWindowOnMainScreen && isWindowVisible && isWindowNormalLevel) {
147 | frontWindow = window;
148 | }
149 | }
150 |
151 | if (!frontWindow) {
152 | frontWindow = [UIApplication sharedApplication].windows.lastObject;
153 | }
154 |
155 | return frontWindow;
156 | }
157 |
158 | @end
159 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZAssetBrowseController/WZAssetBrowseController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZAssetBrowseController.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZImageBrowseController.h"
10 |
11 |
12 | @interface WZAssetBrowseController : WZImageBrowseController
13 |
14 | @property (nonatomic, assign) PHImageRequestID imageRequestID;//请求图片的请求ID
15 | @property (nonatomic, assign) PHImageRequestID imageDataRequestID;//请求图片(data)的请求ID
16 |
17 | /**
18 | * 用于判断滑动的图片是否越界
19 | *
20 | * @return 是否越界
21 | */
22 | - (BOOL)overloadJudgement;
23 |
24 | /**
25 | * 用于计算当前选中的图片数目的接口
26 | */
27 | - (void)caculateSelected;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZAssetBrowseController/WZAssetBrowseController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZAssetBrowseController.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZAssetBrowseController.h"
10 | #import "WZAssetBrowseNavigationView.h"
11 | #import "WZAssetBrowseToolView.h"
12 |
13 | @interface WZAssetBrowseController ()
14 |
15 | @property (nonatomic, strong) WZAssetBrowseNavigationView *navigationView;//顶部导航条
16 | @property (nonatomic, strong) WZAssetBrowseToolView *toolView;//底部工具条
17 |
18 | @end
19 |
20 | @implementation WZAssetBrowseController
21 |
22 | #pragma mark - Lifecycle
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | }
26 |
27 | - (void)dealloc {
28 | NSLog(@"%s", __func__);
29 | }
30 |
31 | #pragma mark - CreateViews
32 | - (void)createViews {
33 | [self.view addSubview:self.navigationView];
34 | [self.view addSubview:self.toolView];
35 | [self caculateSelected];
36 | self.view.backgroundColor = [UIColor blackColor];
37 |
38 | }
39 |
40 |
41 | #pragma mark - WZProtocolAssetBrowseNaviagtion
42 | - (void)backAction {
43 | if ([self.imagesBrowseDelegate respondsToSelector:@selector(backAction)]) {
44 | [self.imagesBrowseDelegate backAction];
45 | }
46 | [self dismissViewControllerAnimated:true completion:^{}];
47 | }
48 |
49 | - (void)selectedAction {
50 | if ([self overloadJudgement] && !self.currentMediaAsset.selected) {
51 | return;
52 | }
53 |
54 | self.currentMediaAsset.selected = !self.currentMediaAsset.selected;
55 | _navigationView.selectedButton.selected = self.currentMediaAsset.selected;
56 | [self caculateSelected];
57 | }
58 |
59 | #pragma mark - WZProtocolAssetBrowseTool
60 | - (void)selectedOrigionAction {
61 | self.currentMediaAsset.origion = !self.currentMediaAsset.origion;
62 | self.toolView.selectedButtonClear.selected = self.currentMediaAsset.origion;
63 | [self fetchOrigion];
64 | }
65 |
66 | - (void)completeAction {
67 | [self dismissViewControllerAnimated:false completion:^{
68 | if ([self.imagesBrowseDelegate respondsToSelector:@selector(send)]) {
69 | [self.imagesBrowseDelegate send];
70 | }
71 | }];
72 | }
73 |
74 | #pragma mark - Match image
75 | - (void)matchThumnailImageWith:(WZImageContainerController *)VC {
76 | [super matchThumnailImageWith:VC];
77 |
78 | NSUInteger index = VC.index;
79 | if (index < self.mediaAssetArray.count ) {
80 | WZMediaAsset *asset = self.mediaAssetArray[index];
81 | if (asset.imageThumbnail) {
82 | [VC matchingPicture:asset.imageThumbnail];
83 | } else {
84 | [WZMediaFetcher fetchThumbnailWithAsset:asset.asset synchronous:false handler:^(UIImage *thumbnail) {
85 | asset.imageThumbnail = thumbnail;
86 | [VC matchingPicture:asset.imageThumbnail];
87 | }];
88 | }
89 | }
90 | }
91 |
92 | - (void)matchClearImageWith:(WZImageContainerController *)VC {
93 | [super matchClearImageWith:VC];
94 |
95 | NSUInteger index = VC.index;
96 | WZMediaAsset *asset = nil;
97 | if (index < self.mediaAssetArray.count ) {
98 | asset = self.mediaAssetArray[index];
99 |
100 | if (asset.clearPath || asset.imageClear) {
101 | if (asset.imageClear) {
102 | [VC matchingPicture:asset.imageClear];
103 | [self caculateImageDataWithImage:asset.imageClear];
104 | } else {
105 | UIImage *image = [UIImage imageWithContentsOfFile:asset.clearPath];
106 | [VC matchingPicture:image];
107 | [self caculateImageDataWithImage:image];
108 | }
109 |
110 | } else if (asset.asset) {
111 | //根据 PHAsset callback
112 | //block回调可能会引起图片紊乱(重用) 请求前先将之前的request cancel掉
113 |
114 | [[PHImageManager defaultManager] cancelImageRequest:_imageRequestID];
115 | [[PHImageManager defaultManager] cancelImageRequest:_imageDataRequestID];
116 |
117 | if (asset.origion) {
118 | _imageRequestID = [WZMediaFetcher fetchOrigionWith:asset.asset synchronous:false handler:^(UIImage *origion) {
119 | [VC matchingPicture:origion];
120 | }];
121 | } else {
122 | //渲染成本太高 不选源图
123 | _imageRequestID = [WZMediaFetcher fetchImageWithAsset:asset.asset costumSize:WZMEDIAASSET_CUSTOMSIZE synchronous:false handler:^(UIImage *image) {
124 | [VC matchingPicture:image];
125 | }];
126 | }
127 |
128 | //数据计算
129 | _imageDataRequestID = [WZMediaFetcher fetchImageWithAsset:asset.asset synchronous:false handler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
130 | [self caculateImageDataWithData:imageData];
131 | }];
132 | }
133 | }
134 |
135 | {
136 | //配置其他的属性
137 | self.currentMediaAsset = asset;
138 | self.currentContainerVC = VC;
139 | self.navigationView.selectedButton.selected = self.currentMediaAsset.selected;
140 | self.toolView.selectedButtonClear.selected = self.currentMediaAsset.origion;
141 | self.navigationView.titleLabel.text = [NSString stringWithFormat:@"当前页面ID:%ld", index];
142 |
143 | }
144 | }
145 |
146 |
147 |
148 | #pragma mark - private method
149 | - (void)caculateSelected {
150 | NSUInteger restrictNumber = 0;
151 | for (WZMediaAsset *asset in self.mediaAssetArray) {
152 | if (asset.selected == true) {
153 | restrictNumber = restrictNumber + 1;
154 | }
155 | }
156 | self.toolView.restrictNumber(restrictNumber);
157 | }
158 |
159 | - (BOOL)overloadJudgement {
160 | if (self.restrictNumber == 0) {
161 | return false;
162 | }
163 |
164 | NSUInteger restrictNumber = 0;
165 | for (WZMediaAsset *asset in self.mediaAssetArray) {
166 | if (asset.selected == true) {
167 | restrictNumber = restrictNumber + 1;
168 | }
169 | }
170 |
171 | if (self.restrictNumber <= restrictNumber) {
172 | return true;
173 | }
174 |
175 | return false;
176 | }
177 |
178 | - (void)caculateImageDataWithImage:(UIImage *)image {
179 | if (!image) {
180 | return;
181 | }
182 | NSData *data = UIImagePNGRepresentation(image);
183 | [self caculateImageDataWithData:data];
184 | }
185 |
186 | - (void)caculateImageDataWithData:(NSData *)data {
187 | self.toolView.fetchClearInfo([NSString stringWithFormat:@"%.3lf M", data.length / 1000.0 / 1000.0]);
188 | }
189 |
190 | - (void)fetchOrigion {
191 | if (self.currentMediaAsset.origion) {
192 | [WZMediaFetcher fetchOrigionWith:self.currentMediaAsset.asset synchronous:true handler:^(UIImage *origion) {
193 | [self.currentContainerVC matchingPicture:origion];
194 | }];
195 | }
196 | }
197 |
198 | #pragma mark - Accessor
199 | - (WZAssetBrowseNavigationView *)navigationView {
200 | if (!_navigationView) {
201 | _navigationView = [WZAssetBrowseNavigationView customAssetBrowseNavigationWithDelegate:(id)self];
202 | }
203 | return _navigationView;
204 | }
205 |
206 | - (WZAssetBrowseToolView *)toolView {
207 | if (!_toolView) {
208 | _toolView = [WZAssetBrowseToolView customAssetBrowseToolWithDelegate:(id)self];
209 | }
210 | return _toolView;
211 | }
212 |
213 | @end
214 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZAssetBrowseController/WZAssetBrowseNavigationView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZAssetBrowseNavigationView.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol WZProtocolAssetBrowseNaviagtion
12 |
13 | - (void)backAction;//返回代理事件
14 | - (void)selectedAction;//选中代理事件
15 |
16 | @end
17 |
18 | @interface WZAssetBrowseNavigationView : UIView
19 |
20 | @property (nonatomic, weak) id delegate;
21 | @property (nonatomic, strong) UIButton *backButton;
22 | @property (nonatomic, strong) UIButton *selectedButton;
23 | @property (nonatomic, strong) UILabel *titleLabel;
24 |
25 | + (instancetype)customAssetBrowseNavigationWithDelegate:(id)delegate;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZAssetBrowseController/WZAssetBrowseNavigationView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZAssetBrowseNavigationView.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZAssetBrowseNavigationView.h"
10 |
11 | @implementation WZAssetBrowseNavigationView
12 |
13 | + (instancetype)customAssetBrowseNavigationWithDelegate:(id)delegate {
14 | WZAssetBrowseNavigationView *navigation = [[WZAssetBrowseNavigationView alloc] initWithFrame:CGRectMake(0.0, 0.0, [UIScreen mainScreen].bounds.size.width, 64.0)];
15 | navigation.delegate = delegate;
16 | navigation.backgroundColor = [UIColor colorWithRed:51.0 / 255 green:51.0 / 255 blue:51.0 / 255 alpha:0.4];
17 |
18 | CGFloat buttonHW = 44.0;
19 | navigation.backButton = [[UIButton alloc] initWithFrame:CGRectMake(5, 20.0, buttonHW, buttonHW)];
20 | navigation.selectedButton = [[UIButton alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - buttonHW, 20.0, buttonHW, buttonHW)];
21 | navigation.titleLabel.textAlignment = NSTextAlignmentCenter;
22 | navigation.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(buttonHW, 20.0, [UIScreen mainScreen].bounds.size.width - buttonHW * 2.0, buttonHW)];
23 | navigation.titleLabel.textAlignment = NSTextAlignmentCenter;
24 | navigation.titleLabel.textColor = [UIColor whiteColor];
25 |
26 | [navigation addSubview:navigation.titleLabel];
27 | [navigation addSubview:navigation.selectedButton];
28 | [navigation addSubview:navigation.backButton];
29 |
30 | [navigation.backButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
31 | [navigation.selectedButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
32 |
33 | [navigation.backButton setImage:[UIImage imageNamed:@"imagesBrowse_back"] forState:UIControlStateNormal];
34 | [navigation.selectedButton setImage:[UIImage imageNamed:@"message_oeuvre_btn_normal"] forState:UIControlStateNormal];
35 | [navigation.selectedButton setImage:[UIImage imageNamed:@"message_oeuvre_btn_selected"] forState:UIControlStateSelected];
36 |
37 | navigation.titleLabel.text = @"图片";
38 | [navigation.selectedButton addTarget:navigation action:@selector(clickedBtn:) forControlEvents:UIControlEventTouchUpInside];
39 | [navigation.backButton addTarget:navigation action:@selector(clickedBtn:) forControlEvents:UIControlEventTouchUpInside];
40 |
41 | return navigation;
42 | }
43 |
44 | - (void)clickedBtn:(UIButton *)sender {
45 | if (sender == self.backButton) {
46 | if ([_delegate respondsToSelector:@selector(backAction)]) {
47 | [_delegate backAction];
48 | }
49 | } else if (sender == self.selectedButton) {
50 | if ([_delegate respondsToSelector:@selector(selectedAction)]) {
51 | [_delegate selectedAction];
52 | }
53 | }
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZAssetBrowseController/WZAssetBrowseToolView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZAssetBrowseToolView.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol WZProtocolAssetBrowseTool
12 |
13 | - (void)selectedOrigionAction;//选择原尺寸图片的代理事件
14 | - (void)completeAction;//发送代理事件
15 |
16 | @end
17 |
18 | @interface WZAssetBrowseToolView : UIView
19 |
20 | @property (nonatomic, weak) id delegate;
21 | @property (nonatomic, strong) void (^fetchClearInfo)(NSString *info);
22 | @property (nonatomic, strong) void (^restrictNumber)(NSUInteger restrictNumber);
23 | @property (nonatomic, strong) UIButton *selectedButtonClear;
24 | @property (nonatomic, strong) UILabel *clearInfoLabel;
25 | @property (nonatomic, strong) UIButton *completeButton;
26 | @property (nonatomic, strong) UILabel *countLabel;
27 |
28 | + (instancetype)customAssetBrowseToolWithDelegate:(id)delegate;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZAssetBrowseController/WZAssetBrowseToolView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZAssetBrowseToolView.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZAssetBrowseToolView.h"
10 |
11 | @implementation WZAssetBrowseToolView
12 |
13 | + (instancetype)customAssetBrowseToolWithDelegate:(id)delegate {
14 | WZAssetBrowseToolView *tool = [[WZAssetBrowseToolView alloc] init];
15 | tool.delegate = delegate;
16 | CGFloat toolH = 49.0;
17 | tool.frame = CGRectMake(0.0, [UIScreen mainScreen].bounds.size.height - toolH, [UIScreen mainScreen].bounds.size.width, toolH);
18 | tool.backgroundColor = [UIColor colorWithRed:51.0 / 255 green:51.0 / 255 blue:51.0 / 255 alpha:0.4];
19 |
20 | tool.selectedButtonClear = [UIButton buttonWithType:UIButtonTypeCustom];
21 | CGFloat button_origionHW = 72 / 2.0;
22 | tool.selectedButtonClear.frame = CGRectMake(5.0, (toolH - button_origionHW)/2.0 , button_origionHW, button_origionHW);
23 |
24 | [tool.selectedButtonClear setImage:[UIImage imageNamed:@"asset_selectedOrigion_normal"] forState:UIControlStateNormal];
25 | [tool.selectedButtonClear setImage:[UIImage imageNamed:@"asset_selectedOrigion_selected"] forState:UIControlStateSelected];
26 |
27 | tool.clearInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(tool.selectedButtonClear.frame), 0.0, [UIScreen mainScreen].bounds.size.width / 2.0, toolH)];
28 | tool.clearInfoLabel.text = @"选择原图";
29 | tool.clearInfoLabel.textColor = [UIColor whiteColor];
30 |
31 | __weak typeof(tool) weakTool = tool;
32 | tool.fetchClearInfo = ^(NSString *info){
33 | weakTool.clearInfoLabel.text = [NSString stringWithFormat:@"选择原图(%@)", info];
34 | };
35 |
36 | tool.completeButton = [UIButton buttonWithType:UIButtonTypeCustom];
37 | CGFloat completeButtonHW = 45.0;
38 | tool.completeButton.frame = CGRectMake([UIScreen mainScreen].bounds.size.width - completeButtonHW - 15.0, (toolH - completeButtonHW)/2.0, completeButtonHW, completeButtonHW);
39 | [tool.completeButton setTitle:@"发送" forState:UIControlStateNormal];
40 | tool.completeButton.titleLabel.font = [UIFont systemFontOfSize:16.0];
41 | [tool.completeButton setTitleColor:[UIColor colorWithRed:254.0 / 255 green:191.0 / 255 blue:39.0 / 255 alpha:1.0] forState:UIControlStateNormal];
42 | [tool.completeButton setTitleColor:[UIColor colorWithRed:254.0 / 255 green:191.0 / 255 blue:39.0 / 255 alpha:1.0] forState:UIControlStateHighlighted];
43 | CGFloat label_HW = 20.0;
44 |
45 | tool.countLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMinX(tool.completeButton.frame) -label_HW, (toolH - label_HW)/2.0, label_HW, label_HW)];
46 | tool.countLabel.backgroundColor = [UIColor colorWithRed:254.0 / 255 green:191.0 / 255 blue:39.0 / 255 alpha:1.0];
47 | tool.countLabel.text = @"0";
48 | tool.restrictNumber = ^(NSUInteger restrictNumber){
49 | weakTool.countLabel.text = [NSString stringWithFormat:@"%ld", restrictNumber];
50 | };
51 | tool.countLabel.layer.cornerRadius = label_HW / 2.0;
52 | tool.countLabel.layer.masksToBounds = true;
53 | tool.countLabel.textAlignment = NSTextAlignmentCenter;
54 | tool.countLabel.textColor = [UIColor whiteColor];
55 |
56 | [tool addSubview:tool.selectedButtonClear];
57 | [tool addSubview:tool.completeButton];
58 | [tool addSubview:tool.clearInfoLabel];
59 | [tool addSubview:tool.countLabel];
60 |
61 | [tool.completeButton addTarget:tool action:@selector(clickedBtn:) forControlEvents:UIControlEventTouchUpInside];
62 | [tool.selectedButtonClear addTarget:tool action:@selector(clickedBtn:) forControlEvents:UIControlEventTouchUpInside];
63 | return tool;
64 | }
65 |
66 | - (void)clickedBtn:(UIButton *)sender {
67 | if (sender == self.selectedButtonClear) {
68 | if ([_delegate respondsToSelector:@selector(selectedOrigionAction)]) {
69 | [_delegate selectedOrigionAction];
70 | }
71 | } else if (sender == self.completeButton) {
72 | if ([_delegate respondsToSelector:@selector(completeAction)]) {
73 | [_delegate completeAction];
74 | }
75 | }
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZImageBrowseController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZImageBrowseController.h
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "WZImageContainerController.h"
11 | #import "UIImageView+WebCache.h"
12 |
13 | @protocol WZProtocolImageBrowse
14 |
15 | - (void)backAction;//返回代理事件
16 | - (void)send;//发送代理事件
17 |
18 | @end
19 |
20 | //图片浏览容器控制器
21 | @interface WZImageBrowseController : UIPageViewController
22 |
23 | @property (nonatomic, strong) id imagesBrowseDelegate;//代理
24 | @property (nonatomic, strong) NSArray *mediaAssetArray;//选中的mdeiaAsset集合
25 | @property (nonatomic, strong) NSArray *imageContainersReuseableArray;//图片容器(复用)
26 | @property (nonatomic, strong) WZImageContainerController *currentContainerVC;//当前的图片容器
27 | @property (nonatomic, assign) NSInteger currentIndex;//当前图片的角标
28 | @property (nonatomic, assign) NSInteger numberOfIndexs;//图片的角标极值
29 | @property (nonatomic, assign) NSUInteger restrictNumber;//限制选图数目 =0时无选图限制
30 | @property (nonatomic, strong) WZMediaAsset *currentMediaAsset;//当前集合
31 |
32 | - (void)showInIndex:(NSInteger)index animated:(BOOL)animated;//控制器定位
33 | - (void)matchThumnailImageWith:(WZImageContainerController *)VC;//控制器缩略图匹配
34 | - (void)matchClearImageWith:(WZImageContainerController *)VC;//控制器上清晰图匹配
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZImageBrowseController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZImageBrowseController.m
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZImageBrowseController.h"
10 |
11 | #pragma mark - WZImageBrowseController
12 | @interface WZImageBrowseController ()
18 |
19 | @end
20 |
21 | @implementation WZImageBrowseController
22 |
23 | #pragma mark - Initialize
24 | - (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(NSDictionary *)options {
25 | NSMutableDictionary *configOptions = [NSMutableDictionary dictionaryWithDictionary:options?:@{}];
26 | //页面间隔设置
27 | configOptions[UIPageViewControllerOptionInterPageSpacingKey] = @(10);
28 | if (self = [super initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:navigationOrientation options:configOptions]) {
29 | //自定义模态跳转模式
30 | // self.modalPresentationStyle = UIModalPresentationCustom;
31 | //模态过渡模式
32 | self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
33 | /*
34 | UIModalTransitionStyleCoverVertical:画面从下向上徐徐弹出,关闭时向下隐 藏(默认方式)。
35 | UIModalTransitionStyleFlipHorizontal:从前一个画面的后方,以水平旋转的方式显示后一画面。
36 | UIModalTransitionStyleCrossDissolve:前一画面逐渐消失的同时,后一画面逐渐显示。
37 | */
38 | //自定义跳转代理
39 | // self.transitioningDelegate = self;
40 |
41 | _currentIndex = 0;
42 | }
43 | return self;
44 | }
45 |
46 | #pragma mark - Lifecycle
47 | - (void)viewDidLoad {
48 | [super viewDidLoad];
49 | self.view.backgroundColor = [UIColor whiteColor];
50 | self.automaticallyAdjustsScrollViewInsets = false;
51 | self.dataSource = self;
52 | self.delegate = self;
53 | [self createViews];
54 |
55 | for (UIView *view in self.view.subviews) {
56 | if ([view isKindOfClass:[UIScrollView class]]) {
57 | UIScrollView *scroll = (UIScrollView *)view;
58 | // NSLog(@"___%@", scroll.delegate);//打印得知代理为null
59 | scroll.delegate = self;
60 | for (UIGestureRecognizer *gesture in scroll.gestureRecognizers) {
61 | if ([gesture isKindOfClass:[UIPanGestureRecognizer class]]) {
62 | ((UIPanGestureRecognizer *)gesture).maximumNumberOfTouches = 1; //不能双手pan 能够解决pageView中的一个BUG
63 | break;
64 | }
65 | }
66 | break;
67 | }
68 | }
69 | }
70 |
71 |
72 |
73 |
74 | - (void)createViews {
75 | }
76 |
77 | #pragma mark - WZProtocolImageBrowseNavigationView
78 | - (void)leftButtunAction {
79 | [self dismissViewControllerAnimated:true completion:^{}];
80 | }
81 | - (void)rightButtunAction {
82 | }
83 |
84 | #pragma mark - Match VC use index
85 | - (WZImageContainerController *)matchControllerIndexWithIndex:(NSInteger)index {
86 |
87 | if (index < 0
88 | || index > _numberOfIndexs) {
89 | return nil;
90 | }
91 |
92 | WZImageContainerController *VC = self.imageContainersReuseableArray[index % self.imageContainersReuseableArray.count];
93 | VC.index = index;
94 | [self matchThumnailImageWith:VC];
95 | return VC;
96 | }
97 |
98 | #pragma mark - Show VC in index
99 | - (void)showInIndex:(NSInteger)index animated:(BOOL)animated {
100 |
101 | if (index <= 0) {index = 0;}
102 | if (index > _numberOfIndexs) {index = _numberOfIndexs;}
103 | _currentIndex = index;
104 |
105 | WZImageContainerController *VC = [self matchControllerIndexWithIndex:_currentIndex];
106 | [self matchClearImageWith:VC];
107 | [self setViewControllers:@[VC] direction:UIPageViewControllerNavigationDirectionForward animated:animated completion:^(BOOL finished) {}];
108 | self.currentContainerVC = VC;
109 | }
110 |
111 |
112 | #pragma mark - Match image
113 | - (void)matchThumnailImageWith:(WZImageContainerController *)VC {
114 | if (!VC) {
115 | return;
116 | }
117 | NSUInteger index = VC.index;
118 | if (index >= _mediaAssetArray.count) {
119 | return;
120 | }
121 | }
122 |
123 | - (void)matchClearImageWith:(WZImageContainerController *)VC {
124 | if (!VC) {
125 | return;
126 | }
127 | NSUInteger index = VC.index;
128 | if (index >= _mediaAssetArray.count) {
129 | return;
130 | }
131 | }
132 |
133 | #pragma mark - WZProtocolImageScrollView
134 | - (void)singleTap:(UIGestureRecognizer *)gesture {
135 | //单击
136 | }
137 |
138 | - (void)doubleTap:(UIGestureRecognizer *)gesture {
139 | //变焦动画
140 | [self.currentContainerVC focusingWithGesture:gesture];
141 | }
142 |
143 | - (void)longPress:(UIGestureRecognizer *)gesture {
144 | //保存图片
145 |
146 | }
147 |
148 | #pragma mark - WZProtocolImageContainer
149 |
150 | #pragma mark - UIPageViewControllerDelegate
151 | - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
152 | WZImageContainerController *VC = pageViewController.viewControllers.firstObject;
153 | if (self.currentContainerVC != VC) {
154 | [self matchClearImageWith:VC];
155 | }
156 | }
157 |
158 | #pragma mark - UIPageViewControllerDataSource
159 | - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(WZImageContainerController *)viewController {
160 | return [self matchControllerIndexWithIndex:viewController.index - 1];
161 | }
162 |
163 | - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(WZImageContainerController *)viewController {
164 | return [self matchControllerIndexWithIndex:viewController.index + 1];
165 | }
166 |
167 | #pragma mark - UIViewControllerTransitioningDelegate
168 | - (nullable id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
169 | return nil;
170 | }
171 |
172 | - (nullable id )animationControllerForDismissedController:(UIViewController *)dismissed {
173 | return nil;
174 | }
175 |
176 | #pragma mark - Accessor
177 | - (NSArray *)imageContainersReuseableArray {
178 | if (!_imageContainersReuseableArray) {
179 | NSMutableArray *tmpMArr = [NSMutableArray array];
180 | NSUInteger reuseCount = 5;//重用控制器数目
181 | for (NSUInteger i = 0; i < reuseCount; i++) {
182 | WZImageContainerController *VC = [[WZImageContainerController alloc] init];
183 | VC.index = i;
184 | VC.delegate = (id)self;
185 | VC.mainVC = self;
186 | [tmpMArr addObject:VC];
187 | }
188 | _imageContainersReuseableArray = [NSArray arrayWithArray:tmpMArr];
189 | }
190 | return _imageContainersReuseableArray;
191 | }
192 |
193 | - (void)setMediaAssetArray:(NSArray *)mediaAssetArray {
194 | if ([mediaAssetArray isKindOfClass:[NSArray class]]) {
195 | _mediaAssetArray = mediaAssetArray;
196 | _numberOfIndexs = _mediaAssetArray.count - 1;
197 | if (_numberOfIndexs < 0) {
198 | _numberOfIndexs = 0;
199 | }
200 | }
201 | }
202 |
203 | @end
204 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZImageContainerController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZImageContainerController.h
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/5/24.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "WZImageScrollView.h"
11 | #import "WZRoundRenderLayer.h"
12 |
13 | @interface WZRemoteImgaeProgressView : UIView
14 |
15 | @property (nonatomic, strong) WZRoundRenderLayer *downloadProgressLayer;//layer进度条
16 |
17 | /**
18 | * 自定义进度条
19 | *
20 | * @return 自定义进度条
21 | */
22 | + (instancetype)customProgress;
23 |
24 | /**
25 | * 进度比例
26 | *
27 | * @param rate 0 <= rate <= 1
28 | */
29 | - (void)setProgressRate:(float)rate;
30 |
31 | @end
32 |
33 | @class WZImageContainerController;
34 | @protocol WZProtocolImageContainer
35 |
36 | @end
37 |
38 | /**
39 | * 图片容器控制器
40 | */
41 | @interface WZImageContainerController : UIViewController
42 |
43 | @property (nonatomic, weak) UIViewController *mainVC;//手势代理对象
44 | @property (nonatomic, weak) id delegate;//
45 | @property (nonatomic, assign) NSInteger index;//当前图片角标
46 |
47 | //进度显示(for remote)
48 | @property (nonatomic, strong) WZRemoteImgaeProgressView *progress;
49 |
50 | /**
51 | * 匹配图片接口
52 | *
53 | * @param image 需要匹配的图片
54 | */
55 | - (void)matchingPicture:(UIImage *)image;
56 |
57 | /**
58 | * 匹配经过缩放的图片接口
59 | *
60 | * @param gesture 缩放手势
61 | */
62 | - (void)focusingWithGesture:(UIGestureRecognizer *)gesture;
63 | @end
64 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZImageContainerController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZImageContainerController.m
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/5/24.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZImageContainerController.h"
10 |
11 | @implementation WZRemoteImgaeProgressView
12 |
13 | #pragma mark - Initialize
14 | + (instancetype)customProgress {
15 |
16 | //进度的图的设置
17 | WZRemoteImgaeProgressView *progress = [[WZRemoteImgaeProgressView alloc] init];
18 | CGFloat viewHW = 50;
19 | progress.downloadProgressLayer = [[WZRoundRenderLayer alloc] initWithCircleRadius:viewHW / 2.0 layerLineWidth:5];
20 | progress.frame = CGRectMake(0.0, 0.0, viewHW, viewHW);
21 | [progress.layer addSublayer:progress.downloadProgressLayer];
22 | return progress;
23 | }
24 |
25 | #pragma mark - Public
26 | - (void)setProgressRate:(float)rate {
27 | if (rate > 1) {rate = 1.0;};
28 | if (self.downloadProgressLayer) {
29 | self.downloadProgressLayer.renderAngle = (M_PI * 2.0) * rate;
30 | }
31 |
32 | }
33 |
34 | #pragma mark - Override
35 | - (void)setFrame:(CGRect)frame {
36 | [super setFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width - frame.size.width) / 2.0, ([UIScreen mainScreen].bounds.size.height - frame.size.height) / 2.0, frame.size.width, frame.size.height)];
37 | }
38 |
39 | @end
40 |
41 | @interface WZImageContainerController()
42 |
43 | @property (nonatomic, strong) WZImageScrollView *scrollPictureView;
44 |
45 | @end
46 |
47 | @implementation WZImageContainerController
48 |
49 | - (instancetype)init
50 | {
51 | self = [super init];
52 | if (self) {
53 | _scrollPictureView = [[WZImageScrollView alloc] init];
54 | [self.view addSubview:_scrollPictureView];
55 | [self.view addSubview:self.progress];
56 | }
57 | return self;
58 | }
59 |
60 | - (void)setMainVC:(UIViewController *)mainVC {
61 | if ([mainVC isKindOfClass:[UIViewController class]]) {
62 | _mainVC = mainVC;
63 | _scrollPictureView.imageScrollDelegate = (id)_mainVC;
64 | }
65 | }
66 |
67 | #pragma mark - Life cycle
68 | - (void)viewDidLoad {
69 | [super viewDidLoad];
70 | }
71 |
72 | - (void)viewWillAppear:(BOOL)animated {
73 | [super viewWillAppear:animated];
74 | }
75 |
76 | #pragma mark - Public
77 | - (void)matchingPicture:(UIImage *)image {
78 | [_scrollPictureView matchingPicture:image];
79 | }
80 | - (void)focusingWithGesture:(UIGestureRecognizer *)gesture {
81 | [_scrollPictureView matchZoomWithGesture:gesture];
82 | }
83 |
84 |
85 | #pragma mark - Accessor
86 | - (WZRemoteImgaeProgressView *)progress {
87 | if (!_progress) {
88 | _progress = [WZRemoteImgaeProgressView customProgress];
89 | _progress.hidden = true;
90 | }
91 | return _progress;
92 | }
93 | @end
94 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZImageScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZImageScrollView.h
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/5/22.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "WZMediaFetcher.h"
11 |
12 | @protocol WZProtocolImageScrollView
13 |
14 | - (void)singleTap:(UIGestureRecognizer *)gesture;
15 | - (void)doubleTap:(UIGestureRecognizer *)gesture;
16 | - (void)longPress:(UIGestureRecognizer *)gesture;
17 |
18 | @end
19 |
20 | @interface WZImageScrollView : UIScrollView
21 |
22 | @property (nonatomic, weak) id imageScrollDelegate;
23 | @property (nonatomic, strong) UITapGestureRecognizer *singleTap;
24 | @property (nonatomic, strong) UITapGestureRecognizer *doubleTap;
25 | @property (nonatomic, strong) UILongPressGestureRecognizer *longPress;
26 |
27 | /**
28 | * 匹配图片接口
29 | *
30 | * @param image 需要匹配的图片
31 | */
32 | - (void)matchingPicture:(UIImage *)image;
33 |
34 | /**
35 | * 匹配经过缩放的图片接口
36 | *
37 | * @param gesture 缩放手势
38 | */
39 | - (void)matchZoomWithGesture:(UIGestureRecognizer *)gesture;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZImageScrollView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZImageScrollView.m
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/5/22.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZImageScrollView.h"
10 |
11 | #define WZ_MAX_ZOOMSCALE 3.0 //最大缩放比例
12 | @interface WZImageScrollView ()
13 |
14 | @property (nonatomic, strong) UIImageView *pictureImageView;
15 |
16 | @end
17 |
18 | @implementation WZImageScrollView
19 |
20 | #pragma mark - Life Cycle
21 | - (instancetype)init
22 | {
23 | self = [super init];
24 | if (self) {
25 | self.frame = CGRectZero;
26 | self.frame = [UIScreen mainScreen].bounds;
27 | self.multipleTouchEnabled = true;
28 | self.showsVerticalScrollIndicator = false;
29 | self.showsHorizontalScrollIndicator = false;
30 | self.alwaysBounceVertical = true;
31 | self.minimumZoomScale = 1.0;
32 | self.maximumZoomScale = 1.0;
33 | self.delegate = self;
34 |
35 | _pictureImageView = [[UIImageView alloc] init];
36 | _pictureImageView.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5];
37 | _pictureImageView.frame = self.bounds;
38 | _pictureImageView.clipsToBounds = true;
39 | _pictureImageView.contentMode = UIViewContentModeScaleAspectFill;
40 | [self addSubview:_pictureImageView];
41 |
42 | _singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gesture:)];
43 | _doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gesture:)];
44 | _doubleTap.numberOfTapsRequired = 2;
45 | [_singleTap requireGestureRecognizerToFail:_doubleTap];
46 | _longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(gesture:)];
47 | [self addGestureRecognizer:_singleTap];
48 | [self addGestureRecognizer:_doubleTap];
49 | [self addGestureRecognizer:_longPress];
50 | }
51 | return self;
52 | }
53 |
54 | #pragma mark - public
55 | - (void)matchingPicture:(UIImage *)image {
56 | if ([image isKindOfClass:[UIImage class]]) {
57 | _pictureImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
58 |
59 | if (_pictureImageView.image) {
60 | [self standardConfig];
61 | }
62 | } else {
63 | _pictureImageView.image = nil;
64 | }
65 | }
66 |
67 | - (void)matchZoomWithGesture:(UIGestureRecognizer *)gesture {
68 | if ([gesture isKindOfClass:[UITapGestureRecognizer class]]) {
69 | CGPoint point = [gesture locationInView:self];
70 | [self matchZoomWithPoint:point];
71 | }
72 | }
73 |
74 | #pragma mark - Common
75 | - (void)gesture:(UIGestureRecognizer *)sender {
76 | if (sender == _singleTap) {
77 | if ([_imageScrollDelegate respondsToSelector:@selector(singleTap:)]) {
78 | [_imageScrollDelegate singleTap:sender];
79 | }
80 | } else if (sender == _doubleTap) {
81 | if ([_imageScrollDelegate respondsToSelector:@selector(doubleTap:)]) {
82 | [_imageScrollDelegate doubleTap:sender];
83 | }
84 | } else if (sender == _longPress) {
85 | if (sender.state == UIGestureRecognizerStateBegan) {
86 | if ([_imageScrollDelegate respondsToSelector:@selector(longPress:)]) {
87 | [_imageScrollDelegate longPress:sender];
88 | }
89 | }
90 | }
91 | }
92 |
93 | - (void)setFrame:(CGRect)frame {
94 | [super setFrame:[UIScreen mainScreen].bounds];
95 | }
96 |
97 | - (void)matchZoomWithPoint:(CGPoint)point {
98 | CGPoint touchPoint = [self convertPoint:point toView:_pictureImageView];
99 | if (self.zoomScale > 1) {
100 | //比例复原
101 | [self setZoomScale:1 animated:true];
102 | } else if (self.maximumZoomScale > 1) {
103 | //
104 | CGFloat currentZoomScale = self.maximumZoomScale;
105 | CGFloat horizontalSize = CGRectGetWidth(self.bounds) / currentZoomScale;
106 | CGFloat verticalSize = CGRectGetHeight(self.bounds) / currentZoomScale;
107 | //设置浏览窗口位置
108 | CGRect rect = CGRectMake(touchPoint.x - horizontalSize / 2.0, touchPoint.y - verticalSize / 2.0, horizontalSize, verticalSize);
109 | [self zoomToRect:rect animated:true];
110 | }
111 | }
112 |
113 | - (void)matchImageViewSize {
114 | //更新imageView位置
115 | if (_pictureImageView.image) {
116 | CGFloat ratio = CGRectGetWidth(self.bounds) / _pictureImageView.image.size.width;
117 | //固定了imageView的宽度 高度随比例
118 | _pictureImageView.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.bounds), ceil(ratio * _pictureImageView.image.size.height));
119 | //配置contentSize
120 | self.contentSize = _pictureImageView.frame.size;
121 | }
122 | }
123 |
124 | //配置imageView 的中心位置: 初始化、变焦前后分别调用
125 | - (void)matchImageViewCenter {
126 | CGFloat contentWidth = self.contentSize.width;
127 | CGFloat horizontalDiff = CGRectGetWidth(self.bounds) - contentWidth;//水平方向偏差 总是0
128 | CGFloat horizontalAddition = horizontalDiff > 0.0 ? horizontalDiff : 0.0;//设置偏差量
129 |
130 | CGFloat contentHeight = self.contentSize.height;
131 | CGFloat verticalDiff = CGRectGetHeight(self.bounds) - contentHeight;//垂直方向偏差
132 |
133 | //设置偏差量 当图片的高宽比大于屏幕的高宽比时,imageView的Y轴为0
134 | CGFloat verticalAdditon = verticalDiff > 0.0 ? verticalDiff : 0.0;
135 | //校正图片中心
136 | _pictureImageView.center = CGPointMake((contentWidth + horizontalAddition) / 2.0, (contentHeight + verticalAdditon) / 2.0);
137 | }
138 |
139 | - (void)matchZoomScale {
140 | //恢复处理
141 | self.maximumZoomScale = 1.0;
142 | [self setZoomScale:1 animated:true];
143 |
144 | CGSize imageSize = _pictureImageView.image.size;
145 |
146 | CGFloat restrictW = CGRectGetWidth(self.bounds);
147 | CGFloat restrictH = CGRectGetHeight(self.bounds);
148 |
149 | // if (imageSize.width <= restrictW && imageSize.height <= restrictH) {
150 | // //不作放大
151 | // self.maximumZoomScale = 1.0;
152 | // } else {
153 | // //比例为3倍
154 | self.maximumZoomScale = MAX(MIN(imageSize.width / restrictW, imageSize.height / restrictH), WZ_MAX_ZOOMSCALE);
155 | // }
156 |
157 | }
158 |
159 | //适配屏幕旋转
160 | - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
161 | [super traitCollectionDidChange:previousTraitCollection];
162 | if (_pictureImageView.image) {
163 | [self standardConfig];
164 | }
165 | }
166 |
167 | - (void)standardConfig {
168 | [self matchZoomScale];
169 | [self matchImageViewSize];
170 | [self matchImageViewCenter];
171 | }
172 |
173 | #pragma mark - UIScrollViewDelegate
174 |
175 | //产生了变焦 镜头发生变化的时候 contentSize 也会发生改变 要同步imageView的位置
176 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(3_2) {
177 | [self matchImageViewCenter];
178 | }
179 |
180 | //设置变焦View
181 | - (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
182 | return _pictureImageView;
183 | }
184 |
185 |
186 | @end
187 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZRemoteImagesBrowseController/WZRemoteImageBrowseController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZRemoteImageBrowseController.h
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZAssetBrowseController.h"
10 | #import "WZRemoteImageNavigationView.h"
11 |
12 | @interface WZRemoteImageBrowseController : WZAssetBrowseController
13 |
14 | @property (nonatomic, strong) UIImageView *mediumImageView;
15 |
16 | + (void)showRemoteImagesWithURLArray:(NSArray *)urlArray loactedVC:(UIViewController *)locatedVC;
17 |
18 | + (NSArray *)fetchUrlArrayAccordingStringArray:(NSArray *)stringArray;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZRemoteImagesBrowseController/WZRemoteImageBrowseController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZRemoteImageBrowseController.m
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZRemoteImageBrowseController.h"
10 | #import "WZToast.h"
11 |
12 | @interface WZRemoteImageBrowseController ()
13 |
14 | @property (nonatomic, strong) WZRemoteImageNavigationView *navigationView;
15 |
16 | @end
17 |
18 | @implementation WZRemoteImageBrowseController
19 |
20 | //会过滤部分字符串
21 | + (NSArray *)fetchUrlArrayAccordingStringArray:(NSArray *)stringArray {
22 | NSMutableArray *urlMArray = [NSMutableArray array];
23 | for (NSString *urlStr in stringArray) {
24 | if ([urlStr isKindOfClass:[NSString class]] && urlStr.length) {
25 | NSURL *url = [NSURL URLWithString:urlStr];
26 | if ([url isKindOfClass:[NSURL class]]) {
27 | [urlMArray addObject:url];
28 | }
29 | }
30 | }
31 | return urlMArray;
32 | }
33 |
34 | #pragma mark - Initialize
35 | + (void)showRemoteImagesWithURLArray:(NSArray *)urlArray loactedVC:(UIViewController *)locatedVC {
36 | if (!urlArray
37 | || !locatedVC
38 | || ![urlArray isKindOfClass:[NSArray class]]
39 | || ![locatedVC isKindOfClass:[UIViewController class]]) {
40 | return;
41 | }
42 |
43 | NSMutableArray *imagesMArray = [NSMutableArray array];
44 |
45 | SDWebImageDownloader *sdDownloader = [SDWebImageDownloader sharedDownloader];
46 | [sdDownloader setValue:@"" forHTTPHeaderField:@"Accept-Encoding"];
47 |
48 | for (int i = 0; i < urlArray.count; i++) {
49 | WZMediaAsset *asset = [[WZMediaAsset alloc] init];
50 | asset.remoteMediaURL = urlArray[i];
51 | asset.imageThumbnail = [UIImage imageWithColor:[[UIColor blackColor] colorWithAlphaComponent:0.5]];
52 | [imagesMArray addObject:asset];
53 |
54 | //使用了url缓存
55 | NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:asset.remoteMediaURL];
56 | if (key) {
57 | UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
58 | if (cacheImage) {
59 | asset.imageClear = cacheImage;
60 | asset.imageThumbnail = cacheImage;
61 | }
62 | NSLog(@"远程图片缓存Path:%@", [[SDImageCache sharedImageCache] defaultCachePathForKey:key]);
63 | NSData *data = [NSData dataWithContentsOfFile:[[SDImageCache sharedImageCache] defaultCachePathForKey:key]];
64 | NSLog(@"文件大小:%ld", data.length);
65 | }
66 | }
67 |
68 | if (imagesMArray.count) {
69 | WZRemoteImageBrowseController *VC = [[WZRemoteImageBrowseController alloc] init];
70 | VC.imagesBrowseDelegate = (id)locatedVC;
71 | VC.mediaAssetArray = imagesMArray;
72 |
73 | VC.restrictNumber = 9;//控制选中图片的数目
74 | [VC showInIndex:0 animated:true];
75 | [locatedVC presentViewController:VC animated:true completion:^{}];
76 | }
77 | }
78 |
79 | #pragma mark - Lifecycle
80 | - (void)viewDidLoad {
81 | [super viewDidLoad];
82 | self.view.backgroundColor = [UIColor blackColor];
83 | }
84 |
85 | - (void)createViews {
86 | [self.view addSubview:self.navigationView];
87 | [self caculateSelected];
88 | }
89 |
90 | #pragma mark - Match image
91 | - (void)matchThumnailImageWith:(WZImageContainerController *)VC {
92 | if (!VC) {
93 | return;
94 | }
95 | NSUInteger index = VC.index;
96 | if (index >= self.mediaAssetArray.count) {
97 | return;
98 | }
99 |
100 | VC.progress.hidden = true;//隐藏加载视图
101 | if (index < self.mediaAssetArray.count) {
102 | WZMediaAsset *asset = self.mediaAssetArray[index];
103 | NSAssert(asset.imageThumbnail, @"请配置默认图!");
104 | if (asset.imageThumbnail) {
105 | [VC matchingPicture:asset.imageThumbnail];
106 | }
107 | }
108 | }
109 |
110 | - (void)matchClearImageWith:(WZImageContainerController *)VC {
111 | if (!VC) {
112 | return;
113 | }
114 | NSUInteger index = VC.index;
115 | if (index >= self.mediaAssetArray.count) {
116 | return;
117 | }
118 | VC.progress.hidden = true;
119 | WZMediaAsset *asset = nil;
120 | if (index < self.mediaAssetArray.count ) {
121 | asset = self.mediaAssetArray[index];
122 | NSAssert(asset.remoteMediaURL, @"却少媒体URL!");
123 |
124 | if (asset.clearPath) {
125 | UIImage *image = [UIImage imageWithContentsOfFile:asset.clearPath];
126 | if (image) {
127 | [VC matchingPicture:image];
128 | return;
129 | }
130 | }
131 | if (asset.imageClear) {
132 | [VC matchingPicture:asset.imageClear];
133 | } else if (asset.remoteMediaURL) {
134 |
135 | [self.mediumImageView sd_cancelCurrentImageLoad];
136 | //复位状态
137 | [VC.progress setProgressRate:0];
138 | VC.progress.hidden = false;
139 | if ([asset.remoteMediaURL isKindOfClass:[NSURL class]]) {
140 |
141 | [self.mediumImageView sd_setImageWithPreviousCachedImageWithURL:asset.remoteMediaURL andPlaceholderImage:nil options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
142 | /*
143 | 这个因为NSHTTPURLResponse中
144 | Accept-Encoding为gzip造成的
145 | 当遇到Accept-Encoding为gzip时,expectedsize会变为-1不确定的大小
146 | 此时在sdwebimage中expectedsize判断小于0,就会赋值为0
147 | 所以如果确定文件的大小时,可以将Accept-Encoding修改成非gzip的就可以获取需要的文件大小了
148 | */
149 | if (expectedSize > 0) {
150 | [VC.progress setProgressRate:receivedSize / (expectedSize * 1.0)];
151 | }
152 | } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
153 | VC.progress.hidden = true;
154 | if (error) {
155 | //显示下载失败的图片
156 | [WZToast toastWithContent:[NSString stringWithFormat:@"图片下载失败:页面id为 %ld", VC.index]];
157 | } else {
158 | if (image) {
159 | asset.imageThumbnail = image;
160 | asset.imageClear = image;
161 | [VC matchingPicture:image];
162 | }
163 | }
164 | }];
165 | } else {
166 | [WZToast toastWithContent:@"图片url错误"];
167 | }
168 | } else {
169 | [WZToast toastWithContent:@"匹配不到图片资源"];
170 | }
171 | }
172 |
173 | self.currentMediaAsset = asset;
174 | self.currentContainerVC = VC;
175 | self.navigationView.titleLabel.text = [NSString stringWithFormat:@"当前页面ID:%ld", index];
176 | }
177 |
178 | /*
179 | HTTP Header中
180 | Accept-Encoding 是浏览器发给服务器,声明浏览器支持的编码类型的
181 | 常见的有
182 | Accept-Encoding: compress, gzip //支持compress 和gzip类型
183 | Accept-Encoding: //默认是identity
184 | Accept-Encoding: * //支持所有类型
185 | Accept-Encoding: compress;q=0.5, gzip;q=1.0 //按顺序支持 gzip , compress
186 | Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0 // 按顺序支持 gzip , identity
187 |
188 | 服务器返回的对应的类型编码header是 content-encoding
189 | 服务器处理accept-encoding的规则如下所示
190 | 1. 如果服务器可以返回定义在Accept-Encoding 中的任何一种Encoding类型, 那么处理成功(除非q的值等于0, 等于0代表不可接受)
191 | 2. * 代表任意一种Encoding类型 (除了在Accept-Encoding中显示定义的类型)
192 | 3.如果有多个Encoding同时匹配, 按照q值顺序排列
193 | 4. identity总是可被接受的encoding类型(除非显示的标记这个类型q=0) , 如果Accept-Encoding的值是空 那么只有identity是会被接受的类型
194 | 如果Accept-Encoding中的所有类型服务器都没发返回, 那么应该返回406错误给客户端
195 | 如果request中没有Accept-Encoding 那么服务器会假设所有的Encoding都是可以被接受的,
196 | 如果Accept-Encoding中有identity 那么应该优先返回identity (除非有q值的定义,或者你认为另外一种类型是更有意义的)
197 | 注意:
198 | 如果服务器不支持identity 并且浏览器没有发送Accept-Encoding,那么服务器应该倾向于使用HTTP1.0中的 "gzip" and "compress" , 服务器可能按照客户端类型 发送更适合的encoding类型
199 | 大部分HTTP1.0的客户端无法处理q值
200 | */
201 |
202 | #pragma mark - Accessor
203 | - (UIImageView *)mediumImageView {
204 | if (!_mediumImageView) {
205 | _mediumImageView = [[UIImageView alloc] init];
206 | }
207 | return _mediumImageView;
208 | }
209 |
210 | - (WZRemoteImageNavigationView *)navigationView {
211 | if (!_navigationView) {
212 | _navigationView = [WZRemoteImageNavigationView customAssetBrowseNavigationWithDelegate:(id)self];
213 | }
214 | return _navigationView;
215 | }
216 | @end
217 |
218 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZRemoteImagesBrowseController/WZRemoteImageNavigationView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZRemoteImageNavigationView.h
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZAssetBrowseNavigationView.h"
10 |
11 | @interface WZRemoteImageNavigationView : WZAssetBrowseNavigationView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZRemoteImagesBrowseController/WZRemoteImageNavigationView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZRemoteImageNavigationView.m
3 | // WZPhotoPicker
4 | //
5 | // Created by admin on 17/6/9.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZRemoteImageNavigationView.h"
10 |
11 | @implementation WZRemoteImageNavigationView
12 |
13 | + (instancetype)customAssetBrowseNavigationWithDelegate:(id)delegate {
14 | WZRemoteImageNavigationView *navigation = [super customAssetBrowseNavigationWithDelegate:delegate];
15 | navigation.selectedButton.hidden = true;
16 | return navigation;
17 | }
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZRoundRenderLayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZRoundRenderLayer.h
3 | // WZBaseRoundSelector
4 | //
5 | // Created by admin on 17/3/28.
6 | // Copyright © 2017年 WZ. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @protocol WZRoundRenderLayerDelegate
13 |
14 | /**
15 | *
16 | * @param currentPoint : bezier path current point
17 | */
18 | - (void)renderPathCurrentPoint:(CGPoint)currentPoint;
19 |
20 | @end
21 |
22 |
23 | /**
24 | * 始终在-PI / 2.0 处绘制 只负责绘制
25 | */
26 | @interface WZRoundRenderLayer : CALayer
27 |
28 | /**
29 | * 设置进行绘制弧
30 | */
31 | @property (nonatomic, assign) float renderAngle;//范围 0 ~ M_PI * 2.0
32 |
33 | @property (nonatomic, weak) id renderLayerDelegate;
34 |
35 | - (instancetype)initWithCircleRadius:(CGFloat)circleRadius layerLineWidth:(CGFloat)layerLineWidth;
36 |
37 | /**
38 | * 渲染表层的颜色
39 | */
40 | - (void)setSurfaceTrackColor:(UIColor *)color;
41 |
42 | /**
43 | * 渲染底层的颜色
44 | */
45 | - (void)setBottomTrackColor:(UIColor *)color;
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoBrowser/WZRoundRenderLayer.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZRoundRenderLayer.m
3 | // WZBaseRoundSelector
4 | //
5 | // Created by admin on 17/3/28.
6 | // Copyright © 2017年 WZ. All rights reserved.
7 | //
8 |
9 | #import "WZRoundRenderLayer.h"
10 |
11 | @interface WZRoundRenderLayer ()
12 |
13 | @property (nonatomic, strong) CAShapeLayer *surfaceLayer;
14 | @property (nonatomic, strong) CAShapeLayer *bottomLayer;
15 | @property (nonatomic, strong) CAShapeLayer *maskLayer;
16 | @property (nonatomic, strong) UIBezierPath *renderBezierPath;
17 |
18 | @property (nonatomic, assign) CGFloat circleRadius;
19 | @property (nonatomic, assign) CGFloat layerLineWidth;
20 |
21 | @end
22 |
23 |
24 | @implementation WZRoundRenderLayer
25 |
26 | #pragma mark - Initalize
27 | - (instancetype)initWithCircleRadius:(CGFloat)circleRadius layerLineWidth:(CGFloat)layerLineWidth {
28 | if (self = [super init]) {
29 | _circleRadius = circleRadius;
30 | _layerLineWidth = layerLineWidth;
31 | self.frame = CGRectZero;
32 |
33 | UIBezierPath *tmpBezierPath = [UIBezierPath bezierPath];
34 | CGFloat circleWH = _circleRadius - _layerLineWidth / 2.0;
35 | [tmpBezierPath addArcWithCenter:CGPointMake(_circleRadius, _circleRadius)
36 | radius:circleWH
37 | startAngle:-M_PI_2
38 | endAngle:M_PI_2 * 3.0
39 | clockwise:true];
40 |
41 | self.bottomLayer.path = tmpBezierPath.CGPath;
42 | self.surfaceLayer.path = tmpBezierPath.CGPath;
43 | self.surfaceLayer.mask = self.maskLayer;
44 | [self addSublayer:self.bottomLayer];
45 | [self addSublayer:self.surfaceLayer];
46 |
47 | }
48 | return self;
49 | }
50 |
51 | //frame 的size 由 _circleRadius 决定
52 | - (void)setFrame:(CGRect)frame {
53 | [super setFrame:CGRectMake(frame.origin.x, frame.origin.y, _circleRadius * 2.0, _circleRadius * 2.0)];
54 | }
55 |
56 |
57 | - (void)setSurfaceTrackColor:(UIColor *)color {
58 | if ([color isKindOfClass:[UIColor class]]) {
59 | self.surfaceLayer.strokeColor = color.CGColor;
60 | }
61 | }
62 |
63 | - (void)setBottomTrackColor:(UIColor *)color {
64 | if ([color isKindOfClass:[UIColor class]]) {
65 | self.bottomLayer.strokeColor = color.CGColor;
66 | }
67 | }
68 |
69 | #pragma mark - setter & getter
70 |
71 | - (CAShapeLayer *)surfaceLayer {
72 | if (!_surfaceLayer) {
73 | _surfaceLayer = [CAShapeLayer layer];
74 | _surfaceLayer.strokeColor = [UIColor colorWithRed:255.0 / 255.0 green:197.0 / 255.0 blue:41.0 / 255.0 alpha:1.0].CGColor;
75 | _surfaceLayer.fillColor = [UIColor clearColor].CGColor;
76 | _surfaceLayer.lineWidth = _layerLineWidth;
77 | _surfaceLayer.lineCap = @"round";
78 | }
79 | return _surfaceLayer;
80 | }
81 |
82 |
83 | - (CAShapeLayer *)bottomLayer {
84 | if (!_bottomLayer) {
85 | _bottomLayer = [CAShapeLayer layer];
86 | _bottomLayer.strokeColor = [UIColor colorWithRed:255.0 / 255.0 green:248.0 / 255.0 blue:234.0 / 255.0 alpha:1.0].CGColor;
87 | _bottomLayer.fillColor = [UIColor clearColor].CGColor;
88 | _bottomLayer.lineWidth = _layerLineWidth;
89 | _bottomLayer.lineCap = @"round";
90 | }
91 | return _bottomLayer;
92 | }
93 |
94 |
95 | - (CAShapeLayer *)maskLayer {
96 | if (!_maskLayer) {
97 | _maskLayer = [CAShapeLayer layer];
98 | _maskLayer.strokeColor = [UIColor whiteColor].CGColor;
99 | _maskLayer.fillColor = [UIColor clearColor].CGColor;
100 | _maskLayer.lineWidth = _layerLineWidth;
101 | _maskLayer.lineCap = @"round";
102 | }
103 | return _maskLayer;
104 | }
105 |
106 |
107 | - (UIBezierPath *)renderBezierPath {
108 | if (!_renderBezierPath) {
109 | _renderBezierPath = [UIBezierPath bezierPath];
110 | }
111 | return _renderBezierPath;
112 | }
113 |
114 | - (void)setRenderAngle:(float)renderAngle {
115 | if (renderAngle < 0) {
116 | renderAngle = 0;
117 | }
118 | if (renderAngle > M_PI * 2.0) {
119 | renderAngle = M_PI * 2.0;
120 | }
121 | renderAngle = renderAngle - M_PI_2;
122 | _renderAngle = renderAngle;
123 |
124 | CGFloat circleWH = _circleRadius - _layerLineWidth / 2.0;
125 | [self.renderBezierPath removeAllPoints];
126 | [_renderBezierPath addArcWithCenter:CGPointMake(_circleRadius, _circleRadius)
127 | radius:circleWH
128 | startAngle:- M_PI_2
129 | endAngle:_renderAngle
130 | clockwise:1];
131 | self.maskLayer.path = _renderBezierPath.CGPath;
132 | if ([self.renderLayerDelegate respondsToSelector:@selector(renderPathCurrentPoint:)]) {
133 | [self.renderLayerDelegate renderPathCurrentPoint:_renderBezierPath.currentPoint];
134 | }
135 | }
136 |
137 |
138 | @end
139 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoPicker/WZMediaAssetBaseCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZMediaAssetBaseCell.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/21.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | @class WZMediaFetcher;
11 | @class WZMediaAsset;
12 |
13 | @interface WZMediaAssetBaseCell : UICollectionViewCell
14 |
15 | @property (nonatomic, strong) UIImageView *imageView;
16 | @property (nonatomic, strong) UIButton *selectButton;
17 | @property (nonatomic, strong) void (^selectedBlock)(BOOL selected);
18 | @property (nonatomic, strong) WZMediaAsset *asset;
19 |
20 | //网络加载 写进度
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoPicker/WZMediaAssetBaseCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZMediaAssetBaseCell.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/21.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZMediaAssetBaseCell.h"
10 | #import "WZMediaFetcher.h"
11 |
12 | @implementation WZMediaAssetBaseCell
13 |
14 | - (void)prepareForReuse {
15 | self.imageView.image = nil;
16 | }
17 |
18 | - (instancetype)initWithFrame:(CGRect)frame
19 | {
20 | self = [super initWithFrame:frame];
21 | if (self) {
22 | // self.contentView.layer.borderWidth = 1.0;
23 | // self.contentView.layer.borderColor = [UIColor blackColor].CGColor;
24 | _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
25 | _imageView.contentMode = UIViewContentModeScaleAspectFill;
26 | _imageView.backgroundColor = [UIColor lightGrayColor];
27 | _imageView.layer.masksToBounds = true;
28 | [self.contentView addSubview:_imageView];
29 | }
30 | return self;
31 | }
32 |
33 | - (void)clickedBtn:(UIButton *)sender {
34 | if (_asset) {
35 | if (_selectedBlock) {
36 | _selectedBlock(_asset.selected);
37 | }
38 | }
39 | }
40 |
41 | - (void)setAsset:(WZMediaAsset *)asset {
42 | if ([asset isKindOfClass:[WZMediaAsset class]]) {
43 | _asset = asset;
44 | self.selectButton.selected = _asset.selected;
45 | if (_asset.imageThumbnail) {
46 | self.imageView.image = _asset.imageThumbnail;
47 | } else {
48 | __weak typeof(self) weakSelf = self;
49 | [_asset fetchThumbnailImageSynchronous:false handler:^(UIImage *image) {
50 | weakSelf.imageView.image = image;
51 | }];
52 | }
53 | }
54 | }
55 |
56 | #pragma mark - Accessor
57 | - (UIButton *)selectButton {
58 | if (!_selectButton) {
59 | CGFloat selectedBtnHW = 33;
60 | _selectButton = [[UIButton alloc] initWithFrame:CGRectMake(self.frame.size.width - selectedBtnHW , 0, selectedBtnHW, selectedBtnHW)];
61 | [self.contentView addSubview:_selectButton];
62 | [_selectButton setImage:[UIImage imageNamed:@"message_oeuvre_btn_normal"] forState:UIControlStateNormal];
63 | [_selectButton setImage:[UIImage imageNamed:@"message_oeuvre_btn_selected"] forState:UIControlStateSelected];
64 | [_selectButton addTarget:self action:@selector(clickedBtn:) forControlEvents:UIControlEventTouchUpInside];
65 | _selectButton.titleLabel.font = [UIFont boldSystemFontOfSize:16.0];
66 | }
67 | return _selectButton;
68 | }
69 |
70 |
71 | @end
72 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoPicker/WZPhotoCatalogueController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZPhotoCatalogueController.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/21.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "WZMediaAssetBaseCell.h"
11 | @class WZMediaAssetCollection;
12 | @protocol WZProtocolMediaAsset;
13 |
14 | /**
15 | * 图片目录
16 | */
17 | @interface WZPhotoCatalogueCell : WZMediaAssetBaseCell
18 |
19 | @property (nonatomic, strong) UILabel *titleLabel;
20 | @property (nonatomic, strong) UIButton *button;
21 | @property (nonatomic, strong) WZMediaAssetCollection *mediaAssetCollection;
22 | @property (nonatomic, strong) void (^clickedBlock)();
23 |
24 | @end
25 |
26 | @interface WZPhotoCatalogueController : UIViewController
27 |
28 | + (void)showPickerWithPresentedController:(UIViewController *)presentedController;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoPicker/WZPhotoCatalogueController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZPhotoCatalogueController.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/21.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZPhotoCatalogueController.h"
10 | #import "WZPhotoPickerController.h"
11 |
12 | #pragma mark - WZPhotoCatalogueController
13 | @interface WZPhotoCatalogueController()
14 |
15 | @property (nonatomic, strong) WZPhotoPickerController *pickerVC;
16 |
17 | @end
18 |
19 | @implementation WZPhotoCatalogueCell
20 |
21 | - (instancetype)initWithFrame:(CGRect)frame
22 | {
23 | self = [super initWithFrame:frame];
24 | if (self) {
25 | [self createViews];
26 | }
27 | return self;
28 | }
29 |
30 | - (void)createViews {
31 | self.imageView.frame = CGRectMake(self.frame.size.width - self.frame.size.height + 10, 10, self.frame.size.height - 20, self.frame.size.height - 20);
32 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0, self.frame.size.width - self.frame.size.height, self.frame.size.height)];
33 | [self.contentView addSubview:_titleLabel];
34 | self.backgroundColor = [UIColor lightGrayColor];
35 |
36 | _button = [[UIButton alloc] initWithFrame:self.bounds];
37 | [_button addTarget:self action:@selector(clickedBtn:) forControlEvents:UIControlEventTouchUpInside];
38 | [self.contentView addSubview:_button];
39 | [self.contentView sendSubviewToBack:_button];
40 | [_button setBackgroundImage:[[self class] imageWithColor:[UIColor colorWithRed:205.0 / 255 green:205.0 / 255 blue:205.0 / 255 alpha:1.0]] forState:UIControlStateNormal];
41 | [_button setBackgroundImage:[[self class] imageWithColor:[UIColor colorWithRed:238.0 / 255 green:238.0 / 255 blue:238.0 / 255 alpha:1.0]] forState:UIControlStateHighlighted];
42 |
43 | }
44 |
45 | - (void)clickedBtn:(UIButton *)sender {
46 | if (_clickedBlock) {
47 | _clickedBlock();
48 | }
49 | }
50 |
51 | - (void)setMediaAssetCollection:(WZMediaAssetCollection *)mediaAssetCollection {
52 | if ([mediaAssetCollection isKindOfClass:[WZMediaAssetCollection class]]) {
53 | _mediaAssetCollection = mediaAssetCollection;
54 | self.titleLabel.text = mediaAssetCollection.title;
55 | [_mediaAssetCollection coverHandler:^(UIImage *image) {
56 | self.imageView.image = image;
57 | }];
58 | }
59 | }
60 |
61 | @end
62 |
63 | #pragma mark - WZPhotoCatalogueController
64 | @interface WZPhotoCatalogueController ()
65 |
66 |
69 |
70 | @property (nonatomic, strong) UICollectionView *collection;
71 | @property (nonatomic, strong) NSArray * mediaAssetArrayCollection;
72 |
73 | @end
74 |
75 | @implementation WZPhotoCatalogueController
76 |
77 | #pragma mark - initialize
78 | + (void)showPickerWithPresentedController:(UIViewController *)presentedController {
79 | WZPhotoCatalogueController *VC = [[WZPhotoCatalogueController alloc] init];
80 | VC.pickerVC.delegate = (id)presentedController;
81 | UINavigationController *navigationVC = [[UINavigationController alloc] initWithRootViewController:VC];
82 | [presentedController presentViewController:navigationVC animated:true completion:^{}];
83 | }
84 |
85 | #pragma mark - Lifecycle
86 | - (instancetype) init {
87 | if (self = [super init]) {
88 | _pickerVC = [[WZPhotoPickerController alloc] init];
89 | _pickerVC.restrictNumber = 9;//选图限制
90 | _mediaAssetArrayCollection = [NSArray array];
91 | }
92 | return self;
93 | }
94 |
95 |
96 |
97 | - (void)viewDidLoad {
98 | [super viewDidLoad];
99 | self.view.backgroundColor = [UIColor whiteColor];
100 | self.title = NSStringFromClass([self class]);
101 | self.automaticallyAdjustsScrollViewInsets = false;
102 | [self getAuthorization];
103 | [self createViews];
104 |
105 | // NSLog(@"%@", NSStringFromUIEdgeInsets(self.additionalSafeAreaInsets));
106 | // NSLog(@"%@", NSStringFromUIEdgeInsets(self.view.safeAreaInsets));
107 |
108 | }
109 |
110 | - (void)didReceiveMemoryWarning {
111 | [super didReceiveMemoryWarning];
112 | }
113 |
114 | - (void)dealloc {
115 | NSLog(@"%s", __func__);
116 | }
117 |
118 | #pragma mark - CreateViews
119 | - (void)createViews {
120 | [self.view addSubview:self.collection];
121 |
122 | UIBarButtonItem *left = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStyleDone target:self action:@selector(back)];
123 | if (self.navigationController) {
124 | self.navigationItem.leftBarButtonItem = left;
125 | }
126 | }
127 |
128 | -(void)back {
129 | [self dismissViewControllerAnimated:true completion:^{}];
130 | }
131 |
132 | #pragma mark - fetchAuthorization
133 | - (void)getAuthorization {
134 | [NSObject requestPhotosLibraryAuthorization:^(BOOL ownAuthorization) {
135 | if (ownAuthorization) {
136 | //action
137 | dispatch_async(dispatch_get_main_queue(), ^{
138 | _mediaAssetArrayCollection = [WZMediaFetcher fetchAssetCollection];
139 | [_collection reloadData];
140 | });
141 | } else {
142 | //提示可到设置页面获取权限
143 | [self showAlter];
144 | }
145 | }];
146 | }
147 |
148 | - (void)showAlter {
149 | UIAlertController *alter = [UIAlertController alertControllerWithTitle:@"尚未获取到相册权限" message:@"是否到设置处进行权限设置" preferredStyle:UIAlertControllerStyleAlert];
150 | UIAlertAction *actionSure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
151 | [NSObject openAppSettings];
152 | }];
153 | UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
154 | [alter dismissViewControllerAnimated:true completion:nil];
155 | }];
156 | [alter addAction:actionSure];
157 | [alter addAction:actionCancel];
158 | [self presentViewController:alter animated:true completion:nil];
159 | }
160 |
161 | #pragma mark - UICollectionViewDataSource
162 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
163 | return _mediaAssetArrayCollection.count;
164 | }
165 |
166 | - (__kindof WZPhotoCatalogueCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
167 | __block WZPhotoCatalogueCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([WZPhotoCatalogueCell class]) forIndexPath:indexPath];
168 | @try {
169 | if ([_mediaAssetArrayCollection[indexPath.row] isKindOfClass:[WZMediaAssetCollection class]]) {
170 |
171 | cell.mediaAssetCollection = _mediaAssetArrayCollection[indexPath.row];
172 |
173 | __weak typeof(self) weakSelf = self;
174 | cell.clickedBlock = ^(){
175 | //点击目录 进入章节
176 | weakSelf.pickerVC.mediaAssetArray = weakSelf.mediaAssetArrayCollection[indexPath.row].mediaAssetArray;
177 | if (weakSelf.navigationController) {
178 | [weakSelf.navigationController pushViewController:weakSelf.pickerVC animated:true];
179 | }
180 | };
181 | }
182 | } @catch (NSException *exception) {
183 | NSLog(@"%@",exception.debugDescription);
184 | }
185 | return cell;
186 | }
187 |
188 | #pragma mark - Accessor
189 | - (UICollectionView *)collection {
190 | if (!_collection) {
191 | CGRect rect = self.navigationController?CGRectMake(0.0, 64.0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64.0):self.view.bounds;
192 |
193 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
194 | CGFloat gap = 10.0;
195 | layout.minimumLineSpacing = gap;
196 | layout.minimumInteritemSpacing = gap;
197 | CGFloat itemW = ([UIScreen mainScreen].bounds.size.width);
198 | CGFloat itemH = 44 + gap * 2.0;
199 | layout.itemSize = CGSizeMake(itemW, itemH);
200 |
201 | _collection = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
202 | _collection.backgroundColor = [UIColor whiteColor];
203 | _collection.delaysContentTouches = false;
204 | _collection.dataSource = self;
205 | _collection.delegate = self;
206 | [_collection registerClass:[WZPhotoCatalogueCell class] forCellWithReuseIdentifier:NSStringFromClass([WZPhotoCatalogueCell class])];
207 | }
208 | return _collection;
209 | }
210 |
211 | @end
212 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoPicker/WZPhotoPickerController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WZPhotoPickerController.h
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/19.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "WZMediaFetcher.h"
11 |
12 | /**
13 | * 图片挑选
14 | */
15 | @interface WZPhotoPickerController : UIViewController
16 |
17 | @property (nonatomic, weak) id delegate;
18 | @property (nonatomic, strong) NSArray * mediaAssetArray;
19 | @property (nonatomic, assign) NSUInteger restrictNumber;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/imagesShow/WZPhotoPicker/WZPhotoPickerController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WZPhotoPickerController.m
3 | // WZPhotoPicker
4 | //
5 | // Created by wizet on 2017/5/19.
6 | // Copyright © 2017年 wizet. All rights reserved.
7 | //
8 |
9 | #import "WZPhotoPickerController.h"
10 | #import "WZMediaAssetBaseCell.h"
11 |
12 | #import "WZImageBrowseController.h"
13 | #import "WZAssetBrowseController.h"
14 | #import "WZRemoteImageBrowseController.h"
15 |
16 | #pragma mark - WZPhotoPickerController
17 | @interface WZPhotoPickerController ()
18 |
21 |
22 | @property (nonatomic, strong) UICollectionView *collection;
23 |
24 | @end
25 |
26 | @implementation WZPhotoPickerController
27 |
28 | #pragma mark - initialize
29 |
30 | #pragma mark - ViewController Lifecycle
31 | - (void)viewDidLoad {
32 | [super viewDidLoad];
33 | self.view.backgroundColor = [UIColor whiteColor];
34 | self.title = NSStringFromClass([self class]);
35 | self.automaticallyAdjustsScrollViewInsets = false;
36 | if (!_mediaAssetArray) {
37 | _mediaAssetArray = [NSArray array];
38 | }
39 |
40 | [self createViews];
41 | }
42 |
43 | - (void)didReceiveMemoryWarning {
44 | [super didReceiveMemoryWarning];
45 | }
46 |
47 | - (void)dealloc {
48 | NSLog(@"%s", __func__);
49 | }
50 |
51 | #pragma mark - create views
52 | - (void)createViews {
53 | [self.view addSubview:self.collection];
54 | UIBarButtonItem *left = [[UIBarButtonItem alloc] initWithTitle:@"返回目录" style:UIBarButtonItemStyleDone target:self action:@selector(back)];
55 | UIBarButtonItem *right = [[UIBarButtonItem alloc] initWithTitle:@"选择完成" style:UIBarButtonItemStyleDone target:self action:@selector(finish)];
56 |
57 | if (self.navigationController) {
58 | self.navigationItem.leftBarButtonItem = left;
59 | self.navigationItem.rightBarButtonItem = right;
60 | }
61 | }
62 |
63 | - (void)finish {
64 | //如果实现了代理
65 | if ([_delegate respondsToSelector:@selector(fetchImages:)]) {
66 | //获取选中目标 同步取出大小图
67 | NSLock *lock = [[NSLock alloc] init];
68 | [lock tryLock];
69 | NSMutableArray *mArray_images = [NSMutableArray array];
70 | for (WZMediaAsset *mediaAsset in self.mediaAssetArray) {
71 | if (mediaAsset.selected) {
72 | if (mediaAsset.origion) {
73 | [mediaAsset fetchOrigionImageSynchronous:true handler:^(UIImage *image) {
74 | [mArray_images addObject:image];
75 | }];
76 | } else {
77 | [WZMediaFetcher fetchImageWithAsset:mediaAsset.asset costumSize:WZMEDIAASSET_CUSTOMSIZE synchronous:true handler:^(UIImage *image) {
78 | [mArray_images addObject:image];
79 | }];
80 | }
81 | }
82 | }
83 |
84 | [lock unlock];
85 | [_delegate fetchImages:mArray_images];
86 | //同步完
87 | [self dismiss];
88 | } else {
89 | [self dismiss];
90 | }
91 | }
92 |
93 | - (void)dismiss {
94 | [self dismissViewControllerAnimated:true completion:^{
95 | if ([_delegate respondsToSelector:@selector(fetchAssets:)]) {
96 | NSMutableArray *mmediaAssetArray_callback = [NSMutableArray array];
97 | for (WZMediaAsset *mediaAsset in self.mediaAssetArray) {
98 | if (mediaAsset.selected) {
99 | [mmediaAssetArray_callback addObject:mediaAsset];
100 | }
101 | }
102 | [_delegate fetchAssets:[NSArray arrayWithArray:mmediaAssetArray_callback]];
103 | }
104 | }];
105 | }
106 |
107 | -(void)back {
108 | //复原选择数据
109 | for (WZMediaAsset *asset in self.mediaAssetArray) {
110 | asset.selected = false;
111 | asset.origion = false;
112 | }
113 | if (self.navigationController) {
114 | [self.navigationController popViewControllerAnimated:true];
115 | } else {
116 | [self dismissViewControllerAnimated:true completion:^{}];
117 | }
118 | }
119 |
120 | #pragma mark - UICollectionViewDataSource
121 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
122 | return _mediaAssetArray.count;
123 | }
124 |
125 | - (__kindof WZMediaAssetBaseCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
126 | WZMediaAssetBaseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([WZMediaAssetBaseCell class]) forIndexPath:indexPath];
127 |
128 | @try {
129 | cell.asset = _mediaAssetArray[indexPath.row];
130 | __weak typeof(cell) weakCell = cell;
131 | __weak typeof(self) weakSelf = self;
132 | cell.selectedBlock = ^(BOOL selected) {
133 | if ([weakSelf overloadJudgement] && !weakCell.asset.selected) {
134 |
135 | } else {
136 | weakCell.asset.selected = !weakCell.asset.selected;
137 | weakCell.selectButton.selected = weakCell.asset.selected;
138 | }
139 | };
140 | } @catch (NSException *exception) {
141 |
142 | }
143 | return cell;
144 | }
145 |
146 | - (BOOL)overloadJudgement {
147 | if (self.restrictNumber == 0) {
148 | return false;
149 | }
150 |
151 | NSUInteger restrictNumber = 0;
152 | for (WZMediaAsset *asset in self.mediaAssetArray) {
153 | if (asset.selected == true) {
154 | restrictNumber = restrictNumber + 1;
155 | }
156 | }
157 | if (self.restrictNumber <= restrictNumber) {
158 | return true;
159 | }
160 |
161 | return false;
162 | }
163 |
164 |
165 | #pragma mark - UICollectionViewDelegate
166 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
167 | // WZMediaAssetBaseCell *cell = (WZMediaAssetBaseCell *)[collectionView cellForItemAtIndexPath:indexPath];
168 |
169 | //浏览大图
170 | if (self.mediaAssetArray.count) {
171 | WZAssetBrowseController *VC = [[WZAssetBrowseController alloc] init];
172 | VC.imagesBrowseDelegate = (id)self;
173 | VC.mediaAssetArray = self.mediaAssetArray;
174 | VC.restrictNumber = self.restrictNumber;
175 | [VC showInIndex:indexPath.row animated:true];
176 | [self presentViewController:VC animated:true completion:^{}];
177 | }
178 | }
179 |
180 | #pragma mark - WZProtocolImageBrowse
181 | - (void)backAction {
182 | [self.collection reloadData];
183 | }
184 |
185 | - (void)send {
186 | [self finish];
187 | }
188 |
189 | #pragma mark - WZProtocolMediaAsset
190 | - (void)fetchAssets:(NSArray *)assets {
191 | if (assets) {
192 | }
193 | }
194 |
195 | #pragma mark - Accessor
196 | - (void)setMediaAssetArray:(NSArray *)mediaAssetArray {
197 | _mediaAssetArray = [mediaAssetArray isKindOfClass:[NSArray class]]?mediaAssetArray:nil;
198 | if (_collection) {
199 | [_collection reloadData];
200 | }
201 | }
202 |
203 | - (UICollectionView *)collection {
204 | if (!_collection) {
205 | CGRect rect = self.navigationController?CGRectMake(0.0, 64.0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64.0):self.view.bounds;
206 |
207 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
208 | CGFloat gap = 10.0;
209 | layout.minimumLineSpacing = gap;
210 | layout.minimumInteritemSpacing = gap;
211 | layout.sectionInset = UIEdgeInsetsMake(gap, gap, gap, gap);
212 | CGFloat itemWH = ([UIScreen mainScreen].bounds.size.width - gap * 5) / 4;
213 | layout.itemSize = CGSizeMake(itemWH, itemWH);
214 |
215 | _collection = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
216 | _collection.backgroundColor = [UIColor whiteColor];
217 | _collection.dataSource = self;
218 | _collection.delegate = self;
219 | [_collection registerClass:[WZMediaAssetBaseCell class] forCellWithReuseIdentifier:NSStringFromClass([WZMediaAssetBaseCell class])];
220 | }
221 | return _collection;
222 | }
223 |
224 |
225 | @end
226 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKit/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TestPhotoKit
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. 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 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKitUITests/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/TestPhotoKitUITests/TestPhotoKitUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestPhotoKitUITests.m
3 | // TestPhotoKitUITests
4 | //
5 | // Created by admin on 16/7/8.
6 | // Copyright © 2016年 admin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TestPhotoKitUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation TestPhotoKitUITests
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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
21 |
22 | @interface NSData (ImageContentTypeDeprecated)
23 |
24 | + (NSString *)contentTypeForImageData:(NSData *)data __deprecated_msg("Use `sd_contentTypeForImageData:`");
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
42 |
43 | @implementation NSData (ImageContentTypeDeprecated)
44 |
45 | + (NSString *)contentTypeForImageData:(NSData *)data {
46 | return [self sd_contentTypeForImageData:data];
47 | }
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | * Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
41 | * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
42 | */
43 | @property (assign, nonatomic) BOOL shouldDecompressImages;
44 |
45 | /**
46 | * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
47 | */
48 | @property (assign, nonatomic) NSUInteger maxMemoryCost;
49 |
50 | /**
51 | * The maximum number of objects the cache should hold.
52 | */
53 | @property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
54 |
55 | /**
56 | * The maximum length of time to keep an image in the cache, in seconds
57 | */
58 | @property (assign, nonatomic) NSInteger maxCacheAge;
59 |
60 | /**
61 | * The maximum size of the cache, in bytes.
62 | */
63 | @property (assign, nonatomic) NSUInteger maxCacheSize;
64 |
65 | /**
66 | * Returns global shared cache instance
67 | *
68 | * @return SDImageCache global instance
69 | */
70 | + (SDImageCache *)sharedImageCache;
71 |
72 | /**
73 | * Init a new cache store with a specific namespace
74 | *
75 | * @param ns The namespace to use for this cache store
76 | */
77 | - (id)initWithNamespace:(NSString *)ns;
78 |
79 | /**
80 | * Init a new cache store with a specific namespace and directory
81 | *
82 | * @param ns The namespace to use for this cache store
83 | * @param directory Directory to cache disk images in
84 | */
85 | - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory;
86 |
87 | -(NSString *)makeDiskCachePath:(NSString*)fullNamespace;
88 |
89 | /**
90 | * Add a read-only cache path to search for images pre-cached by SDImageCache
91 | * Useful if you want to bundle pre-loaded images with your app
92 | *
93 | * @param path The path to use for this read-only cache path
94 | */
95 | - (void)addReadOnlyCachePath:(NSString *)path;
96 |
97 | /**
98 | * Store an image into memory and disk cache at the given key.
99 | *
100 | * @param image The image to store
101 | * @param key The unique image cache key, usually it's image absolute URL
102 | */
103 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key;
104 |
105 | /**
106 | * Store an image into memory and optionally disk cache at the given key.
107 | *
108 | * @param image The image to store
109 | * @param key The unique image cache key, usually it's image absolute URL
110 | * @param toDisk Store the image to disk cache if YES
111 | */
112 | - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk;
113 |
114 | /**
115 | * Store an image into memory and optionally disk cache at the given key.
116 | *
117 | * @param image The image to store
118 | * @param recalculate BOOL indicates if imageData can be used or a new data should be constructed from the UIImage
119 | * @param imageData The image data as returned by the server, this representation will be used for disk storage
120 | * instead of converting the given image object into a storable/compressed image format in order
121 | * to save quality and CPU
122 | * @param key The unique image cache key, usually it's image absolute URL
123 | * @param toDisk Store the image to disk cache if YES
124 | */
125 | - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk;
126 |
127 | /**
128 | * Query the disk cache asynchronously.
129 | *
130 | * @param key The unique key used to store the wanted image
131 | */
132 | - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
133 |
134 | /**
135 | * Query the memory cache synchronously.
136 | *
137 | * @param key The unique key used to store the wanted image
138 | */
139 | - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key;
140 |
141 | /**
142 | * Query the disk cache synchronously after checking the memory cache.
143 | *
144 | * @param key The unique key used to store the wanted image
145 | */
146 | - (UIImage *)imageFromDiskCacheForKey:(NSString *)key;
147 |
148 | /**
149 | * Remove the image from memory and disk cache synchronously
150 | *
151 | * @param key The unique image cache key
152 | */
153 | - (void)removeImageForKey:(NSString *)key;
154 |
155 |
156 | /**
157 | * Remove the image from memory and disk cache asynchronously
158 | *
159 | * @param key The unique image cache key
160 | * @param completion An block that should be executed after the image has been removed (optional)
161 | */
162 | - (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion;
163 |
164 | /**
165 | * Remove the image from memory and optionally disk cache asynchronously
166 | *
167 | * @param key The unique image cache key
168 | * @param fromDisk Also remove cache entry from disk if YES
169 | */
170 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk;
171 |
172 | /**
173 | * Remove the image from memory and optionally disk cache asynchronously
174 | *
175 | * @param key The unique image cache key
176 | * @param fromDisk Also remove cache entry from disk if YES
177 | * @param completion An block that should be executed after the image has been removed (optional)
178 | */
179 | - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion;
180 |
181 | /**
182 | * Clear all memory cached images
183 | */
184 | - (void)clearMemory;
185 |
186 | /**
187 | * Clear all disk cached images. Non-blocking method - returns immediately.
188 | * @param completion An block that should be executed after cache expiration completes (optional)
189 | */
190 | - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion;
191 |
192 | /**
193 | * Clear all disk cached images
194 | * @see clearDiskOnCompletion:
195 | */
196 | - (void)clearDisk;
197 |
198 | /**
199 | * Remove all expired cached image from disk. Non-blocking method - returns immediately.
200 | * @param completionBlock An block that should be executed after cache expiration completes (optional)
201 | */
202 | - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock;
203 |
204 | /**
205 | * Remove all expired cached image from disk
206 | * @see cleanDiskWithCompletionBlock:
207 | */
208 | - (void)cleanDisk;
209 |
210 | /**
211 | * Get the size used by the disk cache
212 | */
213 | - (NSUInteger)getSize;
214 |
215 | /**
216 | * Get the number of images in the disk cache
217 | */
218 | - (NSUInteger)getDiskCount;
219 |
220 | /**
221 | * Asynchronously calculate the disk cache's size.
222 | */
223 | - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock;
224 |
225 | /**
226 | * Async check if image exists in disk cache already (does not load the image)
227 | *
228 | * @param key the key describing the url
229 | * @param completionBlock the block to be executed when the check is done.
230 | * @note the completion block will be always executed on the main queue
231 | */
232 | - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock;
233 |
234 | /**
235 | * Check if image exists in disk cache already (does not load the image)
236 | *
237 | * @param key the key describing the url
238 | *
239 | * @return YES if an image exists for the given key
240 | */
241 | - (BOOL)diskImageExistsWithKey:(NSString *)key;
242 |
243 | /**
244 | * Get the cache path for a certain key (needs the cache path root folder)
245 | *
246 | * @param key the key (can be obtained from url using cacheKeyForURL)
247 | * @param path the cach path root folder
248 | *
249 | * @return the cache path
250 | */
251 | - (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path;
252 |
253 | /**
254 | * Get the default cache path for a certain key
255 | *
256 | * @param key the key (can be obtained from url using cacheKeyForURL)
257 | *
258 | * @return the default cache path
259 | */
260 | - (NSString *)defaultCachePathForKey:(NSString *)key;
261 |
262 | @end
263 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 != 20000 && __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 | extern NSString *const SDWebImageErrorDomain;
59 |
60 | #define dispatch_main_sync_safe(block)\
61 | if ([NSThread isMainThread]) {\
62 | block();\
63 | } else {\
64 | dispatch_sync(dispatch_get_main_queue(), block);\
65 | }
66 |
67 | #define dispatch_main_async_safe(block)\
68 | if ([NSThread isMainThread]) {\
69 | block();\
70 | } else {\
71 | dispatch_async(dispatch_get_main_queue(), block);\
72 | }
73 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | NSRange range = [key rangeOfString:@"@2x."];
34 | if (range.location != NSNotFound) {
35 | scale = 2.0;
36 | }
37 |
38 | range = [key rangeOfString:@"@3x."];
39 | if (range.location != NSNotFound) {
40 | scale = 3.0;
41 | }
42 | }
43 |
44 | UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
45 | image = scaledImage;
46 | }
47 | return image;
48 | }
49 | }
50 |
51 | NSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain";
52 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
55 | /**
56 | * Default value. All download operations will execute in queue style (first-in-first-out).
57 | */
58 | SDWebImageDownloaderFIFOExecutionOrder,
59 |
60 | /**
61 | * All download operations will execute in stack style (last-in-first-out).
62 | */
63 | SDWebImageDownloaderLIFOExecutionOrder
64 | };
65 |
66 | extern NSString *const SDWebImageDownloadStartNotification;
67 | extern NSString *const SDWebImageDownloadStopNotification;
68 |
69 | typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize);
70 |
71 | typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished);
72 |
73 | typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers);
74 |
75 | /**
76 | * Asynchronous downloader dedicated and optimized for image loading.
77 | */
78 | @interface SDWebImageDownloader : NSObject
79 |
80 | /**
81 | * Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
82 | * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
83 | */
84 | @property (assign, nonatomic) BOOL shouldDecompressImages;
85 |
86 | @property (assign, nonatomic) NSInteger maxConcurrentDownloads;
87 |
88 | /**
89 | * Shows the current amount of downloads that still need to be downloaded
90 | */
91 | @property (readonly, nonatomic) NSUInteger currentDownloadCount;
92 |
93 |
94 | /**
95 | * The timeout value (in seconds) for the download operation. Default: 15.0.
96 | */
97 | @property (assign, nonatomic) NSTimeInterval downloadTimeout;
98 |
99 |
100 | /**
101 | * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`.
102 | */
103 | @property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;
104 |
105 | /**
106 | * Singleton method, returns the shared instance
107 | *
108 | * @return global shared instance of downloader class
109 | */
110 | + (SDWebImageDownloader *)sharedDownloader;
111 |
112 | /**
113 | * Set username
114 | */
115 | @property (strong, nonatomic) NSString *username;
116 |
117 | /**
118 | * Set password
119 | */
120 | @property (strong, nonatomic) NSString *password;
121 |
122 | /**
123 | * Set filter to pick headers for downloading image HTTP request.
124 | *
125 | * This block will be invoked for each downloading image request, returned
126 | * NSDictionary will be used as headers in corresponding HTTP request.
127 | */
128 | @property (nonatomic, copy) SDWebImageDownloaderHeadersFilterBlock headersFilter;
129 |
130 | /**
131 | * Set a value for a HTTP header to be appended to each download HTTP request.
132 | *
133 | * @param value The value for the header field. Use `nil` value to remove the header.
134 | * @param field The name of the header field to set.
135 | */
136 | - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
137 |
138 | /**
139 | * Returns the value of the specified HTTP header field.
140 | *
141 | * @return The value associated with the header field field, or `nil` if there is no corresponding header field.
142 | */
143 | - (NSString *)valueForHTTPHeaderField:(NSString *)field;
144 |
145 | /**
146 | * Sets a subclass of `SDWebImageDownloaderOperation` as the default
147 | * `NSOperation` to be used each time SDWebImage constructs a request
148 | * operation to download an image.
149 | *
150 | * @param operationClass The subclass of `SDWebImageDownloaderOperation` to set
151 | * as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`.
152 | */
153 | - (void)setOperationClass:(Class)operationClass;
154 |
155 | /**
156 | * Creates a SDWebImageDownloader async downloader instance with a given URL
157 | *
158 | * The delegate will be informed when the image is finish downloaded or an error has happen.
159 | *
160 | * @see SDWebImageDownloaderDelegate
161 | *
162 | * @param url The URL to the image to download
163 | * @param options The options to be used for this download
164 | * @param progressBlock A block called repeatedly while the image is downloading
165 | * @param completedBlock A block called once the download is completed.
166 | * If the download succeeded, the image parameter is set, in case of error,
167 | * error parameter is set with the error. The last parameter is always YES
168 | * if SDWebImageDownloaderProgressiveDownload isn't use. With the
169 | * SDWebImageDownloaderProgressiveDownload option, this block is called
170 | * repeatedly with the partial image object and the finished argument set to NO
171 | * before to be called a last time with the full image and finished argument
172 | * set to YES. In case of error, the finished argument is always YES.
173 | *
174 | * @return A cancellable SDWebImageOperation
175 | */
176 | - (id )downloadImageWithURL:(NSURL *)url
177 | options:(SDWebImageDownloaderOptions)options
178 | progress:(SDWebImageDownloaderProgressBlock)progressBlock
179 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock;
180 |
181 | /**
182 | * Sets the download queue suspension state
183 | */
184 | - (void)setSuspended:(BOOL)suspended;
185 |
186 | @end
187 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | extern NSString *const SDWebImageDownloadStartNotification;
14 | extern NSString *const SDWebImageDownloadReceiveResponseNotification;
15 | extern NSString *const SDWebImageDownloadStopNotification;
16 | extern NSString *const SDWebImageDownloadFinishNotification;
17 |
18 | @interface SDWebImageDownloaderOperation : NSOperation
19 |
20 | /**
21 | * The request used by the operation's connection.
22 | */
23 | @property (strong, nonatomic, readonly) NSURLRequest *request;
24 |
25 |
26 | @property (assign, nonatomic) BOOL shouldDecompressImages;
27 |
28 | /**
29 | * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default.
30 | *
31 | * This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`.
32 | */
33 | @property (nonatomic, assign) BOOL shouldUseCredentialStorage;
34 |
35 | /**
36 | * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`.
37 | *
38 | * This will be overridden by any shared credentials that exist for the username or password of the request URL, if present.
39 | */
40 | @property (nonatomic, strong) NSURLCredential *credential;
41 |
42 | /**
43 | * The SDWebImageDownloaderOptions for the receiver.
44 | */
45 | @property (assign, nonatomic, readonly) SDWebImageDownloaderOptions options;
46 |
47 | /**
48 | * The expected size of data.
49 | */
50 | @property (assign, nonatomic) NSInteger expectedSize;
51 |
52 | /**
53 | * The response returned by the operation's connection.
54 | */
55 | @property (strong, nonatomic) NSURLResponse *response;
56 |
57 | /**
58 | * Initializes a `SDWebImageDownloaderOperation` object
59 | *
60 | * @see SDWebImageDownloaderOperation
61 | *
62 | * @param request the URL request
63 | * @param options downloader options
64 | * @param progressBlock the block executed when a new chunk of data arrives.
65 | * @note the progress block is executed on a background queue
66 | * @param completedBlock the block executed when the download is done.
67 | * @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
68 | * @param cancelBlock the block executed if the download (operation) is cancelled
69 | *
70 | * @return the initialized instance
71 | */
72 | - (id)initWithRequest:(NSURLRequest *)request
73 | options:(SDWebImageDownloaderOptions)options
74 | progress:(SDWebImageDownloaderProgressBlock)progressBlock
75 | completed:(SDWebImageDownloaderCompletedBlock)completedBlock
76 | cancelled:(SDWebImageNoParamsBlock)cancelBlock;
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | /**
62 | * Queue options for Prefetcher. Defaults to Main Queue.
63 | */
64 | @property (nonatomic, assign) dispatch_queue_t prefetcherQueue;
65 |
66 | @property (weak, nonatomic) id delegate;
67 |
68 | /**
69 | * Return the global image prefetcher instance.
70 | */
71 | + (SDWebImagePrefetcher *)sharedImagePrefetcher;
72 |
73 | /**
74 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,
75 | * currently one image is downloaded at a time,
76 | * and skips images for failed downloads and proceed to the next image in the list
77 | *
78 | * @param urls list of URLs to prefetch
79 | */
80 | - (void)prefetchURLs:(NSArray *)urls;
81 |
82 | /**
83 | * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,
84 | * currently one image is downloaded at a time,
85 | * and skips images for failed downloads and proceed to the next image in the list
86 | *
87 | * @param urls list of URLs to prefetch
88 | * @param progressBlock block to be called when progress updates;
89 | * first parameter is the number of completed (successful or not) requests,
90 | * second parameter is the total number of images originally requested to be prefetched
91 | * @param completionBlock block to be called when prefetching is completed
92 | * first param is the number of completed (successful or not) requests,
93 | * second parameter is the number of skipped requests
94 | */
95 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock;
96 |
97 | /**
98 | * Remove and cancel queued list
99 | */
100 | - (void)cancelPrefetching;
101 |
102 |
103 | @end
104 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | _prefetcherQueue = dispatch_get_main_queue();
44 | self.maxConcurrentDownloads = 3;
45 | }
46 | return self;
47 | }
48 |
49 | - (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads {
50 | self.manager.imageDownloader.maxConcurrentDownloads = maxConcurrentDownloads;
51 | }
52 |
53 | - (NSUInteger)maxConcurrentDownloads {
54 | return self.manager.imageDownloader.maxConcurrentDownloads;
55 | }
56 |
57 | - (void)startPrefetchingAtIndex:(NSUInteger)index {
58 | if (index >= self.prefetchURLs.count) return;
59 | self.requestedCount++;
60 | [self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
61 | if (!finished) return;
62 | self.finishedCount++;
63 |
64 | if (image) {
65 | if (self.progressBlock) {
66 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
67 | }
68 | NSLog(@"Prefetched %@ out of %@", @(self.finishedCount), @(self.prefetchURLs.count));
69 | }
70 | else {
71 | if (self.progressBlock) {
72 | self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
73 | }
74 | NSLog(@"Prefetched %@ out of %@ (Failed)", @(self.finishedCount), @(self.prefetchURLs.count));
75 |
76 | // Add last failed
77 | self.skippedCount++;
78 | }
79 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) {
80 | [self.delegate imagePrefetcher:self
81 | didPrefetchURL:self.prefetchURLs[index]
82 | finishedCount:self.finishedCount
83 | totalCount:self.prefetchURLs.count
84 | ];
85 | }
86 | if (self.prefetchURLs.count > self.requestedCount) {
87 | dispatch_async(self.prefetcherQueue, ^{
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 | self.progressBlock = nil;
98 | }
99 | }];
100 | }
101 |
102 | - (void)reportStatus {
103 | NSUInteger total = [self.prefetchURLs count];
104 | NSLog(@"Finished prefetching (%@ successful, %@ skipped, timeElasped %.2f)", @(total - self.skippedCount), @(self.skippedCount), CFAbsoluteTimeGetCurrent() - self.startedTime);
105 | if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) {
106 | [self.delegate imagePrefetcher:self
107 | didFinishWithTotalCount:(total - self.skippedCount)
108 | skippedCount:self.skippedCount
109 | ];
110 | }
111 | }
112 |
113 | - (void)prefetchURLs:(NSArray *)urls {
114 | [self prefetchURLs:urls progress:nil completed:nil];
115 | }
116 |
117 | - (void)prefetchURLs:(NSArray *)urls progress:(SDWebImagePrefetcherProgressBlock)progressBlock completed:(SDWebImagePrefetcherCompletionBlock)completionBlock {
118 | [self cancelPrefetching]; // Prevent duplicate prefetch request
119 | self.startedTime = CFAbsoluteTimeGetCurrent();
120 | self.prefetchURLs = urls;
121 | self.completionBlock = completionBlock;
122 | self.progressBlock = progressBlock;
123 |
124 | if(urls.count == 0){
125 | if(completionBlock){
126 | completionBlock(0,0);
127 | }
128 | }else{
129 | // Starts prefetching from the very first image on the list with the max allowed concurrency
130 | NSUInteger listCount = self.prefetchURLs.count;
131 | for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) {
132 | [self startPrefetchingAtIndex:i];
133 | }
134 | }
135 | }
136 |
137 | - (void)cancelPrefetching {
138 | self.prefetchURLs = nil;
139 | self.skippedCount = 0;
140 | self.requestedCount = 0;
141 | self.finishedCount = 0;
142 | [self.manager cancelAll];
143 | }
144 |
145 | @end
146 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 | if (!data) {
22 | return nil;
23 | }
24 |
25 | UIImage *image;
26 | NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
27 | if ([imageContentType isEqualToString:@"image/gif"]) {
28 | image = [UIImage sd_animatedGIFWithData:data];
29 | }
30 | #ifdef SD_WEBP
31 | else if ([imageContentType isEqualToString:@"image/webp"])
32 | {
33 | image = [UIImage sd_imageWithWebPData:data];
34 | }
35 | #endif
36 | else {
37 | image = [[UIImage alloc] initWithData:data];
38 | UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
39 | if (orientation != UIImageOrientationUp) {
40 | image = [UIImage imageWithCGImage:image.CGImage
41 | scale:image.scale
42 | orientation:orientation];
43 | }
44 | }
45 |
46 |
47 | return image;
48 | }
49 |
50 |
51 | +(UIImageOrientation)sd_imageOrientationFromImageData:(NSData *)imageData {
52 | UIImageOrientation result = UIImageOrientationUp;
53 | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
54 | if (imageSource) {
55 | CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
56 | if (properties) {
57 | CFTypeRef val;
58 | int exifOrientation;
59 | val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
60 | if (val) {
61 | CFNumberGetValue(val, kCFNumberIntType, &exifOrientation);
62 | result = [self sd_exifOrientationToiOSOrientation:exifOrientation];
63 | } // else - if it's not set it remains at up
64 | CFRelease((CFTypeRef) properties);
65 | } else {
66 | //NSLog(@"NO PROPERTIES, FAIL");
67 | }
68 | CFRelease(imageSource);
69 | }
70 | return result;
71 | }
72 |
73 | #pragma mark EXIF orientation tag converter
74 | // Convert an EXIF image orientation to an iOS one.
75 | // reference see here: http://sylvana.net/jpegcrop/exif_orientation.html
76 | + (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation {
77 | UIImageOrientation orientation = UIImageOrientationUp;
78 | switch (exifOrientation) {
79 | case 1:
80 | orientation = UIImageOrientationUp;
81 | break;
82 |
83 | case 3:
84 | orientation = UIImageOrientationDown;
85 | break;
86 |
87 | case 8:
88 | orientation = UIImageOrientationLeft;
89 | break;
90 |
91 | case 6:
92 | orientation = UIImageOrientationRight;
93 | break;
94 |
95 | case 2:
96 | orientation = UIImageOrientationUpMirrored;
97 | break;
98 |
99 | case 4:
100 | orientation = UIImageOrientationDownMirrored;
101 | break;
102 |
103 | case 5:
104 | orientation = UIImageOrientationLeftMirrored;
105 | break;
106 |
107 | case 7:
108 | orientation = UIImageOrientationRightMirrored;
109 | break;
110 | default:
111 | break;
112 | }
113 | return orientation;
114 | }
115 |
116 |
117 |
118 | @end
119 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
89 |
90 | @interface UIImageView (HighlightedWebCacheDeprecated)
91 |
92 | - (void)setHighlightedImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:`");
93 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:`");
94 | - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:completed:`");
95 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:completed:`");
96 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:progress:completed:`");
97 |
98 | - (void)cancelCurrentHighlightedImageLoad __deprecated_msg("Use `sd_cancelCurrentHighlightedImageLoad`");
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 __typeof(self)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 |
68 |
69 | @implementation UIImageView (HighlightedWebCacheDeprecated)
70 |
71 | - (void)setHighlightedImageWithURL:(NSURL *)url {
72 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil];
73 | }
74 |
75 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options {
76 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil];
77 | }
78 |
79 | - (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
80 | [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
81 | if (completedBlock) {
82 | completedBlock(image, error, cacheType);
83 | }
84 | }];
85 | }
86 |
87 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
88 | [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
89 | if (completedBlock) {
90 | completedBlock(image, error, cacheType);
91 | }
92 | }];
93 | }
94 |
95 | - (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock {
96 | [self sd_setHighlightedImageWithURL:url options:0 progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
97 | if (completedBlock) {
98 | completedBlock(image, error, cacheType);
99 | }
100 | }];
101 | }
102 |
103 | - (void)cancelCurrentHighlightedImageLoad {
104 | [self sd_cancelCurrentHighlightedImageLoad];
105 | }
106 |
107 | @end
108 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 __typeof(self)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 && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
58 | {
59 | completedBlock(image, error, cacheType, url);
60 | return;
61 | }
62 | else if (image) {
63 | wself.image = image;
64 | [wself setNeedsLayout];
65 | } else {
66 | if ((options & SDWebImageDelayPlaceholder)) {
67 | wself.image = placeholder;
68 | [wself setNeedsLayout];
69 | }
70 | }
71 | if (completedBlock && finished) {
72 | completedBlock(image, error, cacheType, url);
73 | }
74 | });
75 | }];
76 | [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
77 | } else {
78 | dispatch_main_async_safe(^{
79 | NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
80 | if (completedBlock) {
81 | completedBlock(nil, error, SDImageCacheTypeNone, url);
82 | }
83 | });
84 | }
85 | }
86 |
87 | - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
88 | NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
89 | UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
90 |
91 | [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock];
92 | }
93 |
94 | - (NSURL *)sd_imageURL {
95 | return objc_getAssociatedObject(self, &imageURLKey);
96 | }
97 |
98 | - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs {
99 | [self sd_cancelCurrentAnimationImagesLoad];
100 | __weak __typeof(self)wself = self;
101 |
102 | NSMutableArray *operationsArray = [[NSMutableArray alloc] init];
103 |
104 | for (NSURL *logoImageURL in arrayOfURLs) {
105 | id operation = [SDWebImageManager.sharedManager downloadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
106 | if (!wself) return;
107 | dispatch_main_sync_safe(^{
108 | __strong UIImageView *sself = wself;
109 | [sself stopAnimating];
110 | if (sself && image) {
111 | NSMutableArray *currentImages = [[sself animationImages] mutableCopy];
112 | if (!currentImages) {
113 | currentImages = [[NSMutableArray alloc] init];
114 | }
115 | [currentImages addObject:image];
116 |
117 | sself.animationImages = currentImages;
118 | [sself setNeedsLayout];
119 | }
120 | [sself startAnimating];
121 | });
122 | }];
123 | [operationsArray addObject:operation];
124 | }
125 |
126 | [self sd_setImageLoadOperation:[NSArray arrayWithArray:operationsArray] forKey:@"UIImageViewAnimationImages"];
127 | }
128 |
129 | - (void)sd_cancelCurrentImageLoad {
130 | [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"];
131 | }
132 |
133 | - (void)sd_cancelCurrentAnimationImagesLoad {
134 | [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
135 | }
136 |
137 | @end
138 |
139 |
140 | @implementation UIImageView (WebCacheDeprecated)
141 |
142 | - (NSURL *)imageURL {
143 | return [self sd_imageURL];
144 | }
145 |
146 | - (void)setImageWithURL:(NSURL *)url {
147 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
148 | }
149 |
150 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder {
151 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
152 | }
153 |
154 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
155 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
156 | }
157 |
158 | - (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
159 | [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
160 | if (completedBlock) {
161 | completedBlock(image, error, cacheType);
162 | }
163 | }];
164 | }
165 |
166 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock {
167 | [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
168 | if (completedBlock) {
169 | completedBlock(image, error, cacheType);
170 | }
171 | }];
172 | }
173 |
174 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
175 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
176 | if (completedBlock) {
177 | completedBlock(image, error, cacheType);
178 | }
179 | }];
180 | }
181 |
182 | - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock {
183 | [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
184 | if (completedBlock) {
185 | completedBlock(image, error, cacheType);
186 | }
187 | }];
188 | }
189 |
190 | - (void)cancelCurrentArrayLoad {
191 | [self sd_cancelCurrentAnimationImagesLoad];
192 | }
193 |
194 | - (void)cancelCurrentImageLoad {
195 | [self sd_cancelCurrentImageLoad];
196 | }
197 |
198 | - (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs {
199 | [self sd_setAnimationImagesWithURLs:arrayOfURLs];
200 | }
201 |
202 | @end
203 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------
/TestPhotoKit/ThirdLibrary/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 |
--------------------------------------------------------------------------------