From 58d7d1e53a8901b6da604600905b46b5045b6ea4 Mon Sep 17 00:00:00 2001 From: stewen <784547228@qq.com> Date: Mon, 10 Feb 2025 15:00:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E9=A1=B9=E7=9B=AE=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=85=A8=E9=83=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 28 + .../contents.xcworkspacedata | 7 + LICENSE | 22 + Package.swift | 29 + README.md | 176 +++ TZImagePickerController.podspec | 23 + .../project.pbxproj | 1084 +++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../TZImagePickerControllerFramework.xcscheme | 80 + TZImagePickerController/AppDelegate.h | 17 + TZImagePickerController/AppDelegate.m | 85 + .../AlbumAddBtn.imageset/AlbumAddBtn@2x.png | Bin 0 -> 136 bytes .../AlbumAddBtn.imageset/Contents.json | 21 + .../AppIcon.appiconset/Contents.json | 53 + .../Assets.xcassets/Contents.json | 6 + .../back.imageset/Contents.json | 21 + .../Assets.xcassets/back.imageset/back@2x.png | Bin 0 -> 2162 bytes .../leftVideoEdit.imageset/Contents.json | 21 + .../hx_videoedit_left@2x.png | Bin 0 -> 122 bytes .../photo_delete.imageset/Contents.json | 21 + .../photo_delete.imageset/photo_delete@2x.png | Bin 0 -> 347 bytes .../rightVideoEdit.imageset/Contents.json | 21 + .../hx_videoedit_right@2x.png | Bin 0 -> 122 bytes .../Base.lproj/LaunchScreen.storyboard | 29 + .../Base.lproj/Main.storyboard | 393 +++++ .../FLAnimatedImage/FLAnimatedImage.h | 84 + .../FLAnimatedImage/FLAnimatedImage.m | 816 ++++++++++ .../FLAnimatedImage/FLAnimatedImageView.h | 36 + .../FLAnimatedImage/FLAnimatedImageView.m | 442 ++++++ TZImagePickerController/Info.plist | 57 + .../Location/TZLocationManager.h | 27 + .../Location/TZLocationManager.m | 90 ++ .../LxGridViewFlowLayout.h | 57 + .../LxGridViewFlowLayout.m | 408 +++++ .../ScreenShots/DemoPage.png | Bin 0 -> 52272 bytes .../ScreenShots/photoPickerVc.PNG | Bin 0 -> 333897 bytes .../ScreenShots/photoPreviewVc.PNG | Bin 0 -> 160218 bytes .../ScreenShots/videoPlayerVc.PNG | Bin 0 -> 109188 bytes .../NSBundle+TZImagePicker.h | 19 + .../NSBundle+TZImagePicker.m | 35 + .../TZImagePickerController/TZAssetCell.h | 61 + .../TZImagePickerController/TZAssetCell.m | 548 +++++++ .../TZImagePickerController/TZAssetModel.h | 56 + .../TZImagePickerController/TZAssetModel.m | 79 + .../TZAuthLimitedFooterTipView.h | 16 + .../TZAuthLimitedFooterTipView.m | 87 ++ .../TZGifPhotoPreviewController.h | 16 + .../TZGifPhotoPreviewController.m | 173 +++ .../TZImageCropManager.h | 39 + .../TZImageCropManager.m | 199 +++ .../TZImagePickerController/TZImageManager.h | 148 ++ .../TZImagePickerController/TZImageManager.m | 1163 ++++++++++++++ .../MMVideoPreviewPlay@2x.png | Bin 0 -> 3645 bytes .../MMVideoPreviewPlayHL@2x.png | Bin 0 -> 3645 bytes .../VideoSendIcon@2x.png | Bin 0 -> 223 bytes .../addMore@2x.png | Bin 0 -> 643 bytes .../ar.lproj/Localizable.strings | 26 + .../de.lproj/Localizable.strings | 26 + .../en.lproj/Localizable.strings | Bin 0 -> 3760 bytes .../es.lproj/Localizable.strings | 26 + .../fr.lproj/Localizable.strings | 26 + .../iCloudError@2x.png | Bin 0 -> 4394 bytes .../ja.lproj/Localizable.strings | 26 + .../ko-KP.lproj/Localizable.strings | 26 + .../navi_back@2x.png | Bin 0 -> 116 bytes .../photo_def_photoPickerVc@2x.png | Bin 0 -> 1155 bytes .../photo_def_previewVc@2x.png | Bin 0 -> 1155 bytes .../photo_number_icon@2x.png | Bin 0 -> 501 bytes .../photo_original_def@2x.png | Bin 0 -> 1602 bytes .../photo_original_sel@2x.png | Bin 0 -> 620 bytes .../photo_sel_photoPickerVc@2x.png | Bin 0 -> 1006 bytes .../photo_sel_previewVc@2x.png | Bin 0 -> 1183 bytes .../preview_number_icon@2x.png | Bin 0 -> 501 bytes .../preview_original_def@2x.png | Bin 0 -> 392 bytes .../pt.lproj/Localizable.strings | 26 + .../right_arrow@2x.png | Bin 0 -> 1259 bytes .../ru.lproj/Localizable.strings | 26 + .../takePicture80@2x.png | Bin 0 -> 1285 bytes .../takePicture@2x.png | Bin 0 -> 3054 bytes .../TZImagePickerController.bundle/tip@2x.png | Bin 0 -> 671 bytes .../vi.lproj/Localizable.strings | 26 + .../zh-Hans.lproj/Localizable.strings | Bin 0 -> 2892 bytes .../zh-Hant.lproj/Localizable.strings | Bin 0 -> 2892 bytes .../TZImagePickerController.h | 396 +++++ .../TZImagePickerController.m | 1131 ++++++++++++++ .../TZImageRequestOperation.h | 30 + .../TZImageRequestOperation.m | 77 + .../TZPhotoPickerController.h | 27 + .../TZPhotoPickerController.m | 1377 +++++++++++++++++ .../TZPhotoPreviewCell.h | 76 + .../TZPhotoPreviewCell.m | 576 +++++++ .../TZPhotoPreviewController.h | 25 + .../TZPhotoPreviewController.m | 686 ++++++++ .../TZImagePickerController/TZProgressView.h | 15 + .../TZImagePickerController/TZProgressView.m | 55 + .../TZVideoCropController.h | 47 + .../TZVideoCropController.m | 673 ++++++++ .../TZVideoEditedPreviewController.h | 17 + .../TZVideoEditedPreviewController.m | 129 ++ .../TZVideoPlayerController.h | 17 + .../TZVideoPlayerController.m | 325 ++++ .../TZImagePickerController/UIView+TZLayout.h | 31 + .../TZImagePickerController/UIView+TZLayout.m | 126 ++ .../TZImageUploadOperation.h | 17 + .../TZImageUploadOperation.m | 69 + TZImagePickerController/TZTestCell.h | 23 + TZImagePickerController/TZTestCell.m | 92 ++ TZImagePickerController/ViewController.h | 15 + TZImagePickerController/ViewController.m | 889 +++++++++++ .../ar-001.lproj/LaunchScreen.strings | 1 + .../ar-001.lproj/Localizable.strings | Bin 0 -> 1886 bytes .../ar-001.lproj/Main.strings | 48 + TZImagePickerController/main.m | 16 + .../tz-ru.lproj/Localizable.strings | Bin 0 -> 1886 bytes .../zh-Hans.lproj/LaunchScreen.strings | 1 + .../zh-Hans.lproj/Main.strings | 18 + TZImagePickerControllerFramework/Info.plist | 24 + .../PrivacyInfo.xcprivacy | 25 + TZImagePickerControllerTests/Info.plist | 24 + .../TZImagePickerControllerTests.m | 39 + TZImagePickerControllerUITests/Info.plist | 24 + .../TZImagePickerControllerUITests.m | 40 + 123 files changed, 14243 insertions(+) create mode 100644 .gitignore create mode 100644 .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata create mode 100644 LICENSE create mode 100644 Package.swift create mode 100644 TZImagePickerController.podspec create mode 100644 TZImagePickerController.xcodeproj/project.pbxproj create mode 100644 TZImagePickerController.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 TZImagePickerController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 TZImagePickerController.xcodeproj/xcshareddata/xcschemes/TZImagePickerControllerFramework.xcscheme create mode 100644 TZImagePickerController/AppDelegate.h create mode 100644 TZImagePickerController/AppDelegate.m create mode 100644 TZImagePickerController/Assets.xcassets/AlbumAddBtn.imageset/AlbumAddBtn@2x.png create mode 100644 TZImagePickerController/Assets.xcassets/AlbumAddBtn.imageset/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/back.imageset/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/back.imageset/back@2x.png create mode 100644 TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/hx_videoedit_left@2x.png create mode 100644 TZImagePickerController/Assets.xcassets/photo_delete.imageset/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/photo_delete.imageset/photo_delete@2x.png create mode 100644 TZImagePickerController/Assets.xcassets/rightVideoEdit.imageset/Contents.json create mode 100644 TZImagePickerController/Assets.xcassets/rightVideoEdit.imageset/hx_videoedit_right@2x.png create mode 100644 TZImagePickerController/Base.lproj/LaunchScreen.storyboard create mode 100644 TZImagePickerController/Base.lproj/Main.storyboard create mode 100644 TZImagePickerController/FLAnimatedImage/FLAnimatedImage.h create mode 100755 TZImagePickerController/FLAnimatedImage/FLAnimatedImage.m create mode 100644 TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.h create mode 100755 TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.m create mode 100644 TZImagePickerController/Info.plist create mode 100644 TZImagePickerController/Location/TZLocationManager.h create mode 100644 TZImagePickerController/Location/TZLocationManager.m create mode 100755 TZImagePickerController/LxGridViewFlowLayout.h create mode 100755 TZImagePickerController/LxGridViewFlowLayout.m create mode 100644 TZImagePickerController/ScreenShots/DemoPage.png create mode 100644 TZImagePickerController/ScreenShots/photoPickerVc.PNG create mode 100644 TZImagePickerController/ScreenShots/photoPreviewVc.PNG create mode 100644 TZImagePickerController/ScreenShots/videoPlayerVc.PNG create mode 100755 TZImagePickerController/TZImagePickerController/NSBundle+TZImagePicker.h create mode 100755 TZImagePickerController/TZImagePickerController/NSBundle+TZImagePicker.m create mode 100644 TZImagePickerController/TZImagePickerController/TZAssetCell.h create mode 100644 TZImagePickerController/TZImagePickerController/TZAssetCell.m create mode 100755 TZImagePickerController/TZImagePickerController/TZAssetModel.h create mode 100644 TZImagePickerController/TZImagePickerController/TZAssetModel.m create mode 100644 TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.h create mode 100644 TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.m create mode 100644 TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.h create mode 100644 TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.m create mode 100644 TZImagePickerController/TZImagePickerController/TZImageCropManager.h create mode 100644 TZImagePickerController/TZImagePickerController/TZImageCropManager.m create mode 100755 TZImagePickerController/TZImagePickerController/TZImageManager.h create mode 100755 TZImagePickerController/TZImagePickerController/TZImageManager.m create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlay@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlayHL@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/VideoSendIcon@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/addMore@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ar.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/de.lproj/Localizable.strings create mode 100755 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/en.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/es.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/fr.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/iCloudError@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ja.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ko-KP.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/navi_back@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_def_photoPickerVc@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_def_previewVc@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_number_icon@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_original_def@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_original_sel@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_sel_photoPickerVc@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_sel_previewVc@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/preview_number_icon@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/preview_original_def@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/pt.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/right_arrow@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ru.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/takePicture80@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/takePicture@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/tip@2x.png create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/vi.lproj/Localizable.strings create mode 100755 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/zh-Hans.lproj/Localizable.strings create mode 100755 TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/zh-Hant.lproj/Localizable.strings create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.h create mode 100644 TZImagePickerController/TZImagePickerController/TZImagePickerController.m create mode 100644 TZImagePickerController/TZImagePickerController/TZImageRequestOperation.h create mode 100644 TZImagePickerController/TZImagePickerController/TZImageRequestOperation.m create mode 100644 TZImagePickerController/TZImagePickerController/TZPhotoPickerController.h create mode 100755 TZImagePickerController/TZImagePickerController/TZPhotoPickerController.m create mode 100644 TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.h create mode 100644 TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m create mode 100644 TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.h create mode 100644 TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.m create mode 100644 TZImagePickerController/TZImagePickerController/TZProgressView.h create mode 100644 TZImagePickerController/TZImagePickerController/TZProgressView.m create mode 100644 TZImagePickerController/TZImagePickerController/TZVideoCropController.h create mode 100644 TZImagePickerController/TZImagePickerController/TZVideoCropController.m create mode 100644 TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.h create mode 100644 TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.m create mode 100644 TZImagePickerController/TZImagePickerController/TZVideoPlayerController.h create mode 100644 TZImagePickerController/TZImagePickerController/TZVideoPlayerController.m create mode 100644 TZImagePickerController/TZImagePickerController/UIView+TZLayout.h create mode 100644 TZImagePickerController/TZImagePickerController/UIView+TZLayout.m create mode 100644 TZImagePickerController/TZImageUploadOperation.h create mode 100644 TZImagePickerController/TZImageUploadOperation.m create mode 100644 TZImagePickerController/TZTestCell.h create mode 100644 TZImagePickerController/TZTestCell.m create mode 100644 TZImagePickerController/ViewController.h create mode 100644 TZImagePickerController/ViewController.m create mode 100644 TZImagePickerController/ar-001.lproj/LaunchScreen.strings create mode 100755 TZImagePickerController/ar-001.lproj/Localizable.strings create mode 100644 TZImagePickerController/ar-001.lproj/Main.strings create mode 100644 TZImagePickerController/main.m create mode 100755 TZImagePickerController/tz-ru.lproj/Localizable.strings create mode 100644 TZImagePickerController/zh-Hans.lproj/LaunchScreen.strings create mode 100644 TZImagePickerController/zh-Hans.lproj/Main.strings create mode 100644 TZImagePickerControllerFramework/Info.plist create mode 100644 TZImagePickerControllerFramework/PrivacyInfo.xcprivacy create mode 100644 TZImagePickerControllerTests/Info.plist create mode 100644 TZImagePickerControllerTests/TZImagePickerControllerTests.m create mode 100644 TZImagePickerControllerUITests/Info.plist create mode 100644 TZImagePickerControllerUITests/TZImagePickerControllerUITests.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..754e6b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control +# +#Pods/ + +.DS_Store diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d2a8818 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zhen Tan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..eb90b24 --- /dev/null +++ b/Package.swift @@ -0,0 +1,29 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "TZImagePickerController", + platforms: [.iOS(.v8)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "TZImagePickerController", + targets: ["TZImagePickerController"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "TZImagePickerController", + path: "TZImagePickerController/TZImagePickerController", + resources: [.process("TZImagePickerController.bundle")], + publicHeadersPath: "." + ) + ] +) diff --git a/README.md b/README.md index e69de29..960d431 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,176 @@ +# TZImagePickerController +[![CocoaPods](https://img.shields.io/cocoapods/v/TZImagePickerController.svg?style=flat)](https://github.com/banchichen/TZImagePickerController) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + + + A clone of UIImagePickerController, support picking multiple photos、original photo、video, also allow preview photo and video, support iOS10+. + 一个支持多选、选原图和视频的图片选择器,同时有预览功能,支持iOS10+。 + +## 重要提示1:提issue前,请先对照Demo、常见问题自查!Demo正常说明你可以升级下新版试试。 + +## 重要提示2:3.8.8版本修复了iOS18下无照片和openURL失效的问题 + 关于iOS14模拟器的问题 + PHAuthorizationStatusLimited授权模式下,iOS14模拟器有bug,未授权照片无法显示,真机正常,暂可忽略:https://github.com/banchichen/TZImagePickerController/issues/1347 + + 关于升级iOS10和Xcdoe8的提示: + 在Xcode8环境下将项目运行在iOS10的设备/模拟器中,访问相册和相机需要额外配置info.plist文件。分别是Privacy - Photo Library Usage Description和Privacy - Camera Usage Description字段,详见Demo中info.plist中的设置。 + + 项目截图 1.Demo首页 2.照片列表页 3.照片预览页 4.视频预览页 + + + +## 一. Installation 安装 + +#### CocoaPods +> pod 'TZImagePickerController' # Full version with all features +> pod 'TZImagePickerController/Basic' # No location code + +#### Carthage +> github "banchichen/TZImagePickerController" + +#### 手动安装 +> 将TZImagePickerController文件夹拽入项目中,导入头文件:#import "TZImagePickerController.h" + +## 二. Example 例子 + + TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:self]; + + // You can get the photos by block, the same as by delegate. + // 你可以通过block或者代理,来得到用户选择的照片. + [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray *photos, NSArray *assets, BOOL isSelectOriginalPhoto) { + + }]; + [self presentViewController:imagePickerVc animated:YES completion:nil]; + +## 三. Requirements 要求 + iOS 10 or later. + 支持iOS10及以上系统。 + + TZImagePickerController uses Camera、Location、Microphone、Photo Library,you need add these properties to info.plist like Demo: + TZImagePickerController使用了相机、定位、麦克风、相册,请参考Demo添加下列属性到info.plist文件: + `Privacy - Camera Usage Description` + `Privacy - Location Usage Description` + `Privacy - Location When In Use Usage Description` + `Privacy - Microphone Usage Description` + `Privacy - Photo Library Usage Description` + `Prevent limited photos access alert` + +## 四. More 更多 + + If you find a bug, please create a issue. + More information please view code. + 如果你发现了bug,请提一个issue。 + 更多信息详见代码,也可查看我的博客: [我的博客](http://www.jianshu.com/p/1975411a31bb "半尺尘 - 简书") + + 关于issue: + 请尽可能详细地描述**系统版本**、**手机型号**、**库的版本**、**崩溃日志**和**复现步骤**,**请先更新到最新版再测试一下**,如果新版还存在再提~如果已有开启的类似issue,请直接在该issue下评论说出你的问题 + +## 五. FAQ 常见问题 + +**Q:pod search TZImagePickerController 搜索出来的不是最新版本** +A:需要在终端执行cd转换文件路径命令退回到Desktop,然后执行pod setup命令更新本地spec缓存(可能需要几分钟),然后再搜索就可以了 + +**Q:拍照后照片保存失败** +A:请参考issue481:https://github.com/banchichen/TZImagePickerController/issues/481 的信息排查,若还有问题请直接在issue内评论 + +**Q:photos数组图片不是原图,如何获取原图?** +A:请参考issue457的解释:https://github.com/banchichen/TZImagePickerController/issues/457 + +**Q:系统语言是中文/英文,界面上却有部分相册名字、返回按钮显示成了英文/中文?** +A:请参考 https://github.com/banchichen/TZImagePickerController/issues/443 和 https://github.com/banchichen/TZImagePickerController/issues/929 + +**Q:预览界面能否支持传入NSURL、UIImage对象?** +A:3.0.1版本已支持,需新接一个库:[TZImagePreviewController](https://github.com/banchichen/TZImagePreviewController),请参考里面的Demo使用。 + +**Q:设置可选视频的最大/最小时长?照片的最小/最大尺寸?不符合要求的不显示** +A:可以的,参照Demo的isAssetCanBeDisplayed方法实现。我会返回asset出来,显示与否你来决定,注意这个是一个同步方法,对于需要根据asset去异步获取的信息如视频的大小、视频是否存在iCloud里来过滤的,无法做到。如果真要这样做,相册打开速度会变慢,你需要改我源码。 +如果需要显示,选择时才提醒用户不可选,则实现isAssetCanBeSelected,用户选择时会调用它 + +**Q:预览页面出现了导航栏?** +A:https://github.com/banchichen/TZImagePickerController/issues/652 + +**Q:可否增加微信编辑图片的功能?** +A:考虑下,优先级低 + +**Q:是否有QQ/微信群/钉钉群?** +A:有「钉钉群:33192786」和「QQ群:859033147」,推荐加钉钉群,答疑响应更快 + +**Q:想提交一个Pull Request?** +A:请先加钉钉群(33192786)说下方案,和我确认下,避免同时改动同一处内容。**一个PR请只修复1个问题,变动内容越少越好**。 + +**Q:demo在真机上跑不起来?** +A:1、team选你自己的;2、bundleId也改成你自己的或改成一个不会和别人重复的。可参考[简书的这篇博客](https://www.jianshu.com/p/cbe59138fca6) + +**Q:3.6.4以上版本设置导航栏颜色无效?** +A:参考Demo里的代码,加上imagePickerVc.navigationBar.standardAppearance的相关设置 + +**Q:设置导航栏颜色无效?导航栏颜色总是白色?** +A:是否有集成WRNavigationBar?如有,参考其readme调一下它的wr_setBlackList,把TZImagePickerController相关的控制器放到黑名单里,使得不受WRNavigationBar的影响。如果没有集成,可在issues列表里搜一下看看类似的issue参考下,如实在没头绪,可加群提供个能复现该问题的demo,0~2天给你解决。最近发现WRNavigationBar的黑名单会有不生效的情况,临时解决方案大家可参考:[https://github.com/wangrui460/WRNavigationBar/issues/145](https://github.com/wangrui460/WRNavigationBar/issues/145) + +**Q:导航栏没了?** +A:是否有集成GKNavigationBarViewController?需要升级到2.0.4及以上版本,详见issue:[https://github.com/QuintGao/GKNavigationBarViewController/issues/7](https://github.com/QuintGao/GKNavigationBarViewController/issues/7)。 + +**Q:有的视频导出失败?** +A:升级到2.2.6及以上版本试试,发现是修正视频转向导致的,2.2.6开始默认不再主动修正。如需打开,可设置needFixComposition为YES,但有几率导致安卓拍的视频导出失败。此外也可参考这个issue:https://github.com/banchichen/TZImagePickerController/issues/1073 + +**Q:视频导出慢?** +A:视频导出分两步,第一步是通过PHAsset获取AVURLAsset,如是iCloud视频则涉及到网络请求,耗时容易不可控,第二步是通过AVURLAsset把视频保存到沙盒,耗时不算多。但第一步耗时不可控,你可以拷贝我源码出来拿到第一步的进度给用户一个进度提示... + +**Q:有的图片info里没有PHImageFileURLKey?** +A:不要去拿PHImageFileURLKey,没用的,只有通过Photos框架才能访问相册照片,光拿一个路径没用。 +如果需要通过路径上传照片,请先把UIImage保存到沙盒,**用沙盒路径**。 +如果你上传照片需要一个名字参数,请参考Demo**直接用照片名字**。 + +## 六. Release Notes 最近更新 + +**3.8.8 支持iOS18,修复openURL的失效问题** [#1686](https://github.com/banchichen/TZImagePickerController/issues/1686) +**3.8.5 新增隐私清单文件** [#1675](https://github.com/banchichen/TZImagePickerController/pull/1675) +**3.8.4 支持使用不带定位代码的版本** [#1606](https://github.com/banchichen/TZImagePickerController/pull/1606) +3.8.1 iOS14下可添加访问更多照片,详见PR内的评论 [#1526](https://github.com/banchichen/TZImagePickerController/pull/1526) +3.7.6 修复iOS15.2下初次授权相册权限时的长时间卡顿&白屏问题 [#1547](https://github.com/banchichen/TZImagePickerController/issues/1547) +**3.6.7 修复Xcode13&iOS15下导航栏颜色异常问题** +3.6.2 新增allowEditVideo,单选视频时支持裁剪 +3.6.0 修复iOS14下iCloud视频导出失败问题 +**3.5.2 适配iPhone12系列设备** +3.4.4 支持Dark Mode +3.4.2 适配iOS14,若干问题修复 +3.3.2 适配iOS13,若干问题修复 +3.2.1 新增裁剪用scaleAspectFillCrop属性,设置为YES后,照片尺寸小于裁剪框时会自动放大撑满 +3.2.0 加入用NSOperationQueue控制获取原图并发数降低内存的示例 +3.1.8 批量获取图片时加入队列控制,尝试优化大批量选择图片时CPU和内存占用过高的问题(仍然危险,maxImagesCount谨慎设置过大...) +3.1.5 相册内无照片时给出提示,修复快速滑动时内存一直增加的问题 +3.1.3 适配阿拉伯等语言下从右往左布局的特性 +3.0.8 新增gifImagePlayBlock允许使用FLAnimatedImage等替换内部的GIF播放方案 +3.0.7 适配iPhoneXR、XS、XS Max +3.0.6 优化保存照片、视频的方法 +3.0.1 新增对[TZImagePreviewController](https://github.com/banchichen/TZImagePreviewController)库的支持,允许预览UIImage、NSURL、PHAsset对象 +**3.0.0 去除iOS6和7的适配代码,更轻量,最低支持iOS8** +2.2.6 新增needFixComposition属性,默认为NO,不再主动修正视频转向,防止部分安卓拍的视频导出失败(**最后一个支持iOS6和7的版本**) +2.1.5 修复开启showSelectedIndex后照片列表页iCloud图片进度条紊乱的bug +2.1.4 新增多个页面和组件的样式自定义block,允许自定义绝大多数UI样式 +2.1.2 新增showPhotoCannotSelectLayer属性,当已选照片张数达到最大可选张数时,可像微信一样让其它照片显示一个提示不可选的浮层 +2.1.1 新增是否显示图片选中序号的属性,优化一些细节 +2.1.0.3 新增拍摄视频功能,优化一些细节 +2.0.0.6 优化自定义languageBundle的支持,加入使用示例 +2.0.0.5 优化性能,提高选择器打开速度,新增越南语支持 +2.0.0.2 新增繁体语言,可设置首选语言,国际化支持更强大;优化一些细节 +1.9.8 支持Carthage,优化一些细节 +1.9.6 优化视频预览和gif预览页toolbar在iPhoneX上的样式 +... +1.8.4 加入横竖屏适配;支持视频/gif多选;支持视频和照片一起选 +1.8.1 新增2个代理方法,支持由上层来决定相册/照片的显示与否 +... +1.7.7 支持GIF图片的播放和选择 +1.7.6 支持对共享相册和同步相册的显示 +1.7.5 允许不进入预览页面直接选择照片 +1.7.4 支持单选模式下裁剪照片,支持任意矩形和圆形裁剪框 +1.7.3 优化iCloud照片的显示与选择 +... +1.5.0 可把拍照按钮放在外面;可自定义照片排序方式;Demo页的UI大改版,新增若干开关; +... +1.4.5 性能大幅提升(性能测试截图请去博客查看);可在照片列表页拍照;Demo大幅优化; +... + +## 七. Common links 常用链接 +1. Json diff online: https://www.jsondiffonline.com/ + diff --git a/TZImagePickerController.podspec b/TZImagePickerController.podspec new file mode 100644 index 0000000..2a64a2b --- /dev/null +++ b/TZImagePickerController.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = "TZImagePickerController" + s.version = "3.8.8" + s.summary = "A clone of UIImagePickerController, support picking multiple photos、original photo and video" + s.homepage = "https://github.com/banchichen/TZImagePickerController" + s.license = "MIT" + s.author = { "banchichen" => "tanzhenios@foxmail.com" } + s.platform = :ios + s.ios.deployment_target = "10.0" + s.source = { :git => "https://github.com/banchichen/TZImagePickerController.git", :tag => "3.8.8" } + s.requires_arc = true + + s.subspec 'Basic' do |b| + b.resources = "TZImagePickerController/TZImagePickerController/*.{png,bundle}" + b.source_files = "TZImagePickerController/TZImagePickerController/*.{h,m}" + end + + s.subspec 'Location' do |l| + l.source_files = 'TZImagePickerController/Location/*.{h,m}' + end + + s.frameworks = "Photos", "PhotosUI" +end diff --git a/TZImagePickerController.xcodeproj/project.pbxproj b/TZImagePickerController.xcodeproj/project.pbxproj new file mode 100644 index 0000000..707f891 --- /dev/null +++ b/TZImagePickerController.xcodeproj/project.pbxproj @@ -0,0 +1,1084 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 441B78D32BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 441B78D22BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy */; }; + 441B78D42BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 441B78D22BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy */; }; + 441B78D52BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 441B78D22BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy */; }; + 441B78D62BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 441B78D22BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy */; }; + 570A348C26D7275C000EEF2E /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570A348B26D7275C000EEF2E /* Photos.framework */; }; + 570A348E26D72762000EEF2E /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570A348D26D72762000EEF2E /* PhotosUI.framework */; }; + 570A349026D72768000EEF2E /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570A348F26D72768000EEF2E /* PhotosUI.framework */; }; + 57DD378A26D61592005090FF /* TZAuthLimitedFooterTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 57DD378926D61592005090FF /* TZAuthLimitedFooterTipView.m */; }; + 57DD378E26D619C9005090FF /* TZAuthLimitedFooterTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 57DD378926D61592005090FF /* TZAuthLimitedFooterTipView.m */; }; + 6D32B9BD1CD83640005CE1E0 /* LxGridViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */; }; + 6D4608311DFFC60D004FB009 /* TZGifPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D4608301DFFC60D004FB009 /* TZGifPhotoPreviewController.m */; }; + 6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */; }; + 6DC358661CC8BAFD00898D29 /* TZImagePickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */; }; + 6DC84D0A1DF5358500A107A9 /* TZImageCropManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC84D091DF5358500A107A9 /* TZImageCropManager.m */; }; + 6DD0502B1DF659ED0057C78D /* TZProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0502A1DF659ED0057C78D /* TZProgressView.m */; }; + 90020E1320F8840800D3AB10 /* TZImagePickerController.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 90020E1220F8840800D3AB10 /* TZImagePickerController.podspec */; }; + 90020E1520F8840F00D3AB10 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 90020E1420F8840E00D3AB10 /* README.md */; }; + 9005E2B3257A462E002A8682 /* UIView+TZLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 9005E2B1257A462E002A8682 /* UIView+TZLayout.m */; }; + 9005E2B4257A462E002A8682 /* UIView+TZLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 9005E2B1257A462E002A8682 /* UIView+TZLayout.m */; }; + 9005E2B5257A462E002A8682 /* UIView+TZLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9005E2B2257A462E002A8682 /* UIView+TZLayout.h */; }; + 900E65811C2BB8D5003D9A9E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65801C2BB8D5003D9A9E /* main.m */; }; + 900E65841C2BB8D5003D9A9E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65831C2BB8D5003D9A9E /* AppDelegate.m */; }; + 900E65871C2BB8D5003D9A9E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65861C2BB8D5003D9A9E /* ViewController.m */; }; + 900E658A1C2BB8D5003D9A9E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 900E65881C2BB8D5003D9A9E /* Main.storyboard */; }; + 900E658C1C2BB8D5003D9A9E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 900E658B1C2BB8D5003D9A9E /* Assets.xcassets */; }; + 900E658F1C2BB8D5003D9A9E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 900E658D1C2BB8D5003D9A9E /* LaunchScreen.storyboard */; }; + 900E659A1C2BB8D5003D9A9E /* TZImagePickerControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65991C2BB8D5003D9A9E /* TZImagePickerControllerTests.m */; }; + 900E65A51C2BB8D5003D9A9E /* TZImagePickerControllerUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65A41C2BB8D5003D9A9E /* TZImagePickerControllerUITests.m */; }; + 900EEFF81C2BBF9500EA709B /* TZImagePickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EEFF71C2BBF9500EA709B /* TZImagePickerController.m */; }; + 900EEFFE1C2BD58B00EA709B /* TZPhotoPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EEFFD1C2BD58B00EA709B /* TZPhotoPickerController.m */; }; + 900EF0021C2BD7E400EA709B /* TZAssetCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0001C2BD7E400EA709B /* TZAssetCell.m */; }; + 900EF00F1C2C0B1100EA709B /* TZAssetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF00E1C2C0B1100EA709B /* TZAssetModel.m */; }; + 900EF0121C2C107400EA709B /* TZPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0111C2C107400EA709B /* TZPhotoPreviewController.m */; }; + 900EF0161C2C134900EA709B /* TZPhotoPreviewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */; }; + 9019FD8D21EC25D7009ADEAE /* TZImageUploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9019FD8C21EC25D7009ADEAE /* TZImageUploadOperation.m */; }; + 901CC3FA21CB757500C55443 /* TZImageRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 901CC3F821CB757500C55443 /* TZImageRequestOperation.h */; }; + 901CC3FB21CB757500C55443 /* TZImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 901CC3F921CB757500C55443 /* TZImageRequestOperation.m */; }; + 901CC3FC21CB758500C55443 /* TZImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 901CC3F921CB757500C55443 /* TZImageRequestOperation.m */; }; + 901F2295215CABD600F604ED /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 901F2291215CABD600F604ED /* FLAnimatedImage.m */; }; + 901F2296215CABD600F604ED /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 901F2293215CABD600F604ED /* FLAnimatedImageView.m */; }; + 9038D5911C3974F0007DE549 /* TZTestCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9038D5901C3974F0007DE549 /* TZTestCell.m */; }; + 903996931F447604005E77C2 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 903996921F447604005E77C2 /* Photos.framework */; }; + 908D11582887ED8000DD212E /* TZLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 908D11562887ED7F00DD212E /* TZLocationManager.m */; }; + 908D11592887ED8000DD212E /* TZLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 908D11562887ED7F00DD212E /* TZLocationManager.m */; }; + 908D115A2887ED8000DD212E /* TZLocationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 908D11572887ED7F00DD212E /* TZLocationManager.h */; }; + 90A74B85203287C200D84C2A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 90A74B83203287C200D84C2A /* Localizable.strings */; }; + 90CE84AE1C3A89EF003D0779 /* TZImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 90CE84AD1C3A89EF003D0779 /* TZImageManager.m */; }; + 9F763A4A1FA071D000D9E526 /* TZImagePickerController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9F763A421FA071CF00D9E526 /* TZImagePickerController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9F763A501FA072E500D9E526 /* TZImagePickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EEFF71C2BBF9500EA709B /* TZImagePickerController.m */; }; + 9F763A521FA072E500D9E526 /* TZPhotoPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EEFFD1C2BD58B00EA709B /* TZPhotoPickerController.m */; }; + 9F763A541FA072E500D9E526 /* TZAssetCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0001C2BD7E400EA709B /* TZAssetCell.m */; }; + 9F763A561FA072E500D9E526 /* TZAssetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF00E1C2C0B1100EA709B /* TZAssetModel.m */; }; + 9F763A581FA072E500D9E526 /* TZPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0111C2C107400EA709B /* TZPhotoPreviewController.m */; }; + 9F763A5A1FA072E500D9E526 /* TZPhotoPreviewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */; }; + 9F763A5C1FA072E500D9E526 /* TZVideoPlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90CE84B61C3BABB6003D0779 /* TZVideoPlayerController.m */; }; + 9F763A5E1FA072E500D9E526 /* TZGifPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D4608301DFFC60D004FB009 /* TZGifPhotoPreviewController.m */; }; + 9F763A601FA072E500D9E526 /* TZProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0502A1DF659ED0057C78D /* TZProgressView.m */; }; + 9F763A621FA072E500D9E526 /* TZImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 90CE84AD1C3A89EF003D0779 /* TZImageManager.m */; }; + 9F763A641FA072E500D9E526 /* TZImageCropManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC84D091DF5358500A107A9 /* TZImageCropManager.m */; }; + 9F763A6A1FA072E500D9E526 /* NSBundle+TZImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */; }; + 9F763A6B1FA0731E00D9E526 /* TZImagePickerController.h in Headers */ = {isa = PBXBuildFile; fileRef = 900EEFF61C2BBF9500EA709B /* TZImagePickerController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A6C1FA0733100D9E526 /* TZAssetModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 900EF00D1C2C0B1100EA709B /* TZAssetModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A6D1FA0733700D9E526 /* NSBundle+TZImagePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A6E1FA0734800D9E526 /* TZImagePickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */; }; + 9F763A6F1FA0741D00D9E526 /* TZPhotoPickerController.h in Headers */ = {isa = PBXBuildFile; fileRef = 900EEFFC1C2BD58B00EA709B /* TZPhotoPickerController.h */; }; + 9F763A701FA0741D00D9E526 /* TZAssetCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 900EEFFF1C2BD7E400EA709B /* TZAssetCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A711FA0741D00D9E526 /* TZPhotoPreviewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 900EF0101C2C107400EA709B /* TZPhotoPreviewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A721FA0741D00D9E526 /* TZPhotoPreviewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 900EF0131C2C134800EA709B /* TZPhotoPreviewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A731FA0741D00D9E526 /* TZVideoPlayerController.h in Headers */ = {isa = PBXBuildFile; fileRef = 90CE84B51C3BABB6003D0779 /* TZVideoPlayerController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A741FA0741D00D9E526 /* TZGifPhotoPreviewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D46082F1DFFC60D004FB009 /* TZGifPhotoPreviewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A751FA0741D00D9E526 /* TZProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DD050291DF659ED0057C78D /* TZProgressView.h */; }; + 9F763A761FA0741D00D9E526 /* TZImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 90CE84AC1C3A89EF003D0779 /* TZImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F763A771FA0741D00D9E526 /* TZImageCropManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC84D081DF5358500A107A9 /* TZImageCropManager.h */; }; + B606A9C4265FD53200F5493E /* TZVideoCropController.m in Sources */ = {isa = PBXBuildFile; fileRef = B606A9C2265FD53200F5493E /* TZVideoCropController.m */; }; + B606A9CE265FD5F700F5493E /* TZVideoPlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90CE84B61C3BABB6003D0779 /* TZVideoPlayerController.m */; }; + B662C36F2662914D006A672A /* TZVideoEditedPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B662C36E2662914D006A672A /* TZVideoEditedPreviewController.m */; }; + B662C37326629179006A672A /* TZVideoEditedPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B662C36E2662914D006A672A /* TZVideoEditedPreviewController.m */; }; + B6977B0A265FDB280028BA31 /* TZVideoCropController.m in Sources */ = {isa = PBXBuildFile; fileRef = B606A9C2265FD53200F5493E /* TZVideoCropController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 900E65961C2BB8D5003D9A9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 900E65741C2BB8D5003D9A9E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 900E657B1C2BB8D5003D9A9E; + remoteInfo = TZImagePickerController; + }; + 900E65A11C2BB8D5003D9A9E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 900E65741C2BB8D5003D9A9E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 900E657B1C2BB8D5003D9A9E; + remoteInfo = TZImagePickerController; + }; + 9F763A471FA071D000D9E526 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 900E65741C2BB8D5003D9A9E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9F763A411FA071CF00D9E526; + remoteInfo = TZImagePickerControllerFramework; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9F763A4E1FA071D000D9E526 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 9F763A4A1FA071D000D9E526 /* TZImagePickerController.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 441B78D22BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 570A348B26D7275C000EEF2E /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; }; + 570A348D26D72762000EEF2E /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/iOSSupport/System/Library/Frameworks/PhotosUI.framework; sourceTree = DEVELOPER_DIR; }; + 570A348F26D72768000EEF2E /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = System/Library/Frameworks/PhotosUI.framework; sourceTree = SDKROOT; }; + 57DD378826D61592005090FF /* TZAuthLimitedFooterTipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZAuthLimitedFooterTipView.h; sourceTree = ""; }; + 57DD378926D61592005090FF /* TZAuthLimitedFooterTipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZAuthLimitedFooterTipView.m; sourceTree = ""; }; + 6D12FC191D66B71E00182C44 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + 6D12FC1A1D66B71E00182C44 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; + 6D32B9BB1CD83640005CE1E0 /* LxGridViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LxGridViewFlowLayout.h; sourceTree = ""; }; + 6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LxGridViewFlowLayout.m; sourceTree = ""; }; + 6D46082F1DFFC60D004FB009 /* TZGifPhotoPreviewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZGifPhotoPreviewController.h; sourceTree = ""; }; + 6D4608301DFFC60D004FB009 /* TZGifPhotoPreviewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZGifPhotoPreviewController.m; sourceTree = ""; }; + 6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+TZImagePicker.h"; sourceTree = ""; }; + 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+TZImagePicker.m"; sourceTree = ""; }; + 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TZImagePickerController.bundle; sourceTree = ""; }; + 6DC84D081DF5358500A107A9 /* TZImageCropManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImageCropManager.h; sourceTree = ""; }; + 6DC84D091DF5358500A107A9 /* TZImageCropManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImageCropManager.m; sourceTree = ""; }; + 6DD050291DF659ED0057C78D /* TZProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZProgressView.h; sourceTree = ""; }; + 6DD0502A1DF659ED0057C78D /* TZProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZProgressView.m; sourceTree = ""; }; + 90020E1220F8840800D3AB10 /* TZImagePickerController.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TZImagePickerController.podspec; sourceTree = SOURCE_ROOT; }; + 90020E1420F8840E00D3AB10 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; + 9005E2B1257A462E002A8682 /* UIView+TZLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+TZLayout.m"; sourceTree = ""; }; + 9005E2B2257A462E002A8682 /* UIView+TZLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+TZLayout.h"; sourceTree = ""; }; + 900E657C1C2BB8D5003D9A9E /* TZImagePickerController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TZImagePickerController.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 900E65801C2BB8D5003D9A9E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 900E65821C2BB8D5003D9A9E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 900E65831C2BB8D5003D9A9E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 900E65851C2BB8D5003D9A9E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 900E65861C2BB8D5003D9A9E /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 900E65891C2BB8D5003D9A9E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 900E658B1C2BB8D5003D9A9E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 900E658E1C2BB8D5003D9A9E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 900E65901C2BB8D5003D9A9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 900E65951C2BB8D5003D9A9E /* TZImagePickerControllerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TZImagePickerControllerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 900E65991C2BB8D5003D9A9E /* TZImagePickerControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TZImagePickerControllerTests.m; sourceTree = ""; }; + 900E659B1C2BB8D5003D9A9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 900E65A01C2BB8D5003D9A9E /* TZImagePickerControllerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TZImagePickerControllerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 900E65A41C2BB8D5003D9A9E /* TZImagePickerControllerUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TZImagePickerControllerUITests.m; sourceTree = ""; }; + 900E65A61C2BB8D5003D9A9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 900EEFF61C2BBF9500EA709B /* TZImagePickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImagePickerController.h; sourceTree = ""; }; + 900EEFF71C2BBF9500EA709B /* TZImagePickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImagePickerController.m; sourceTree = ""; }; + 900EEFFC1C2BD58B00EA709B /* TZPhotoPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPickerController.h; sourceTree = ""; }; + 900EEFFD1C2BD58B00EA709B /* TZPhotoPickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPickerController.m; sourceTree = ""; }; + 900EEFFF1C2BD7E400EA709B /* TZAssetCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZAssetCell.h; sourceTree = ""; }; + 900EF0001C2BD7E400EA709B /* TZAssetCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZAssetCell.m; sourceTree = ""; }; + 900EF00D1C2C0B1100EA709B /* TZAssetModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZAssetModel.h; sourceTree = ""; }; + 900EF00E1C2C0B1100EA709B /* TZAssetModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZAssetModel.m; sourceTree = ""; }; + 900EF0101C2C107400EA709B /* TZPhotoPreviewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPreviewController.h; sourceTree = ""; }; + 900EF0111C2C107400EA709B /* TZPhotoPreviewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPreviewController.m; sourceTree = ""; }; + 900EF0131C2C134800EA709B /* TZPhotoPreviewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPreviewCell.h; sourceTree = ""; }; + 900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPreviewCell.m; sourceTree = ""; }; + 9019FD8B21EC25D7009ADEAE /* TZImageUploadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImageUploadOperation.h; sourceTree = ""; }; + 9019FD8C21EC25D7009ADEAE /* TZImageUploadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImageUploadOperation.m; sourceTree = ""; }; + 901CC3F821CB757500C55443 /* TZImageRequestOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TZImageRequestOperation.h; sourceTree = ""; }; + 901CC3F921CB757500C55443 /* TZImageRequestOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TZImageRequestOperation.m; sourceTree = ""; }; + 901F2290215CABD600F604ED /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = ""; }; + 901F2291215CABD600F604ED /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImage.m; sourceTree = ""; }; + 901F2292215CABD600F604ED /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImageView.h; sourceTree = ""; }; + 901F2293215CABD600F604ED /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = ""; }; + 9038D58F1C3974F0007DE549 /* TZTestCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZTestCell.h; sourceTree = ""; }; + 9038D5901C3974F0007DE549 /* TZTestCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZTestCell.m; sourceTree = ""; }; + 903996921F447604005E77C2 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; + 903996941F447609005E77C2 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; + 908D11562887ED7F00DD212E /* TZLocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZLocationManager.m; sourceTree = ""; }; + 908D11572887ED7F00DD212E /* TZLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZLocationManager.h; sourceTree = ""; }; + 909DBC95216B981B00926570 /* ar-001 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ar-001"; path = "ar-001.lproj/Main.strings"; sourceTree = ""; }; + 909DBC96216B981B00926570 /* ar-001 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ar-001"; path = "ar-001.lproj/LaunchScreen.strings"; sourceTree = ""; }; + 909DBC97216B981B00926570 /* ar-001 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ar-001"; path = "../ar-001.lproj/Localizable.strings"; sourceTree = ""; }; + 90A74B84203287C200D84C2A /* tz-ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "tz-ru"; path = Localizable.strings; sourceTree = ""; }; + 90CE84AC1C3A89EF003D0779 /* TZImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImageManager.h; sourceTree = ""; }; + 90CE84AD1C3A89EF003D0779 /* TZImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImageManager.m; sourceTree = ""; }; + 90CE84B51C3BABB6003D0779 /* TZVideoPlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZVideoPlayerController.h; sourceTree = ""; }; + 90CE84B61C3BABB6003D0779 /* TZVideoPlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZVideoPlayerController.m; sourceTree = ""; }; + 9F763A421FA071CF00D9E526 /* TZImagePickerController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TZImagePickerController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9F763A451FA071D000D9E526 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B606A9C2265FD53200F5493E /* TZVideoCropController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZVideoCropController.m; sourceTree = ""; }; + B606A9C3265FD53200F5493E /* TZVideoCropController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZVideoCropController.h; sourceTree = ""; }; + B662C36D2662914D006A672A /* TZVideoEditedPreviewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TZVideoEditedPreviewController.h; sourceTree = ""; }; + B662C36E2662914D006A672A /* TZVideoEditedPreviewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TZVideoEditedPreviewController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 900E65791C2BB8D5003D9A9E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 570A349026D72768000EEF2E /* PhotosUI.framework in Frameworks */, + 903996931F447604005E77C2 /* Photos.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 900E65921C2BB8D5003D9A9E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 900E659D1C2BB8D5003D9A9E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9F763A3E1FA071CF00D9E526 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 570A348E26D72762000EEF2E /* PhotosUI.framework in Frameworks */, + 570A348C26D7275C000EEF2E /* Photos.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5B7A0D4F288691E7002B2603 /* Location */ = { + isa = PBXGroup; + children = ( + 908D11572887ED7F00DD212E /* TZLocationManager.h */, + 908D11562887ED7F00DD212E /* TZLocationManager.m */, + ); + path = Location; + sourceTree = ""; + }; + 6DC358641CC8BAE300898D29 /* Resources */ = { + isa = PBXGroup; + children = ( + 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */, + ); + name = Resources; + sourceTree = ""; + }; + 900E65731C2BB8D5003D9A9E = { + isa = PBXGroup; + children = ( + 900E657E1C2BB8D5003D9A9E /* TZImagePickerController */, + 900E65981C2BB8D5003D9A9E /* TZImagePickerControllerTests */, + 900E65A31C2BB8D5003D9A9E /* TZImagePickerControllerUITests */, + 9F763A431FA071D000D9E526 /* TZImagePickerControllerFramework */, + 900E657D1C2BB8D5003D9A9E /* Products */, + 903996911F447603005E77C2 /* Frameworks */, + ); + sourceTree = ""; + }; + 900E657D1C2BB8D5003D9A9E /* Products */ = { + isa = PBXGroup; + children = ( + 900E657C1C2BB8D5003D9A9E /* TZImagePickerController.app */, + 900E65951C2BB8D5003D9A9E /* TZImagePickerControllerTests.xctest */, + 900E65A01C2BB8D5003D9A9E /* TZImagePickerControllerUITests.xctest */, + 9F763A421FA071CF00D9E526 /* TZImagePickerController.framework */, + ); + name = Products; + sourceTree = ""; + }; + 900E657E1C2BB8D5003D9A9E /* TZImagePickerController */ = { + isa = PBXGroup; + children = ( + 5B7A0D4F288691E7002B2603 /* Location */, + 901F228F215CABD600F604ED /* FLAnimatedImage */, + 900EEFF51C2BBF7600EA709B /* TZImagePickerController */, + 900E65821C2BB8D5003D9A9E /* AppDelegate.h */, + 900E65831C2BB8D5003D9A9E /* AppDelegate.m */, + 900E65851C2BB8D5003D9A9E /* ViewController.h */, + 900E65861C2BB8D5003D9A9E /* ViewController.m */, + 9019FD8B21EC25D7009ADEAE /* TZImageUploadOperation.h */, + 9019FD8C21EC25D7009ADEAE /* TZImageUploadOperation.m */, + 6D32B9BB1CD83640005CE1E0 /* LxGridViewFlowLayout.h */, + 6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */, + 9038D58F1C3974F0007DE549 /* TZTestCell.h */, + 9038D5901C3974F0007DE549 /* TZTestCell.m */, + 90020E1420F8840E00D3AB10 /* README.md */, + 90020E1220F8840800D3AB10 /* TZImagePickerController.podspec */, + 900E65881C2BB8D5003D9A9E /* Main.storyboard */, + 900E658B1C2BB8D5003D9A9E /* Assets.xcassets */, + 900E658D1C2BB8D5003D9A9E /* LaunchScreen.storyboard */, + 900E65901C2BB8D5003D9A9E /* Info.plist */, + 900E657F1C2BB8D5003D9A9E /* Supporting Files */, + ); + path = TZImagePickerController; + sourceTree = ""; + }; + 900E657F1C2BB8D5003D9A9E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 90A74B82203287C200D84C2A /* tz-ru.lproj */, + 900E65801C2BB8D5003D9A9E /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 900E65981C2BB8D5003D9A9E /* TZImagePickerControllerTests */ = { + isa = PBXGroup; + children = ( + 900E65991C2BB8D5003D9A9E /* TZImagePickerControllerTests.m */, + 900E659B1C2BB8D5003D9A9E /* Info.plist */, + ); + path = TZImagePickerControllerTests; + sourceTree = ""; + }; + 900E65A31C2BB8D5003D9A9E /* TZImagePickerControllerUITests */ = { + isa = PBXGroup; + children = ( + 900E65A41C2BB8D5003D9A9E /* TZImagePickerControllerUITests.m */, + 900E65A61C2BB8D5003D9A9E /* Info.plist */, + ); + path = TZImagePickerControllerUITests; + sourceTree = ""; + }; + 900EEFF51C2BBF7600EA709B /* TZImagePickerController */ = { + isa = PBXGroup; + children = ( + 900EEFF61C2BBF9500EA709B /* TZImagePickerController.h */, + 900EEFF71C2BBF9500EA709B /* TZImagePickerController.m */, + 900EEFFC1C2BD58B00EA709B /* TZPhotoPickerController.h */, + 900EEFFD1C2BD58B00EA709B /* TZPhotoPickerController.m */, + 900EEFFF1C2BD7E400EA709B /* TZAssetCell.h */, + 900EF0001C2BD7E400EA709B /* TZAssetCell.m */, + 900EF00D1C2C0B1100EA709B /* TZAssetModel.h */, + 900EF00E1C2C0B1100EA709B /* TZAssetModel.m */, + 900EF0101C2C107400EA709B /* TZPhotoPreviewController.h */, + 900EF0111C2C107400EA709B /* TZPhotoPreviewController.m */, + 900EF0131C2C134800EA709B /* TZPhotoPreviewCell.h */, + 900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */, + 90CE84B51C3BABB6003D0779 /* TZVideoPlayerController.h */, + 90CE84B61C3BABB6003D0779 /* TZVideoPlayerController.m */, + 6D46082F1DFFC60D004FB009 /* TZGifPhotoPreviewController.h */, + 6D4608301DFFC60D004FB009 /* TZGifPhotoPreviewController.m */, + B606A9C3265FD53200F5493E /* TZVideoCropController.h */, + B606A9C2265FD53200F5493E /* TZVideoCropController.m */, + B662C36D2662914D006A672A /* TZVideoEditedPreviewController.h */, + B662C36E2662914D006A672A /* TZVideoEditedPreviewController.m */, + 6DD050291DF659ED0057C78D /* TZProgressView.h */, + 6DD0502A1DF659ED0057C78D /* TZProgressView.m */, + 57DD378826D61592005090FF /* TZAuthLimitedFooterTipView.h */, + 57DD378926D61592005090FF /* TZAuthLimitedFooterTipView.m */, + 90CE84AC1C3A89EF003D0779 /* TZImageManager.h */, + 90CE84AD1C3A89EF003D0779 /* TZImageManager.m */, + 901CC3F821CB757500C55443 /* TZImageRequestOperation.h */, + 901CC3F921CB757500C55443 /* TZImageRequestOperation.m */, + 6DC84D081DF5358500A107A9 /* TZImageCropManager.h */, + 6DC84D091DF5358500A107A9 /* TZImageCropManager.m */, + 9005E2B2257A462E002A8682 /* UIView+TZLayout.h */, + 9005E2B1257A462E002A8682 /* UIView+TZLayout.m */, + 6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */, + 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */, + 6DC358641CC8BAE300898D29 /* Resources */, + ); + path = TZImagePickerController; + sourceTree = ""; + }; + 901F228F215CABD600F604ED /* FLAnimatedImage */ = { + isa = PBXGroup; + children = ( + 901F2290215CABD600F604ED /* FLAnimatedImage.h */, + 901F2291215CABD600F604ED /* FLAnimatedImage.m */, + 901F2292215CABD600F604ED /* FLAnimatedImageView.h */, + 901F2293215CABD600F604ED /* FLAnimatedImageView.m */, + ); + path = FLAnimatedImage; + sourceTree = ""; + }; + 903996911F447603005E77C2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 570A348D26D72762000EEF2E /* PhotosUI.framework */, + 570A348F26D72768000EEF2E /* PhotosUI.framework */, + 570A348B26D7275C000EEF2E /* Photos.framework */, + 903996941F447609005E77C2 /* AssetsLibrary.framework */, + 903996921F447604005E77C2 /* Photos.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 90A74B82203287C200D84C2A /* tz-ru.lproj */ = { + isa = PBXGroup; + children = ( + 90A74B83203287C200D84C2A /* Localizable.strings */, + ); + path = "tz-ru.lproj"; + sourceTree = ""; + }; + 9F763A431FA071D000D9E526 /* TZImagePickerControllerFramework */ = { + isa = PBXGroup; + children = ( + 9F763A451FA071D000D9E526 /* Info.plist */, + 441B78D22BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy */, + ); + path = TZImagePickerControllerFramework; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 9F763A3F1FA071CF00D9E526 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 901CC3FA21CB757500C55443 /* TZImageRequestOperation.h in Headers */, + 9F763A6B1FA0731E00D9E526 /* TZImagePickerController.h in Headers */, + 9F763A6D1FA0733700D9E526 /* NSBundle+TZImagePicker.h in Headers */, + 9F763A6C1FA0733100D9E526 /* TZAssetModel.h in Headers */, + 9F763A731FA0741D00D9E526 /* TZVideoPlayerController.h in Headers */, + 9F763A741FA0741D00D9E526 /* TZGifPhotoPreviewController.h in Headers */, + 9005E2B5257A462E002A8682 /* UIView+TZLayout.h in Headers */, + 9F763A761FA0741D00D9E526 /* TZImageManager.h in Headers */, + 908D115A2887ED8000DD212E /* TZLocationManager.h in Headers */, + 9F763A711FA0741D00D9E526 /* TZPhotoPreviewController.h in Headers */, + 9F763A721FA0741D00D9E526 /* TZPhotoPreviewCell.h in Headers */, + 9F763A701FA0741D00D9E526 /* TZAssetCell.h in Headers */, + 9F763A6F1FA0741D00D9E526 /* TZPhotoPickerController.h in Headers */, + 9F763A751FA0741D00D9E526 /* TZProgressView.h in Headers */, + 9F763A771FA0741D00D9E526 /* TZImageCropManager.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 900E657B1C2BB8D5003D9A9E /* TZImagePickerController */ = { + isa = PBXNativeTarget; + buildConfigurationList = 900E65A91C2BB8D5003D9A9E /* Build configuration list for PBXNativeTarget "TZImagePickerController" */; + buildPhases = ( + 900E65781C2BB8D5003D9A9E /* Sources */, + 900E65791C2BB8D5003D9A9E /* Frameworks */, + 900E657A1C2BB8D5003D9A9E /* Resources */, + 9F763A4E1FA071D000D9E526 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 9F763A481FA071D000D9E526 /* PBXTargetDependency */, + ); + name = TZImagePickerController; + productName = TZImagePickerController; + productReference = 900E657C1C2BB8D5003D9A9E /* TZImagePickerController.app */; + productType = "com.apple.product-type.application"; + }; + 900E65941C2BB8D5003D9A9E /* TZImagePickerControllerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 900E65AC1C2BB8D5003D9A9E /* Build configuration list for PBXNativeTarget "TZImagePickerControllerTests" */; + buildPhases = ( + 900E65911C2BB8D5003D9A9E /* Sources */, + 900E65921C2BB8D5003D9A9E /* Frameworks */, + 900E65931C2BB8D5003D9A9E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 900E65971C2BB8D5003D9A9E /* PBXTargetDependency */, + ); + name = TZImagePickerControllerTests; + productName = TZImagePickerControllerTests; + productReference = 900E65951C2BB8D5003D9A9E /* TZImagePickerControllerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 900E659F1C2BB8D5003D9A9E /* TZImagePickerControllerUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 900E65AF1C2BB8D5003D9A9E /* Build configuration list for PBXNativeTarget "TZImagePickerControllerUITests" */; + buildPhases = ( + 900E659C1C2BB8D5003D9A9E /* Sources */, + 900E659D1C2BB8D5003D9A9E /* Frameworks */, + 900E659E1C2BB8D5003D9A9E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 900E65A21C2BB8D5003D9A9E /* PBXTargetDependency */, + ); + name = TZImagePickerControllerUITests; + productName = TZImagePickerControllerUITests; + productReference = 900E65A01C2BB8D5003D9A9E /* TZImagePickerControllerUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + 9F763A411FA071CF00D9E526 /* TZImagePickerControllerFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9F763A4D1FA071D000D9E526 /* Build configuration list for PBXNativeTarget "TZImagePickerControllerFramework" */; + buildPhases = ( + 9F763A3D1FA071CF00D9E526 /* Sources */, + 9F763A3E1FA071CF00D9E526 /* Frameworks */, + 9F763A3F1FA071CF00D9E526 /* Headers */, + 9F763A401FA071CF00D9E526 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TZImagePickerControllerFramework; + productName = TZImagePickerControllerFramework; + productReference = 9F763A421FA071CF00D9E526 /* TZImagePickerController.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 900E65741C2BB8D5003D9A9E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "谭真"; + TargetAttributes = { + 900E657B1C2BB8D5003D9A9E = { + CreatedOnToolsVersion = 7.2; + DevelopmentTeam = FK3N68H5LP; + ProvisioningStyle = Automatic; + }; + 900E65941C2BB8D5003D9A9E = { + CreatedOnToolsVersion = 7.2; + TestTargetID = 900E657B1C2BB8D5003D9A9E; + }; + 900E659F1C2BB8D5003D9A9E = { + CreatedOnToolsVersion = 7.2; + TestTargetID = 900E657B1C2BB8D5003D9A9E; + }; + 9F763A411FA071CF00D9E526 = { + CreatedOnToolsVersion = 9.0.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 900E65771C2BB8D5003D9A9E /* Build configuration list for PBXProject "TZImagePickerController" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + "zh-Hans", + "tz-ru", + "ar-001", + ); + mainGroup = 900E65731C2BB8D5003D9A9E; + productRefGroup = 900E657D1C2BB8D5003D9A9E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 900E657B1C2BB8D5003D9A9E /* TZImagePickerController */, + 900E65941C2BB8D5003D9A9E /* TZImagePickerControllerTests */, + 900E659F1C2BB8D5003D9A9E /* TZImagePickerControllerUITests */, + 9F763A411FA071CF00D9E526 /* TZImagePickerControllerFramework */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 900E657A1C2BB8D5003D9A9E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 90020E1320F8840800D3AB10 /* TZImagePickerController.podspec in Resources */, + 90A74B85203287C200D84C2A /* Localizable.strings in Resources */, + 900E658F1C2BB8D5003D9A9E /* LaunchScreen.storyboard in Resources */, + 90020E1520F8840F00D3AB10 /* README.md in Resources */, + 6DC358661CC8BAFD00898D29 /* TZImagePickerController.bundle in Resources */, + 900E658C1C2BB8D5003D9A9E /* Assets.xcassets in Resources */, + 441B78D32BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */, + 900E658A1C2BB8D5003D9A9E /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 900E65931C2BB8D5003D9A9E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 441B78D42BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 900E659E1C2BB8D5003D9A9E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 441B78D52BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9F763A401FA071CF00D9E526 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 441B78D62BBD7E0300A1CB09 /* PrivacyInfo.xcprivacy in Resources */, + 9F763A6E1FA0734800D9E526 /* TZImagePickerController.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 900E65781C2BB8D5003D9A9E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B606A9CE265FD5F700F5493E /* TZVideoPlayerController.m in Sources */, + B662C36F2662914D006A672A /* TZVideoEditedPreviewController.m in Sources */, + 9038D5911C3974F0007DE549 /* TZTestCell.m in Sources */, + 900EF00F1C2C0B1100EA709B /* TZAssetModel.m in Sources */, + 900EEFFE1C2BD58B00EA709B /* TZPhotoPickerController.m in Sources */, + 900EF0021C2BD7E400EA709B /* TZAssetCell.m in Sources */, + 6DD0502B1DF659ED0057C78D /* TZProgressView.m in Sources */, + 6D32B9BD1CD83640005CE1E0 /* LxGridViewFlowLayout.m in Sources */, + 57DD378A26D61592005090FF /* TZAuthLimitedFooterTipView.m in Sources */, + 6D4608311DFFC60D004FB009 /* TZGifPhotoPreviewController.m in Sources */, + 900EF0161C2C134900EA709B /* TZPhotoPreviewCell.m in Sources */, + 900E65871C2BB8D5003D9A9E /* ViewController.m in Sources */, + 90CE84AE1C3A89EF003D0779 /* TZImageManager.m in Sources */, + 901F2295215CABD600F604ED /* FLAnimatedImage.m in Sources */, + 908D11582887ED8000DD212E /* TZLocationManager.m in Sources */, + 900E65841C2BB8D5003D9A9E /* AppDelegate.m in Sources */, + 9005E2B3257A462E002A8682 /* UIView+TZLayout.m in Sources */, + B606A9C4265FD53200F5493E /* TZVideoCropController.m in Sources */, + 901F2296215CABD600F604ED /* FLAnimatedImageView.m in Sources */, + 9019FD8D21EC25D7009ADEAE /* TZImageUploadOperation.m in Sources */, + 900E65811C2BB8D5003D9A9E /* main.m in Sources */, + 900EF0121C2C107400EA709B /* TZPhotoPreviewController.m in Sources */, + 901CC3FC21CB758500C55443 /* TZImageRequestOperation.m in Sources */, + 6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */, + 900EEFF81C2BBF9500EA709B /* TZImagePickerController.m in Sources */, + 6DC84D0A1DF5358500A107A9 /* TZImageCropManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 900E65911C2BB8D5003D9A9E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 900E659A1C2BB8D5003D9A9E /* TZImagePickerControllerTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 900E659C1C2BB8D5003D9A9E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 900E65A51C2BB8D5003D9A9E /* TZImagePickerControllerUITests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9F763A3D1FA071CF00D9E526 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 57DD378E26D619C9005090FF /* TZAuthLimitedFooterTipView.m in Sources */, + B662C37326629179006A672A /* TZVideoEditedPreviewController.m in Sources */, + B6977B0A265FDB280028BA31 /* TZVideoCropController.m in Sources */, + 901CC3FB21CB757500C55443 /* TZImageRequestOperation.m in Sources */, + 9F763A501FA072E500D9E526 /* TZImagePickerController.m in Sources */, + 9F763A521FA072E500D9E526 /* TZPhotoPickerController.m in Sources */, + 9F763A541FA072E500D9E526 /* TZAssetCell.m in Sources */, + 9F763A561FA072E500D9E526 /* TZAssetModel.m in Sources */, + 9F763A581FA072E500D9E526 /* TZPhotoPreviewController.m in Sources */, + 9005E2B4257A462E002A8682 /* UIView+TZLayout.m in Sources */, + 9F763A5A1FA072E500D9E526 /* TZPhotoPreviewCell.m in Sources */, + 9F763A5C1FA072E500D9E526 /* TZVideoPlayerController.m in Sources */, + 9F763A5E1FA072E500D9E526 /* TZGifPhotoPreviewController.m in Sources */, + 9F763A601FA072E500D9E526 /* TZProgressView.m in Sources */, + 908D11592887ED8000DD212E /* TZLocationManager.m in Sources */, + 9F763A621FA072E500D9E526 /* TZImageManager.m in Sources */, + 9F763A641FA072E500D9E526 /* TZImageCropManager.m in Sources */, + 9F763A6A1FA072E500D9E526 /* NSBundle+TZImagePicker.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 900E65971C2BB8D5003D9A9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 900E657B1C2BB8D5003D9A9E /* TZImagePickerController */; + targetProxy = 900E65961C2BB8D5003D9A9E /* PBXContainerItemProxy */; + }; + 900E65A21C2BB8D5003D9A9E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 900E657B1C2BB8D5003D9A9E /* TZImagePickerController */; + targetProxy = 900E65A11C2BB8D5003D9A9E /* PBXContainerItemProxy */; + }; + 9F763A481FA071D000D9E526 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9F763A411FA071CF00D9E526 /* TZImagePickerControllerFramework */; + targetProxy = 9F763A471FA071D000D9E526 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 900E65881C2BB8D5003D9A9E /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 900E65891C2BB8D5003D9A9E /* Base */, + 6D12FC191D66B71E00182C44 /* zh-Hans */, + 909DBC95216B981B00926570 /* ar-001 */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 900E658D1C2BB8D5003D9A9E /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 900E658E1C2BB8D5003D9A9E /* Base */, + 6D12FC1A1D66B71E00182C44 /* zh-Hans */, + 909DBC96216B981B00926570 /* ar-001 */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + 90A74B83203287C200D84C2A /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 90A74B84203287C200D84C2A /* tz-ru */, + 909DBC97216B981B00926570 /* ar-001 */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 900E65A71C2BB8D5003D9A9E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 900E65A81C2BB8D5003D9A9E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 900E65AA1C2BB8D5003D9A9E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = FK3N68H5LP; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/TZImagePickerController", + ); + INFOPLIST_FILE = TZImagePickerController/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MARKETING_VERSION = 3.8.8; + PRODUCT_BUNDLE_IDENTIFIER = tanzhenios2025.TZImagePickerController.ggg; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 900E65AB1C2BB8D5003D9A9E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = LTFQDC2QVX; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/TZImagePickerController", + ); + INFOPLIST_FILE = TZImagePickerController/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MARKETING_VERSION = 3.8.8; + PRODUCT_BUNDLE_IDENTIFIER = tanzhenios2022.TZImagePickerController.www; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 900E65AD1C2BB8D5003D9A9E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = TZImagePickerControllerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZImagePickerControllerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TZImagePickerController.app/TZImagePickerController"; + }; + name = Debug; + }; + 900E65AE1C2BB8D5003D9A9E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = TZImagePickerControllerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZImagePickerControllerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TZImagePickerController.app/TZImagePickerController"; + }; + name = Release; + }; + 900E65B01C2BB8D5003D9A9E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = TZImagePickerControllerUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZImagePickerControllerUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_TARGET_NAME = TZImagePickerController; + USES_XCTRUNNER = YES; + }; + name = Debug; + }; + 900E65B11C2BB8D5003D9A9E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = TZImagePickerControllerUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZImagePickerControllerUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_TARGET_NAME = TZImagePickerController; + USES_XCTRUNNER = YES; + }; + name = Release; + }; + 9F763A4B1FA071D000D9E526 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = TZImagePickerControllerFramework/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 3.8.3; + OTHER_LDFLAGS = "-all_load"; + PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZImagePickerControllerFramework; + PRODUCT_NAME = TZImagePickerController; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9F763A4C1FA071D000D9E526 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = TZImagePickerControllerFramework/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 3.8.3; + OTHER_LDFLAGS = "-all_load"; + PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZImagePickerControllerFramework; + PRODUCT_NAME = TZImagePickerController; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 900E65771C2BB8D5003D9A9E /* Build configuration list for PBXProject "TZImagePickerController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 900E65A71C2BB8D5003D9A9E /* Debug */, + 900E65A81C2BB8D5003D9A9E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 900E65A91C2BB8D5003D9A9E /* Build configuration list for PBXNativeTarget "TZImagePickerController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 900E65AA1C2BB8D5003D9A9E /* Debug */, + 900E65AB1C2BB8D5003D9A9E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 900E65AC1C2BB8D5003D9A9E /* Build configuration list for PBXNativeTarget "TZImagePickerControllerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 900E65AD1C2BB8D5003D9A9E /* Debug */, + 900E65AE1C2BB8D5003D9A9E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 900E65AF1C2BB8D5003D9A9E /* Build configuration list for PBXNativeTarget "TZImagePickerControllerUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 900E65B01C2BB8D5003D9A9E /* Debug */, + 900E65B11C2BB8D5003D9A9E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9F763A4D1FA071D000D9E526 /* Build configuration list for PBXNativeTarget "TZImagePickerControllerFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9F763A4B1FA071D000D9E526 /* Debug */, + 9F763A4C1FA071D000D9E526 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 900E65741C2BB8D5003D9A9E /* Project object */; +} diff --git a/TZImagePickerController.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TZImagePickerController.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..bd70cc9 --- /dev/null +++ b/TZImagePickerController.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/TZImagePickerController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TZImagePickerController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/TZImagePickerController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/TZImagePickerController.xcodeproj/xcshareddata/xcschemes/TZImagePickerControllerFramework.xcscheme b/TZImagePickerController.xcodeproj/xcshareddata/xcschemes/TZImagePickerControllerFramework.xcscheme new file mode 100644 index 0000000..04c9ed2 --- /dev/null +++ b/TZImagePickerController.xcodeproj/xcshareddata/xcschemes/TZImagePickerControllerFramework.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TZImagePickerController/AppDelegate.h b/TZImagePickerController/AppDelegate.h new file mode 100644 index 0000000..9027dc4 --- /dev/null +++ b/TZImagePickerController/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/TZImagePickerController/AppDelegate.m b/TZImagePickerController/AppDelegate.m new file mode 100644 index 0000000..7a42f19 --- /dev/null +++ b/TZImagePickerController/AppDelegate.m @@ -0,0 +1,85 @@ +// +// AppDelegate.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "AppDelegate.h" +#import "TZImagePickerController.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // 打开下面这句代码,使用导航栏控制器作为rootViewController + // [self useNavControllerAsRoot]; + return YES; +} + +- (void)useNavControllerAsRoot { + UIViewController *vc = [[UIViewController alloc] init]; + vc.view.backgroundColor = [UIColor whiteColor]; + + UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(20, 200, 300, 44)]; + [btn setTitle:@"pushTZImagePickerController" forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [btn addTarget:self action:@selector(pushTZImagePickerController) forControlEvents:UIControlEventTouchUpInside]; + [vc.view addSubview:btn]; + + UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; + nav.navigationBar.barStyle = UIBarStyleBlack; + nav.navigationBar.translucent = YES; + nav.navigationBar.barTintColor = [UIColor colorWithRed:(34/255.0) green:(34/255.0) blue:(34/255.0) alpha:1.0]; + nav.navigationBar.tintColor = [UIColor blackColor]; + if (@available(iOS 13.0, *)) { + UINavigationBarAppearance *barAppearance = [[UINavigationBarAppearance alloc] init]; + if (nav.navigationBar.isTranslucent) { + UIColor *barTintColor = nav.navigationBar.barTintColor; + barAppearance.backgroundColor = [barTintColor colorWithAlphaComponent:0.85]; + } else { + barAppearance.backgroundColor = nav.navigationBar.barTintColor; + } + barAppearance.titleTextAttributes = nav.navigationBar.titleTextAttributes; + nav.navigationBar.standardAppearance = barAppearance; + nav.navigationBar.scrollEdgeAppearance = barAppearance; + } + [nav setNavigationBarHidden:YES]; + + self.window.rootViewController = nav; + [self.window makeKeyAndVisible]; +} + +- (void)pushTZImagePickerController { + TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 columnNumber:4 delegate:nil pushPhotoPickerVc:YES]; + imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; + UINavigationController *nav = (UINavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController; + [nav.topViewController presentViewController:imagePickerVc animated:YES completion:nil]; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + +} + +- (void)applicationWillTerminate:(UIApplication *)application { + +} + +@end diff --git a/TZImagePickerController/Assets.xcassets/AlbumAddBtn.imageset/AlbumAddBtn@2x.png b/TZImagePickerController/Assets.xcassets/AlbumAddBtn.imageset/AlbumAddBtn@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b458d895e5308ac6300e3a459573254bd294025a GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^O(4w33?w(4ZQ2K<*aCb)TyNaC2}C{1m%IduFqH)P z1^;Jwy4}DF$kX?9aSW+oOjcmK@!y?QIVL6K$$XnirNuz_Ut)p7yc)q%ca61-w2Y!w d^>+y{GkjPtmuB@bkZ zLX?-i?(V##u)*zPblC_1=p=!C4<2^TfkT-a1LfV|uk1v|%K~*70HTxtAod9M;sG;hi(hawmJ-Im+RWQSriJN;q!cPw})6^2A6Y;EJWHc8Dh@ z>`+g5Jd;~?jdMi7L+uH@GLmYHiu$Z9sa&bVZtj9dGDGO3%cAYc6?I$d#PDZ$avLIQ zczkUy>Z!;fWo?X*N5MgxVS=syFq0b#9ZE}yDW6EJE}f%7LYkU1NawEm2!f6~upv_Utrr)Sf$t%Bs8AlZDJ@c_4m*k&7xFzmV`RR48^xwQ#*7fX56 zhEkx2knr*D5*@VE8kBoUBdt3hU~vTngXwB0>nK8d_Z^xOmvyj~QqUUfLU$^NhSt?uOoF}*EPI|ek_vv83Z-p0-INM?35 zGudq09U8X1lcK6aY<^?ZZT5cq9fR?>EBSegxxtRf(wL!EW-dqBrnJq#Iv;Py;k3L? z(?emkxZ?!xo+^ofXPky0scCO_i5-eDy;1I&GtYq2!8MRZsKM6BlO#l9~sYe+JU zY;nk(T)MEmwr=1|!z8h3jB!_E_wR6yoOj7tzYPD{rbl_o>XP^f96;%k;*n?mugAp7Vd$kvEUoosX_CP;UL4_bqd* zZF)0|+f($Wtn8*V6z5yQhFlK4T!_3VLcc#Tuf1>Jo^KRzQ9xouAY+=pPffhuvJf4K zO7nL*2w$E{;HBei#f1rcC6SAjua=fwU9XH6lIK9wWBJgjB2(fL5A!zvbuCb%thau4 zPMJn&B0q%5BvJ^kZZl*n`s!&v+K-Efl)gKUwzBe)zauU^z1~-}85hCrl{KHljcra4 z>g?|qs4R+V7^+cLO|0W$++67(OTlqU;|XWMk2{sh)6FfQpk+A(tvDj?ud)cG%{tuNm3&k9Ybl3Tv+KZ&iHu`(NL zU5o9|t&K;a(IVBi+WGgnt}g9Q3wTgYw-SaXms5-aC9aJPIQT(^GvuX_U=08q%*y~B z$n&{%1PBT%T~WANTh?&u#y$HFFRpLKopk6Y(;5pj2LzCr>bSvH3SkZ*BvW$QKrB67 zHuFk%6_`|6RUrIyyN}6q4W4(&TbE6GS3pg7vo&s(nxp;*ir zBs3Y{)q7jJ8Mouhy|Gm+9`Q(=O7D9?fY@pUJsqlPpT-Nx*nKJssI-)T^v3klI^U{Z zOS4ABcH|~{!ZgX9cj81|e zj-R6b{o)UG_21uS@rwWC1y1=HN#NV)Bah{J$Yt78as0Uy?@?UH)>uhsu6! zb92vJWAl59eT820%@Y4}X|FBcKJ+m3XDz)(u@8E^L1%ksS8v6P*@M zdF&s)3%Z~4Bcx2h`A_e~!9$fl7Y{{d?{!t!SF8D8uVzfqYS+P- zAe!uKszJ3+H<*rti)69=B-?iQM9)8XO&5AYy26}#Ng?1f+dKh9yr~l&?SaSWdWB%v z05o85q&iGn{T$2zuC0sE)IF!A3e(nw!S<7@G5;gL2BH1DBmci3<)g?jTX6kX2V9ts zuBQhMqaGUK2YCD4!stSwP~RXd2I_&v`UOJ$yn+JNy@LYrP&_vHcjkuo^9V&m`r|PO sbXbH|2vpHjQ&9(|s007CF-9sHX+hYx(k*J0*-ZdTQyY_VWB0iK0GEj6LjV8( literal 0 HcmV?d00001 diff --git a/TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/Contents.json b/TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/Contents.json new file mode 100644 index 0000000..ca894cd --- /dev/null +++ b/TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_videoedit_left@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/hx_videoedit_left@2x.png b/TZImagePickerController/Assets.xcassets/leftVideoEdit.imageset/hx_videoedit_left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..32bce3515145fc96806aaf222e7119614ed2db92 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0zjO?$P6U6_9=Y@QY`6?zK#qG8~eHcB(ehejKx9j zP7LeL$-D$|*aCb)T>t<7f8xZ6m`BV`KoKEN7sn8Z%gG56EDgsSB1{%AFg%*h?77kJ RtPxO_!PC{xWt~$(695NtA|L<& literal 0 HcmV?d00001 diff --git a/TZImagePickerController/Assets.xcassets/photo_delete.imageset/Contents.json b/TZImagePickerController/Assets.xcassets/photo_delete.imageset/Contents.json new file mode 100644 index 0000000..e9fe6b4 --- /dev/null +++ b/TZImagePickerController/Assets.xcassets/photo_delete.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "photo_delete@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TZImagePickerController/Assets.xcassets/photo_delete.imageset/photo_delete@2x.png b/TZImagePickerController/Assets.xcassets/photo_delete.imageset/photo_delete@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d07e71482571b37a6e4c4aa0f060ba1055344712 GIT binary patch literal 347 zcmV-h0i^zkP)2AjC<*R0H}dRz?EQf+ml z99`>r=YbhfoB9Yq1{l3iOD_Sa-4t}x6y*G9NFad(66pBGFBT&D{X}49CpQex-u0l4 z%lU|6ynIlb83Q!zo7td_K2c!&Vk%^SK+T3U!vKAv2!;a!RlHDO*sJ$wU_DYZA;EA# zpf*x4tPs|*M`}=k(bh98CB5o_+DNr^L8t=#dnzoZLroB>z-q_7KL?<=pwAV0JOITE zfqA)i9_~RgK%W>;EIk9w;JM4!*U=2#c{xk(ZDte$>hy+XgtfA-7*J<7JC_oi2qcg| tKX^i88@GRC(#cR;ct<7f8xZ6m`BV`KoKEN7sn8Z%gG56EDgsSB1{%AFg%*h?77kJ RtPxO_!PC{xWt~$(695NtA|L<& literal 0 HcmV?d00001 diff --git a/TZImagePickerController/Base.lproj/LaunchScreen.storyboard b/TZImagePickerController/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..3cbf303 --- /dev/null +++ b/TZImagePickerController/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TZImagePickerController/Base.lproj/Main.storyboard b/TZImagePickerController/Base.lproj/Main.storyboard new file mode 100644 index 0000000..9e19921 --- /dev/null +++ b/TZImagePickerController/Base.lproj/Main.storyboard @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TZImagePickerController/FLAnimatedImage/FLAnimatedImage.h b/TZImagePickerController/FLAnimatedImage/FLAnimatedImage.h new file mode 100644 index 0000000..f056c3b --- /dev/null +++ b/TZImagePickerController/FLAnimatedImage/FLAnimatedImage.h @@ -0,0 +1,84 @@ +// +// FLAnimatedImage.h +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) 2013-2015 Flipboard. All rights reserved. +// + + +#import + +// Allow user classes conveniently just importing one header. +#import "FLAnimatedImageView.h" + + +#ifndef NS_DESIGNATED_INITIALIZER + #if __has_attribute(objc_designated_initializer) + #define NS_DESIGNATED_INITIALIZER __attribute((objc_designated_initializer)) + #else + #define NS_DESIGNATED_INITIALIZER + #endif +#endif + +extern const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum; + +// +// An `FLAnimatedImage`'s job is to deliver frames in a highly performant way and works in conjunction with `FLAnimatedImageView`. +// It subclasses `NSObject` and not `UIImage` because it's only an "image" in the sense that a sea lion is a lion. +// It tries to intelligently choose the frame cache size depending on the image and memory situation with the goal to lower CPU usage for smaller ones, lower memory usage for larger ones and always deliver frames for high performant play-back. +// Note: `posterImage`, `size`, `loopCount`, `delayTimes` and `frameCount` don't change after successful initialization. +// +@interface FLAnimatedImage : NSObject + +@property (nonatomic, strong, readonly) UIImage *posterImage; // Guaranteed to be loaded; usually equivalent to `-imageLazilyCachedAtIndex:0` +@property (nonatomic, assign, readonly) CGSize size; // The `.posterImage`'s `.size` + +@property (nonatomic, assign, readonly) NSUInteger loopCount; // 0 means repeating the animation indefinitely +@property (nonatomic, strong, readonly) NSDictionary *delayTimesForIndexes; // Of type `NSTimeInterval` boxed in `NSNumber`s +@property (nonatomic, assign, readonly) NSUInteger frameCount; // Number of valid frames; equal to `[.delayTimes count]` + +@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeCurrent; // Current size of intelligently chosen buffer window; can range in the interval [1..frameCount] +@property (nonatomic, assign) NSUInteger frameCacheSizeMax; // Allow to cap the cache size; 0 means no specific limit (default) + +// Intended to be called from main thread synchronously; will return immediately. +// If the result isn't cached, will return `nil`; the caller should then pause playback, not increment frame counter and keep polling. +// After an initial loading time, depending on `frameCacheSize`, frames should be available immediately from the cache. +- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index; + +// Pass either a `UIImage` or an `FLAnimatedImage` and get back its size ++ (CGSize)sizeForImage:(id)image; + +// On success, the initializers return an `FLAnimatedImage` with all fields initialized, on failure they return `nil` and an error will be logged. +- (instancetype)initWithAnimatedGIFData:(NSData *)data; +// Pass 0 for optimalFrameCacheSize to get the default, predrawing is enabled by default. +- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled NS_DESIGNATED_INITIALIZER; ++ (instancetype)animatedImageWithGIFData:(NSData *)data; + +@property (nonatomic, strong, readonly) NSData *data; // The data the receiver was initialized with; read-only + +@end + +typedef NS_ENUM(NSUInteger, FLLogLevel) { + FLLogLevelNone = 0, + FLLogLevelError, + FLLogLevelWarn, + FLLogLevelInfo, + FLLogLevelDebug, + FLLogLevelVerbose +}; + +@interface FLAnimatedImage (Logging) + ++ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel; ++ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level; + +@end + +#define FLLog(logLevel, format, ...) [FLAnimatedImage logStringFromBlock:^NSString *{ return [NSString stringWithFormat:(format), ## __VA_ARGS__]; } withLevel:(logLevel)] + +@interface FLWeakProxy : NSProxy + ++ (instancetype)weakProxyForObject:(id)targetObject; + +@end diff --git a/TZImagePickerController/FLAnimatedImage/FLAnimatedImage.m b/TZImagePickerController/FLAnimatedImage/FLAnimatedImage.m new file mode 100755 index 0000000..cf49ff2 --- /dev/null +++ b/TZImagePickerController/FLAnimatedImage/FLAnimatedImage.m @@ -0,0 +1,816 @@ +// +// FLAnimatedImage.m +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) 2013-2015 Flipboard. All rights reserved. +// + + +#import "FLAnimatedImage.h" +#import +#import + + +// From vm_param.h, define for iOS 8.0 or higher to build on device. +#ifndef BYTE_SIZE + #define BYTE_SIZE 8 // byte size in bits +#endif + +#define MEGABYTE (1024 * 1024) + +// This is how the fastest browsers do it as per 2012: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility +const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum = 0.02; + +// An animated image's data size (dimensions * frameCount) category; its value is the max allowed memory (in MB). +// E.g.: A 100x200px GIF with 30 frames is ~2.3MB in our pixel format and would fall into the `FLAnimatedImageDataSizeCategoryAll` category. +typedef NS_ENUM(NSUInteger, FLAnimatedImageDataSizeCategory) { + FLAnimatedImageDataSizeCategoryAll = 10, // All frames permanently in memory (be nice to the CPU) + FLAnimatedImageDataSizeCategoryDefault = 75, // A frame cache of default size in memory (usually real-time performance and keeping low memory profile) + FLAnimatedImageDataSizeCategoryOnDemand = 250, // Only keep one frame at the time in memory (easier on memory, slowest performance) + FLAnimatedImageDataSizeCategoryUnsupported // Even for one frame too large, computer says no. +}; + +typedef NS_ENUM(NSUInteger, FLAnimatedImageFrameCacheSize) { + FLAnimatedImageFrameCacheSizeNoLimit = 0, // 0 means no specific limit + FLAnimatedImageFrameCacheSizeLowMemory = 1, // The minimum frame cache size; this will produce frames on-demand. + FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning = 2, // If we can produce the frames faster than we consume, one frame ahead will already result in a stutter-free playback. + FLAnimatedImageFrameCacheSizeDefault = 5 // Build up a comfy buffer window to cope with CPU hiccups etc. +}; + + +#if defined(DEBUG) && DEBUG +@protocol FLAnimatedImageDebugDelegate +@optional +- (void)debug_animatedImage:(FLAnimatedImage *)animatedImage didUpdateCachedFrames:(NSIndexSet *)indexesOfFramesInCache; +- (void)debug_animatedImage:(FLAnimatedImage *)animatedImage didRequestCachedFrame:(NSUInteger)index; +- (CGFloat)debug_animatedImagePredrawingSlowdownFactor:(FLAnimatedImage *)animatedImage; +@end +#endif + + +@interface FLAnimatedImage () + +@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeOptimal; // The optimal number of frames to cache based on image size & number of frames; never changes +@property (nonatomic, assign, readonly, getter=isPredrawingEnabled) BOOL predrawingEnabled; // Enables predrawing of images to improve performance. +@property (nonatomic, assign) NSUInteger frameCacheSizeMaxInternal; // Allow to cap the cache size e.g. when memory warnings occur; 0 means no specific limit (default) +@property (nonatomic, assign) NSUInteger requestedFrameIndex; // Most recently requested frame index +@property (nonatomic, assign, readonly) NSUInteger posterImageFrameIndex; // Index of non-purgable poster image; never changes +@property (nonatomic, strong, readonly) NSMutableDictionary *cachedFramesForIndexes; +@property (nonatomic, strong, readonly) NSMutableIndexSet *cachedFrameIndexes; // Indexes of cached frames +@property (nonatomic, strong, readonly) NSMutableIndexSet *requestedFrameIndexes; // Indexes of frames that are currently produced in the background +@property (nonatomic, strong, readonly) NSIndexSet *allFramesIndexSet; // Default index set with the full range of indexes; never changes +@property (nonatomic, assign) NSUInteger memoryWarningCount; +@property (nonatomic, strong, readonly) dispatch_queue_t serialQueue; +@property (nonatomic, strong, readonly) __attribute__((NSObject)) CGImageSourceRef imageSource; + +// The weak proxy is used to break retain cycles with delayed actions from memory warnings. +// We are lying about the actual type here to gain static type checking and eliminate casts. +// The actual type of the object is `FLWeakProxy`. +@property (nonatomic, strong, readonly) FLAnimatedImage *weakProxy; + +#if defined(DEBUG) && DEBUG +@property (nonatomic, weak) id debug_delegate; +#endif + +@end + + +// For custom dispatching of memory warnings to avoid deallocation races since NSNotificationCenter doesn't retain objects it is notifying. +static NSHashTable *allAnimatedImagesWeak; + +@implementation FLAnimatedImage + +#pragma mark - Accessors +#pragma mark Public + +// This is the definite value the frame cache needs to size itself to. +- (NSUInteger)frameCacheSizeCurrent +{ + NSUInteger frameCacheSizeCurrent = self.frameCacheSizeOptimal; + + // If set, respect the caps. + if (self.frameCacheSizeMax > FLAnimatedImageFrameCacheSizeNoLimit) { + frameCacheSizeCurrent = MIN(frameCacheSizeCurrent, self.frameCacheSizeMax); + } + + if (self.frameCacheSizeMaxInternal > FLAnimatedImageFrameCacheSizeNoLimit) { + frameCacheSizeCurrent = MIN(frameCacheSizeCurrent, self.frameCacheSizeMaxInternal); + } + + return frameCacheSizeCurrent; +} + + +- (void)setFrameCacheSizeMax:(NSUInteger)frameCacheSizeMax +{ + if (_frameCacheSizeMax != frameCacheSizeMax) { + + // Remember whether the new cap will cause the current cache size to shrink; then we'll make sure to purge from the cache if needed. + BOOL willFrameCacheSizeShrink = (frameCacheSizeMax < self.frameCacheSizeCurrent); + + // Update the value + _frameCacheSizeMax = frameCacheSizeMax; + + if (willFrameCacheSizeShrink) { + [self purgeFrameCacheIfNeeded]; + } + } +} + + +#pragma mark Private + +- (void)setFrameCacheSizeMaxInternal:(NSUInteger)frameCacheSizeMaxInternal +{ + if (_frameCacheSizeMaxInternal != frameCacheSizeMaxInternal) { + + // Remember whether the new cap will cause the current cache size to shrink; then we'll make sure to purge from the cache if needed. + BOOL willFrameCacheSizeShrink = (frameCacheSizeMaxInternal < self.frameCacheSizeCurrent); + + // Update the value + _frameCacheSizeMaxInternal = frameCacheSizeMaxInternal; + + if (willFrameCacheSizeShrink) { + [self purgeFrameCacheIfNeeded]; + } + } +} + + +#pragma mark - Life Cycle + ++ (void)initialize +{ + if (self == [FLAnimatedImage class]) { + // UIKit memory warning notification handler shared by all of the instances + allAnimatedImagesWeak = [NSHashTable weakObjectsHashTable]; + + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:nil usingBlock:^(NSNotification *note) { + // UIKit notifications are posted on the main thread. didReceiveMemoryWarning: is expecting the main run loop, and we don't lock on allAnimatedImagesWeak + NSAssert([NSThread isMainThread], @"Received memory warning on non-main thread"); + // Get a strong reference to all of the images. If an instance is returned in this array, it is still live and has not entered dealloc. + // Note that FLAnimatedImages can be created on any thread, so the hash table must be locked. + NSArray *images = nil; + @synchronized(allAnimatedImagesWeak) { + images = [[allAnimatedImagesWeak allObjects] copy]; + } + // Now issue notifications to all of the images while holding a strong reference to them + [images makeObjectsPerformSelector:@selector(didReceiveMemoryWarning:) withObject:note]; + }]; + } +} + + +- (instancetype)init +{ + FLAnimatedImage *animatedImage = [self initWithAnimatedGIFData:nil]; + if (!animatedImage) { + FLLog(FLLogLevelError, @"Use `-initWithAnimatedGIFData:` and supply the animated GIF data as an argument to initialize an object of type `FLAnimatedImage`."); + } + return animatedImage; +} + + +- (instancetype)initWithAnimatedGIFData:(NSData *)data +{ + return [self initWithAnimatedGIFData:data optimalFrameCacheSize:0 predrawingEnabled:YES]; +} + +- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled +{ + // Early return if no data supplied! + BOOL hasData = ([data length] > 0); + if (!hasData) { + FLLog(FLLogLevelError, @"No animated GIF data supplied."); + return nil; + } + + self = [super init]; + if (self) { + // Do one-time initializations of `readonly` properties directly to ivar to prevent implicit actions and avoid need for private `readwrite` property overrides. + + // Keep a strong reference to `data` and expose it read-only publicly. + // However, we will use the `_imageSource` as handler to the image data throughout our life cycle. + _data = data; + _predrawingEnabled = isPredrawingEnabled; + + // Initialize internal data structures + _cachedFramesForIndexes = [[NSMutableDictionary alloc] init]; + _cachedFrameIndexes = [[NSMutableIndexSet alloc] init]; + _requestedFrameIndexes = [[NSMutableIndexSet alloc] init]; + + // Note: We could leverage `CGImageSourceCreateWithURL` too to add a second initializer `-initWithAnimatedGIFContentsOfURL:`. + _imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, + (__bridge CFDictionaryRef)@{(NSString *)kCGImageSourceShouldCache: @NO}); + // Early return on failure! + if (!_imageSource) { + FLLog(FLLogLevelError, @"Failed to `CGImageSourceCreateWithData` for animated GIF data %@", data); + return nil; + } + + // Early return if not GIF! + CFStringRef imageSourceContainerType = CGImageSourceGetType(_imageSource); + BOOL isGIFData = UTTypeConformsTo(imageSourceContainerType, kUTTypeGIF); + if (!isGIFData) { + FLLog(FLLogLevelError, @"Supplied data is of type %@ and doesn't seem to be GIF data %@", imageSourceContainerType, data); + return nil; + } + + // Get `LoopCount` + // Note: 0 means repeating the animation indefinitely. + // Image properties example: + // { + // FileSize = 314446; + // "{GIF}" = { + // HasGlobalColorMap = 1; + // LoopCount = 0; + // }; + // } + NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(_imageSource, NULL); + _loopCount = [[[imageProperties objectForKey:(id)kCGImagePropertyGIFDictionary] objectForKey:(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue]; + + // Iterate through frame images + size_t imageCount = CGImageSourceGetCount(_imageSource); + NSUInteger skippedFrameCount = 0; + NSMutableDictionary *delayTimesForIndexesMutable = [NSMutableDictionary dictionaryWithCapacity:imageCount]; + for (size_t i = 0; i < imageCount; i++) { + @autoreleasepool { + CGImageRef frameImageRef = CGImageSourceCreateImageAtIndex(_imageSource, i, NULL); + if (frameImageRef) { + UIImage *frameImage = [UIImage imageWithCGImage:frameImageRef]; + // Check for valid `frameImage` before parsing its properties as frames can be corrupted (and `frameImage` even `nil` when `frameImageRef` was valid). + if (frameImage) { + // Set poster image + if (!self.posterImage) { + _posterImage = frameImage; + // Set its size to proxy our size. + _size = _posterImage.size; + // Remember index of poster image so we never purge it; also add it to the cache. + _posterImageFrameIndex = i; + [self.cachedFramesForIndexes setObject:self.posterImage forKey:@(self.posterImageFrameIndex)]; + [self.cachedFrameIndexes addIndex:self.posterImageFrameIndex]; + } + + // Get `DelayTime` + // Note: It's not in (1/100) of a second like still falsely described in the documentation as per iOS 8 (rdar://19507384) but in seconds stored as `kCFNumberFloat32Type`. + // Frame properties example: + // { + // ColorModel = RGB; + // Depth = 8; + // PixelHeight = 960; + // PixelWidth = 640; + // "{GIF}" = { + // DelayTime = "0.4"; + // UnclampedDelayTime = "0.4"; + // }; + // } + + NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(_imageSource, i, NULL); + NSDictionary *framePropertiesGIF = [frameProperties objectForKey:(id)kCGImagePropertyGIFDictionary]; + + // Try to use the unclamped delay time; fall back to the normal delay time. + NSNumber *delayTime = [framePropertiesGIF objectForKey:(id)kCGImagePropertyGIFUnclampedDelayTime]; + if (!delayTime) { + delayTime = [framePropertiesGIF objectForKey:(id)kCGImagePropertyGIFDelayTime]; + } + // If we don't get a delay time from the properties, fall back to `kDelayTimeIntervalDefault` or carry over the preceding frame's value. + const NSTimeInterval kDelayTimeIntervalDefault = 0.1; + if (!delayTime) { + if (i == 0) { + FLLog(FLLogLevelInfo, @"Falling back to default delay time for first frame %@ because none found in GIF properties %@", frameImage, frameProperties); + delayTime = @(kDelayTimeIntervalDefault); + } else { + FLLog(FLLogLevelInfo, @"Falling back to preceding delay time for frame %zu %@ because none found in GIF properties %@", i, frameImage, frameProperties); + delayTime = delayTimesForIndexesMutable[@(i - 1)]; + } + } + // Support frame delays as low as `kFLAnimatedImageDelayTimeIntervalMinimum`, with anything below being rounded up to `kDelayTimeIntervalDefault` for legacy compatibility. + // To support the minimum even when rounding errors occur, use an epsilon when comparing. We downcast to float because that's what we get for delayTime from ImageIO. + if ([delayTime floatValue] < ((float)kFLAnimatedImageDelayTimeIntervalMinimum - FLT_EPSILON)) { + FLLog(FLLogLevelInfo, @"Rounding frame %zu's `delayTime` from %f up to default %f (minimum supported: %f).", i, [delayTime floatValue], kDelayTimeIntervalDefault, kFLAnimatedImageDelayTimeIntervalMinimum); + delayTime = @(kDelayTimeIntervalDefault); + } + delayTimesForIndexesMutable[@(i)] = delayTime; + } else { + skippedFrameCount++; + FLLog(FLLogLevelInfo, @"Dropping frame %zu because valid `CGImageRef` %@ did result in `nil`-`UIImage`.", i, frameImageRef); + } + CFRelease(frameImageRef); + } else { + skippedFrameCount++; + FLLog(FLLogLevelInfo, @"Dropping frame %zu because failed to `CGImageSourceCreateImageAtIndex` with image source %@", i, self->_imageSource); + } + } + } + _delayTimesForIndexes = [delayTimesForIndexesMutable copy]; + _frameCount = imageCount; + + if (self.frameCount == 0) { + FLLog(FLLogLevelInfo, @"Failed to create any valid frames for GIF with properties %@", imageProperties); + return nil; + } else if (self.frameCount == 1) { + // Warn when we only have a single frame but return a valid GIF. + FLLog(FLLogLevelInfo, @"Created valid GIF but with only a single frame. Image properties: %@", imageProperties); + } else { + // We have multiple frames, rock on! + } + + // If no value is provided, select a default based on the GIF. + if (optimalFrameCacheSize == 0) { + // Calculate the optimal frame cache size: try choosing a larger buffer window depending on the predicted image size. + // It's only dependent on the image size & number of frames and never changes. + CGFloat animatedImageDataSize = CGImageGetBytesPerRow(self.posterImage.CGImage) * self.size.height * (self.frameCount - skippedFrameCount) / MEGABYTE; + if (animatedImageDataSize <= FLAnimatedImageDataSizeCategoryAll) { + _frameCacheSizeOptimal = self.frameCount; + } else if (animatedImageDataSize <= FLAnimatedImageDataSizeCategoryDefault) { + // This value doesn't depend on device memory much because if we're not keeping all frames in memory we will always be decoding 1 frame up ahead per 1 frame that gets played and at this point we might as well just keep a small buffer just large enough to keep from running out of frames. + _frameCacheSizeOptimal = FLAnimatedImageFrameCacheSizeDefault; + } else { + // The predicted size exceeds the limits to build up a cache and we go into low memory mode from the beginning. + _frameCacheSizeOptimal = FLAnimatedImageFrameCacheSizeLowMemory; + } + } else { + // Use the provided value. + _frameCacheSizeOptimal = optimalFrameCacheSize; + } + // In any case, cap the optimal cache size at the frame count. + _frameCacheSizeOptimal = MIN(_frameCacheSizeOptimal, self.frameCount); + + // Convenience/minor performance optimization; keep an index set handy with the full range to return in `-frameIndexesToCache`. + _allFramesIndexSet = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, self.frameCount)]; + + // See the property declarations for descriptions. + _weakProxy = (id)[FLWeakProxy weakProxyForObject:self]; + + // Register this instance in the weak table for memory notifications. The NSHashTable will clean up after itself when we're gone. + // Note that FLAnimatedImages can be created on any thread, so the hash table must be locked. + @synchronized(allAnimatedImagesWeak) { + [allAnimatedImagesWeak addObject:self]; + } + } + return self; +} + + ++ (instancetype)animatedImageWithGIFData:(NSData *)data +{ + FLAnimatedImage *animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:data]; + return animatedImage; +} + + +- (void)dealloc +{ + if (_weakProxy) { + [NSObject cancelPreviousPerformRequestsWithTarget:_weakProxy]; + } + + if (_imageSource) { + CFRelease(_imageSource); + } +} + + +#pragma mark - Public Methods + +// See header for more details. +// Note: both consumer and producer are throttled: consumer by frame timings and producer by the available memory (max buffer window size). +- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index +{ + // Early return if the requested index is beyond bounds. + // Note: We're comparing an index with a count and need to bail on greater than or equal to. + if (index >= self.frameCount) { + FLLog(FLLogLevelWarn, @"Skipping requested frame %lu beyond bounds (total frame count: %lu) for animated image: %@", (unsigned long)index, (unsigned long)self.frameCount, self); + return nil; + } + + // Remember requested frame index, this influences what we should cache next. + self.requestedFrameIndex = index; +#if defined(DEBUG) && DEBUG + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImage:didRequestCachedFrame:)]) { + [self.debug_delegate debug_animatedImage:self didRequestCachedFrame:index]; + } +#endif + + // Quick check to avoid doing any work if we already have all possible frames cached, a common case. + if ([self.cachedFrameIndexes count] < self.frameCount) { + // If we have frames that should be cached but aren't and aren't requested yet, request them. + // Exclude existing cached frames, frames already requested, and specially cached poster image. + NSMutableIndexSet *frameIndexesToAddToCacheMutable = [self frameIndexesToCache]; + [frameIndexesToAddToCacheMutable removeIndexes:self.cachedFrameIndexes]; + [frameIndexesToAddToCacheMutable removeIndexes:self.requestedFrameIndexes]; + [frameIndexesToAddToCacheMutable removeIndex:self.posterImageFrameIndex]; + NSIndexSet *frameIndexesToAddToCache = [frameIndexesToAddToCacheMutable copy]; + + // Asynchronously add frames to our cache. + if ([frameIndexesToAddToCache count] > 0) { + [self addFrameIndexesToCache:frameIndexesToAddToCache]; + } + } + + // Get the specified image. + UIImage *image = self.cachedFramesForIndexes[@(index)]; + + // Purge if needed based on the current playhead position. + [self purgeFrameCacheIfNeeded]; + + return image; +} + + +// Only called once from `-imageLazilyCachedAtIndex` but factored into its own method for logical grouping. +- (void)addFrameIndexesToCache:(NSIndexSet *)frameIndexesToAddToCache +{ + // Order matters. First, iterate over the indexes starting from the requested frame index. + // Then, if there are any indexes before the requested frame index, do those. + NSRange firstRange = NSMakeRange(self.requestedFrameIndex, self.frameCount - self.requestedFrameIndex); + NSRange secondRange = NSMakeRange(0, self.requestedFrameIndex); + if (firstRange.length + secondRange.length != self.frameCount) { + FLLog(FLLogLevelWarn, @"Two-part frame cache range doesn't equal full range."); + } + + // Add to the requested list before we actually kick them off, so they don't get into the queue twice. + [self.requestedFrameIndexes addIndexes:frameIndexesToAddToCache]; + + // Lazily create dedicated isolation queue. + if (!self.serialQueue) { + _serialQueue = dispatch_queue_create("com.flipboard.framecachingqueue", DISPATCH_QUEUE_SERIAL); + } + + // Start streaming requested frames in the background into the cache. + // Avoid capturing self in the block as there's no reason to keep doing work if the animated image went away. + FLAnimatedImage * __weak weakSelf = self; + dispatch_async(self.serialQueue, ^{ + // Produce and cache next needed frame. + void (^frameRangeBlock)(NSRange, BOOL *) = ^(NSRange range, BOOL *stop) { + // Iterate through contiguous indexes; can be faster than `enumerateIndexesInRange:options:usingBlock:`. + for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { +#if defined(DEBUG) && DEBUG + CFTimeInterval predrawBeginTime = CACurrentMediaTime(); +#endif + UIImage *image = [weakSelf imageAtIndex:i]; +#if defined(DEBUG) && DEBUG + CFTimeInterval predrawDuration = CACurrentMediaTime() - predrawBeginTime; + CFTimeInterval slowdownDuration = 0.0; + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImagePredrawingSlowdownFactor:)]) { + CGFloat predrawingSlowdownFactor = [self.debug_delegate debug_animatedImagePredrawingSlowdownFactor:self]; + slowdownDuration = predrawDuration * predrawingSlowdownFactor - predrawDuration; + [NSThread sleepForTimeInterval:slowdownDuration]; + } + FLLog(FLLogLevelVerbose, @"Predrew frame %lu in %f ms for animated image: %@", (unsigned long)i, (predrawDuration + slowdownDuration) * 1000, self); +#endif + // The results get returned one by one as soon as they're ready (and not in batch). + // The benefits of having the first frames as quick as possible outweigh building up a buffer to cope with potential hiccups when the CPU suddenly gets busy. + if (image && weakSelf) { + dispatch_async(dispatch_get_main_queue(), ^{ + weakSelf.cachedFramesForIndexes[@(i)] = image; + [weakSelf.cachedFrameIndexes addIndex:i]; + [weakSelf.requestedFrameIndexes removeIndex:i]; +#if defined(DEBUG) && DEBUG + if ([weakSelf.debug_delegate respondsToSelector:@selector(debug_animatedImage:didUpdateCachedFrames:)]) { + [weakSelf.debug_delegate debug_animatedImage:weakSelf didUpdateCachedFrames:weakSelf.cachedFrameIndexes]; + } +#endif + }); + } + } + }; + + [frameIndexesToAddToCache enumerateRangesInRange:firstRange options:0 usingBlock:frameRangeBlock]; + [frameIndexesToAddToCache enumerateRangesInRange:secondRange options:0 usingBlock:frameRangeBlock]; + }); +} + + ++ (CGSize)sizeForImage:(id)image +{ + CGSize imageSize = CGSizeZero; + + // Early return for nil + if (!image) { + return imageSize; + } + + if ([image isKindOfClass:[UIImage class]]) { + UIImage *uiImage = (UIImage *)image; + imageSize = uiImage.size; + } else if ([image isKindOfClass:[FLAnimatedImage class]]) { + FLAnimatedImage *animatedImage = (FLAnimatedImage *)image; + imageSize = animatedImage.size; + } else { + // Bear trap to capture bad images; we have seen crashers cropping up on iOS 7. + FLLog(FLLogLevelError, @"`image` isn't of expected types `UIImage` or `FLAnimatedImage`: %@", image); + } + + return imageSize; +} + + +#pragma mark - Private Methods +#pragma mark Frame Loading + +- (UIImage *)imageAtIndex:(NSUInteger)index +{ + // It's very important to use the cached `_imageSource` since the random access to a frame with `CGImageSourceCreateImageAtIndex` turns from an O(1) into an O(n) operation when re-initializing the image source every time. + CGImageRef imageRef = CGImageSourceCreateImageAtIndex(_imageSource, index, NULL); + + // Early return for nil + if (!imageRef) { + return nil; + } + + UIImage *image = [UIImage imageWithCGImage:imageRef]; + CFRelease(imageRef); + + // Loading in the image object is only half the work, the displaying image view would still have to synchronosly wait and decode the image, so we go ahead and do that here on the background thread. + if (self.isPredrawingEnabled) { + image = [[self class] predrawnImageFromImage:image]; + } + + return image; +} + + +#pragma mark Frame Caching + +- (NSMutableIndexSet *)frameIndexesToCache +{ + NSMutableIndexSet *indexesToCache = nil; + // Quick check to avoid building the index set if the number of frames to cache equals the total frame count. + if (self.frameCacheSizeCurrent == self.frameCount) { + indexesToCache = [self.allFramesIndexSet mutableCopy]; + } else { + indexesToCache = [[NSMutableIndexSet alloc] init]; + + // Add indexes to the set in two separate blocks- the first starting from the requested frame index, up to the limit or the end. + // The second, if needed, the remaining number of frames beginning at index zero. + NSUInteger firstLength = MIN(self.frameCacheSizeCurrent, self.frameCount - self.requestedFrameIndex); + NSRange firstRange = NSMakeRange(self.requestedFrameIndex, firstLength); + [indexesToCache addIndexesInRange:firstRange]; + NSUInteger secondLength = self.frameCacheSizeCurrent - firstLength; + if (secondLength > 0) { + NSRange secondRange = NSMakeRange(0, secondLength); + [indexesToCache addIndexesInRange:secondRange]; + } + // Double check our math, before we add the poster image index which may increase it by one. + if ([indexesToCache count] != self.frameCacheSizeCurrent) { + FLLog(FLLogLevelWarn, @"Number of frames to cache doesn't equal expected cache size."); + } + + [indexesToCache addIndex:self.posterImageFrameIndex]; + } + + return indexesToCache; +} + + +- (void)purgeFrameCacheIfNeeded +{ + // Purge frames that are currently cached but don't need to be. + // But not if we're still under the number of frames to cache. + // This way, if all frames are allowed to be cached (the common case), we can skip all the `NSIndexSet` math below. + if ([self.cachedFrameIndexes count] > self.frameCacheSizeCurrent) { + NSMutableIndexSet *indexesToPurge = [self.cachedFrameIndexes mutableCopy]; + [indexesToPurge removeIndexes:[self frameIndexesToCache]]; + [indexesToPurge enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) { + // Iterate through contiguous indexes; can be faster than `enumerateIndexesInRange:options:usingBlock:`. + for (NSUInteger i = range.location; i < NSMaxRange(range); i++) { + [self.cachedFrameIndexes removeIndex:i]; + [self.cachedFramesForIndexes removeObjectForKey:@(i)]; + // Note: Don't `CGImageSourceRemoveCacheAtIndex` on the image source for frames that we don't want cached any longer to maintain O(1) time access. +#if defined(DEBUG) && DEBUG + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImage:didUpdateCachedFrames:)]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.debug_delegate debug_animatedImage:self didUpdateCachedFrames:self.cachedFrameIndexes]; + }); + } +#endif + } + }]; + } +} + + +- (void)growFrameCacheSizeAfterMemoryWarning:(NSNumber *)frameCacheSize +{ + self.frameCacheSizeMaxInternal = [frameCacheSize unsignedIntegerValue]; + FLLog(FLLogLevelDebug, @"Grew frame cache size max to %lu after memory warning for animated image: %@", (unsigned long)self.frameCacheSizeMaxInternal, self); + + // Schedule resetting the frame cache size max completely after a while. + const NSTimeInterval kResetDelay = 3.0; + [self.weakProxy performSelector:@selector(resetFrameCacheSizeMaxInternal) withObject:nil afterDelay:kResetDelay]; +} + + +- (void)resetFrameCacheSizeMaxInternal +{ + self.frameCacheSizeMaxInternal = FLAnimatedImageFrameCacheSizeNoLimit; + FLLog(FLLogLevelDebug, @"Reset frame cache size max (current frame cache size: %lu) for animated image: %@", (unsigned long)self.frameCacheSizeCurrent, self); +} + + +#pragma mark System Memory Warnings Notification Handler + +- (void)didReceiveMemoryWarning:(NSNotification *)notification +{ + self.memoryWarningCount++; + + // If we were about to grow larger, but got rapped on our knuckles by the system again, cancel. + [NSObject cancelPreviousPerformRequestsWithTarget:self.weakProxy selector:@selector(growFrameCacheSizeAfterMemoryWarning:) object:@(FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning)]; + [NSObject cancelPreviousPerformRequestsWithTarget:self.weakProxy selector:@selector(resetFrameCacheSizeMaxInternal) object:nil]; + + // Go down to the minimum and by that implicitly immediately purge from the cache if needed to not get jettisoned by the system and start producing frames on-demand. + FLLog(FLLogLevelDebug, @"Attempt setting frame cache size max to %lu (previous was %lu) after memory warning #%lu for animated image: %@", (unsigned long)FLAnimatedImageFrameCacheSizeLowMemory, (unsigned long)self.frameCacheSizeMaxInternal, (unsigned long)self.memoryWarningCount, self); + self.frameCacheSizeMaxInternal = FLAnimatedImageFrameCacheSizeLowMemory; + + // Schedule growing larger again after a while, but cap our attempts to prevent a periodic sawtooth wave (ramps upward and then sharply drops) of memory usage. + // + // [mem]^ (2) (5) (6) 1) Loading frames for the first time + // (*)| , , , 2) Mem warning #1; purge cache + // | /| (4)/| /| 3) Grow cache size a bit after a while, if no mem warning occurs + // | / | _/ | _/ | 4) Try to grow cache size back to optimum after a while, if no mem warning occurs + // |(1)/ |_/ |/ |__(7) 5) Mem warning #2; purge cache + // |__/ (3) 6) After repetition of (3) and (4), mem warning #3; purge cache + // +----------------------> 7) After 3 mem warnings, stay at minimum cache size + // [t] + // *) The mem high water mark before we get warned might change for every cycle. + // + const NSUInteger kGrowAttemptsMax = 2; + const NSTimeInterval kGrowDelay = 2.0; + if ((self.memoryWarningCount - 1) <= kGrowAttemptsMax) { + [self.weakProxy performSelector:@selector(growFrameCacheSizeAfterMemoryWarning:) withObject:@(FLAnimatedImageFrameCacheSizeGrowAfterMemoryWarning) afterDelay:kGrowDelay]; + } + + // Note: It's not possible to get the level of a memory warning with a public API: http://stackoverflow.com/questions/2915247/iphone-os-memory-warnings-what-do-the-different-levels-mean/2915477#2915477 +} + + +#pragma mark Image Decoding + +// Decodes the image's data and draws it off-screen fully in memory; it's thread-safe and hence can be called on a background thread. +// On success, the returned object is a new `UIImage` instance with the same content as the one passed in. +// On failure, the returned object is the unchanged passed in one; the data will not be predrawn in memory though and an error will be logged. +// First inspired by & good Karma to: https://gist.github.com/steipete/1144242 ++ (UIImage *)predrawnImageFromImage:(UIImage *)imageToPredraw +{ + // Always use a device RGB color space for simplicity and predictability what will be going on. + CGColorSpaceRef colorSpaceDeviceRGBRef = CGColorSpaceCreateDeviceRGB(); + // Early return on failure! + if (!colorSpaceDeviceRGBRef) { + FLLog(FLLogLevelError, @"Failed to `CGColorSpaceCreateDeviceRGB` for image %@", imageToPredraw); + return imageToPredraw; + } + + // Even when the image doesn't have transparency, we have to add the extra channel because Quartz doesn't support other pixel formats than 32 bpp/8 bpc for RGB: + // kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst, kCGImageAlphaPremultipliedLast + // (source: docs "Quartz 2D Programming Guide > Graphics Contexts > Table 2-1 Pixel formats supported for bitmap graphics contexts") + size_t numberOfComponents = CGColorSpaceGetNumberOfComponents(colorSpaceDeviceRGBRef) + 1; // 4: RGB + A + + // "In iOS 4.0 and later, and OS X v10.6 and later, you can pass NULL if you want Quartz to allocate memory for the bitmap." (source: docs) + void *data = NULL; + size_t width = imageToPredraw.size.width; + size_t height = imageToPredraw.size.height; + size_t bitsPerComponent = CHAR_BIT; + + size_t bitsPerPixel = (bitsPerComponent * numberOfComponents); + size_t bytesPerPixel = (bitsPerPixel / BYTE_SIZE); + size_t bytesPerRow = (bytesPerPixel * width); + + CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; + + CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageToPredraw.CGImage); + // If the alpha info doesn't match to one of the supported formats (see above), pick a reasonable supported one. + // "For bitmaps created in iOS 3.2 and later, the drawing environment uses the premultiplied ARGB format to store the bitmap data." (source: docs) + if (alphaInfo == kCGImageAlphaNone || alphaInfo == kCGImageAlphaOnly) { + alphaInfo = kCGImageAlphaNoneSkipFirst; + } else if (alphaInfo == kCGImageAlphaFirst) { + alphaInfo = kCGImageAlphaPremultipliedFirst; + } else if (alphaInfo == kCGImageAlphaLast) { + alphaInfo = kCGImageAlphaPremultipliedLast; + } + // "The constants for specifying the alpha channel information are declared with the `CGImageAlphaInfo` type but can be passed to this parameter safely." (source: docs) + bitmapInfo |= alphaInfo; + + // Create our own graphics context to draw to; `UIGraphicsGetCurrentContext`/`UIGraphicsBeginImageContextWithOptions` doesn't create a new context but returns the current one which isn't thread-safe (e.g. main thread could use it at the same time). + // Note: It's not worth caching the bitmap context for multiple frames ("unique key" would be `width`, `height` and `hasAlpha`), it's ~50% slower. Time spent in libRIP's `CGSBlendBGRA8888toARGB8888` suddenly shoots up -- not sure why. + CGContextRef bitmapContextRef = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpaceDeviceRGBRef, bitmapInfo); + CGColorSpaceRelease(colorSpaceDeviceRGBRef); + // Early return on failure! + if (!bitmapContextRef) { + FLLog(FLLogLevelError, @"Failed to `CGBitmapContextCreate` with color space %@ and parameters (width: %zu height: %zu bitsPerComponent: %zu bytesPerRow: %zu) for image %@", colorSpaceDeviceRGBRef, width, height, bitsPerComponent, bytesPerRow, imageToPredraw); + return imageToPredraw; + } + + // Draw image in bitmap context and create image by preserving receiver's properties. + CGContextDrawImage(bitmapContextRef, CGRectMake(0.0, 0.0, imageToPredraw.size.width, imageToPredraw.size.height), imageToPredraw.CGImage); + CGImageRef predrawnImageRef = CGBitmapContextCreateImage(bitmapContextRef); + UIImage *predrawnImage = [UIImage imageWithCGImage:predrawnImageRef scale:imageToPredraw.scale orientation:imageToPredraw.imageOrientation]; + CGImageRelease(predrawnImageRef); + CGContextRelease(bitmapContextRef); + + // Early return on failure! + if (!predrawnImage) { + FLLog(FLLogLevelError, @"Failed to `imageWithCGImage:scale:orientation:` with image ref %@ created with color space %@ and bitmap context %@ and properties and properties (scale: %f orientation: %ld) for image %@", predrawnImageRef, colorSpaceDeviceRGBRef, bitmapContextRef, imageToPredraw.scale, (long)imageToPredraw.imageOrientation, imageToPredraw); + return imageToPredraw; + } + + return predrawnImage; +} + + +#pragma mark - Description + +- (NSString *)description +{ + NSString *description = [super description]; + + description = [description stringByAppendingFormat:@" size=%@", NSStringFromCGSize(self.size)]; + description = [description stringByAppendingFormat:@" frameCount=%lu", (unsigned long)self.frameCount]; + + return description; +} + + +@end + +#pragma mark - Logging + +@implementation FLAnimatedImage (Logging) + +static void (^_logBlock)(NSString *logString, FLLogLevel logLevel) = nil; +static FLLogLevel _logLevel; + ++ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel +{ + _logBlock = logBlock; + _logLevel = logLevel; +} + ++ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level +{ + if (level <= _logLevel && _logBlock && stringBlock) { + _logBlock(stringBlock(), level); + } +} + +@end + + +#pragma mark - FLWeakProxy + +@interface FLWeakProxy () + +@property (nonatomic, weak) id target; + +@end + + +@implementation FLWeakProxy + +#pragma mark Life Cycle + +// This is the designated creation method of an `FLWeakProxy` and +// as a subclass of `NSProxy` it doesn't respond to or need `-init`. ++ (instancetype)weakProxyForObject:(id)targetObject +{ + FLWeakProxy *weakProxy = [FLWeakProxy alloc]; + weakProxy.target = targetObject; + return weakProxy; +} + + +#pragma mark Forwarding Messages + +- (id)forwardingTargetForSelector:(SEL)selector +{ + // Keep it lightweight: access the ivar directly + return _target; +} + + +#pragma mark - NSWeakProxy Method Overrides +#pragma mark Handling Unimplemented Methods + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + // Fallback for when target is nil. Don't do anything, just return 0/NULL/nil. + // The method signature we've received to get here is just a dummy to keep `doesNotRecognizeSelector:` from firing. + // We can't really handle struct return types here because we don't know the length. + void *nullPointer = NULL; + [invocation setReturnValue:&nullPointer]; +} + + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector +{ + // We only get here if `forwardingTargetForSelector:` returns nil. + // In that case, our weak target has been reclaimed. Return a dummy method signature to keep `doesNotRecognizeSelector:` from firing. + // We'll emulate the Obj-c messaging nil behavior by setting the return value to nil in `forwardInvocation:`, but we'll assume that the return value is `sizeof(void *)`. + // Other libraries handle this situation by making use of a global method signature cache, but that seems heavier than necessary and has issues as well. + // See https://www.mikeash.com/pyblog/friday-qa-2010-02-26-futures.html and https://github.com/steipete/PSTDelegateProxy/issues/1 for examples of using a method signature cache. + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} + + +@end diff --git a/TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.h b/TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.h new file mode 100644 index 0000000..c0d527a --- /dev/null +++ b/TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.h @@ -0,0 +1,36 @@ +// +// FLAnimatedImageView.h +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) 2013-2015 Flipboard. All rights reserved. +// + + +#import + +@class FLAnimatedImage; +@protocol FLAnimatedImageViewDebugDelegate; + + +// +// An `FLAnimatedImageView` can take an `FLAnimatedImage` and plays it automatically when in view hierarchy and stops when removed. +// The animation can also be controlled with the `UIImageView` methods `-start/stop/isAnimating`. +// It is a fully compatible `UIImageView` subclass and can be used as a drop-in component to work with existing code paths expecting to display a `UIImage`. +// Under the hood it uses a `CADisplayLink` for playback, which can be inspected with `currentFrame` & `currentFrameIndex`. +// +@interface FLAnimatedImageView : UIImageView + +// Setting `[UIImageView.image]` to a non-`nil` value clears out existing `animatedImage`. +// And vice versa, setting `animatedImage` will initially populate the `[UIImageView.image]` to its `posterImage` and then start animating and hold `currentFrame`. +@property (nonatomic, strong) FLAnimatedImage *animatedImage; +@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining); + +@property (nonatomic, strong, readonly) UIImage *currentFrame; +@property (nonatomic, assign, readonly) NSUInteger currentFrameIndex; + +// The animation runloop mode. Enables playback during scrolling by allowing timer events (i.e. animation) with NSRunLoopCommonModes. +// To keep scrolling smooth on single-core devices such as iPhone 3GS/4 and iPod Touch 4th gen, the default run loop mode is NSDefaultRunLoopMode. Otherwise, the default is NSDefaultRunLoopMode. +@property (nonatomic, copy) NSString *runLoopMode; + +@end diff --git a/TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.m b/TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.m new file mode 100755 index 0000000..26fea1d --- /dev/null +++ b/TZImagePickerController/FLAnimatedImage/FLAnimatedImageView.m @@ -0,0 +1,442 @@ +// +// FLAnimatedImageView.h +// Flipboard +// +// Created by Raphael Schaad on 7/8/13. +// Copyright (c) 2013-2015 Flipboard. All rights reserved. +// + + +#import "FLAnimatedImageView.h" +#import "FLAnimatedImage.h" +#import + + +#if defined(DEBUG) && DEBUG +@protocol FLAnimatedImageViewDebugDelegate +@optional +- (void)debug_animatedImageView:(FLAnimatedImageView *)animatedImageView waitingForFrame:(NSUInteger)index duration:(NSTimeInterval)duration; +@end +#endif + + +@interface FLAnimatedImageView () + +// Override of public `readonly` properties as private `readwrite` +@property (nonatomic, strong, readwrite) UIImage *currentFrame; +@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex; + +@property (nonatomic, assign) NSUInteger loopCountdown; +@property (nonatomic, assign) NSTimeInterval accumulator; +@property (nonatomic, strong) CADisplayLink *displayLink; + +@property (nonatomic, assign) BOOL shouldAnimate; // Before checking this value, call `-updateShouldAnimate` whenever the animated image or visibility (window, superview, hidden, alpha) has changed. +@property (nonatomic, assign) BOOL needsDisplayWhenImageBecomesAvailable; + +#if defined(DEBUG) && DEBUG +@property (nonatomic, weak) id debug_delegate; +#endif + +@end + + +@implementation FLAnimatedImageView +@synthesize runLoopMode = _runLoopMode; + +#pragma mark - Initializers + +// -initWithImage: isn't documented as a designated initializer of UIImageView, but it actually seems to be. +// Using -initWithImage: doesn't call any of the other designated initializers. +- (instancetype)initWithImage:(UIImage *)image +{ + self = [super initWithImage:image]; + if (self) { + [self commonInit]; + } + return self; +} + +// -initWithImage:highlightedImage: also isn't documented as a designated initializer of UIImageView, but it doesn't call any other designated initializers. +- (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage +{ + self = [super initWithImage:image highlightedImage:highlightedImage]; + if (self) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit +{ + self.runLoopMode = [[self class] defaultRunLoopMode]; + + if (@available(iOS 11.0, *)) { + self.accessibilityIgnoresInvertColors = YES; + } +} + + +#pragma mark - Accessors +#pragma mark Public + +- (void)setAnimatedImage:(FLAnimatedImage *)animatedImage +{ + if (![_animatedImage isEqual:animatedImage]) { + if (animatedImage) { + // Clear out the image. + super.image = nil; + // Ensure disabled highlighting; it's not supported (see `-setHighlighted:`). + super.highlighted = NO; + // UIImageView seems to bypass some accessors when calculating its intrinsic content size, so this ensures its intrinsic content size comes from the animated image. + [self invalidateIntrinsicContentSize]; + } else { + // Stop animating before the animated image gets cleared out. + [self stopAnimating]; + } + + _animatedImage = animatedImage; + + self.currentFrame = animatedImage.posterImage; + self.currentFrameIndex = 0; + if (animatedImage.loopCount > 0) { + self.loopCountdown = animatedImage.loopCount; + } else { + self.loopCountdown = NSUIntegerMax; + } + self.accumulator = 0.0; + + // Start animating after the new animated image has been set. + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } + + [self.layer setNeedsDisplay]; + } +} + + +#pragma mark - Life Cycle + +- (void)dealloc +{ + // Removes the display link from all run loop modes. + [_displayLink invalidate]; +} + + +#pragma mark - UIView Method Overrides +#pragma mark Observing View-Related Changes + +- (void)didMoveToSuperview +{ + [super didMoveToSuperview]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + + +- (void)didMoveToWindow +{ + [super didMoveToWindow]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + +- (void)setAlpha:(CGFloat)alpha +{ + [super setAlpha:alpha]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + +- (void)setHidden:(BOOL)hidden +{ + [super setHidden:hidden]; + + [self updateShouldAnimate]; + if (self.shouldAnimate) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + + +#pragma mark Auto Layout + +- (CGSize)intrinsicContentSize +{ + // Default to let UIImageView handle the sizing of its image, and anything else it might consider. + CGSize intrinsicContentSize = [super intrinsicContentSize]; + + // If we have have an animated image, use its image size. + // UIImageView's intrinsic content size seems to be the size of its image. The obvious approach, simply calling `-invalidateIntrinsicContentSize` when setting an animated image, results in UIImageView steadfastly returning `{UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric}` for its intrinsicContentSize. + // (Perhaps UIImageView bypasses its `-image` getter in its implementation of `-intrinsicContentSize`, as `-image` is not called after calling `-invalidateIntrinsicContentSize`.) + if (self.animatedImage) { + intrinsicContentSize = self.image.size; + } + + return intrinsicContentSize; +} + +#pragma mark Smart Invert Colors + +#pragma mark - UIImageView Method Overrides +#pragma mark Image Data + +- (UIImage *)image +{ + UIImage *image = nil; + if (self.animatedImage) { + // Initially set to the poster image. + image = self.currentFrame; + } else { + image = super.image; + } + return image; +} + + +- (void)setImage:(UIImage *)image +{ + if (image) { + // Clear out the animated image and implicitly pause animation playback. + self.animatedImage = nil; + } + + super.image = image; +} + + +#pragma mark Animating Images + +- (NSTimeInterval)frameDelayGreatestCommonDivisor +{ + // Presision is set to half of the `kFLAnimatedImageDelayTimeIntervalMinimum` in order to minimize frame dropping. + const NSTimeInterval kGreatestCommonDivisorPrecision = 2.0 / kFLAnimatedImageDelayTimeIntervalMinimum; + + NSArray *delays = self.animatedImage.delayTimesForIndexes.allValues; + + // Scales the frame delays by `kGreatestCommonDivisorPrecision` + // then converts it to an UInteger for in order to calculate the GCD. + NSUInteger scaledGCD = lrint([delays.firstObject floatValue] * kGreatestCommonDivisorPrecision); + for (NSNumber *value in delays) { + scaledGCD = gcd(lrint([value floatValue] * kGreatestCommonDivisorPrecision), scaledGCD); + } + + // Reverse to scale to get the value back into seconds. + return scaledGCD / kGreatestCommonDivisorPrecision; +} + + +static NSUInteger gcd(NSUInteger a, NSUInteger b) +{ + // http://en.wikipedia.org/wiki/Greatest_common_divisor + if (a < b) { + return gcd(b, a); + } else if (a == b) { + return b; + } + + while (true) { + NSUInteger remainder = a % b; + if (remainder == 0) { + return b; + } + a = b; + b = remainder; + } +} + + +- (void)startAnimating +{ + if (self.animatedImage) { + // Lazily create the display link. + if (!self.displayLink) { + // It is important to note the use of a weak proxy here to avoid a retain cycle. `-displayLinkWithTarget:selector:` + // will retain its target until it is invalidated. We use a weak proxy so that the image view will get deallocated + // independent of the display link's lifetime. Upon image view deallocation, we invalidate the display + // link which will lead to the deallocation of both the display link and the weak proxy. + FLWeakProxy *weakProxy = [FLWeakProxy weakProxyForObject:self]; + self.displayLink = [CADisplayLink displayLinkWithTarget:weakProxy selector:@selector(displayDidRefresh:)]; + + [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:self.runLoopMode]; + } + + // Note: The display link's `.frameInterval` value of 1 (default) means getting callbacks at the refresh rate of the display (~60Hz). + // Setting it to 2 divides the frame rate by 2 and hence calls back at every other display refresh. + const NSTimeInterval kDisplayRefreshRate = 60.0; // 60Hz + self.displayLink.frameInterval = MAX([self frameDelayGreatestCommonDivisor] * kDisplayRefreshRate, 1); + + self.displayLink.paused = NO; + } else { + [super startAnimating]; + } +} + +- (void)setRunLoopMode:(NSString *)runLoopMode +{ + if (![@[NSDefaultRunLoopMode, NSRunLoopCommonModes] containsObject:runLoopMode]) { + NSAssert(NO, @"Invalid run loop mode: %@", runLoopMode); + _runLoopMode = [[self class] defaultRunLoopMode]; + } else { + _runLoopMode = runLoopMode; + } +} + +- (void)stopAnimating +{ + if (self.animatedImage) { + self.displayLink.paused = YES; + } else { + [super stopAnimating]; + } +} + + +- (BOOL)isAnimating +{ + BOOL isAnimating = NO; + if (self.animatedImage) { + isAnimating = self.displayLink && !self.displayLink.isPaused; + } else { + isAnimating = [super isAnimating]; + } + return isAnimating; +} + + +#pragma mark Highlighted Image Unsupport + +- (void)setHighlighted:(BOOL)highlighted +{ + // Highlighted image is unsupported for animated images, but implementing it breaks the image view when embedded in a UICollectionViewCell. + if (!self.animatedImage) { + [super setHighlighted:highlighted]; + } +} + + +#pragma mark - Private Methods +#pragma mark Animation + +// Don't repeatedly check our window & superview in `-displayDidRefresh:` for performance reasons. +// Just update our cached value whenever the animated image or visibility (window, superview, hidden, alpha) is changed. +- (void)updateShouldAnimate +{ + BOOL isVisible = self.window && self.superview && ![self isHidden] && self.alpha > 0.0; + self.shouldAnimate = self.animatedImage && isVisible; +} + + +- (void)displayDidRefresh:(CADisplayLink *)displayLink +{ + // If for some reason a wild call makes it through when we shouldn't be animating, bail. + // Early return! + if (!self.shouldAnimate) { + FLLog(FLLogLevelWarn, @"Trying to animate image when we shouldn't: %@", self); + return; + } + + NSNumber *delayTimeNumber = [self.animatedImage.delayTimesForIndexes objectForKey:@(self.currentFrameIndex)]; + // If we don't have a frame delay (e.g. corrupt frame), don't update the view but skip the playhead to the next frame (in else-block). + if (delayTimeNumber) { + NSTimeInterval delayTime = [delayTimeNumber floatValue]; + // If we have a nil image (e.g. waiting for frame), don't update the view nor playhead. + UIImage *image = [self.animatedImage imageLazilyCachedAtIndex:self.currentFrameIndex]; + if (image) { + FLLog(FLLogLevelVerbose, @"Showing frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage); + self.currentFrame = image; + if (self.needsDisplayWhenImageBecomesAvailable) { + [self.layer setNeedsDisplay]; + self.needsDisplayWhenImageBecomesAvailable = NO; + } + + self.accumulator += displayLink.duration * displayLink.frameInterval; + + // While-loop first inspired by & good Karma to: https://github.com/ondalabs/OLImageView/blob/master/OLImageView.m + while (self.accumulator >= delayTime) { + self.accumulator -= delayTime; + self.currentFrameIndex++; + if (self.currentFrameIndex >= self.animatedImage.frameCount) { + // If we've looped the number of times that this animated image describes, stop looping. + self.loopCountdown--; + if (self.loopCompletionBlock) { + self.loopCompletionBlock(self.loopCountdown); + } + + if (self.loopCountdown == 0) { + [self stopAnimating]; + return; + } + self.currentFrameIndex = 0; + } + // Calling `-setNeedsDisplay` will just paint the current frame, not the new frame that we may have moved to. + // Instead, set `needsDisplayWhenImageBecomesAvailable` to `YES` -- this will paint the new image once loaded. + self.needsDisplayWhenImageBecomesAvailable = YES; + } + } else { + FLLog(FLLogLevelDebug, @"Waiting for frame %lu for animated image: %@", (unsigned long)self.currentFrameIndex, self.animatedImage); +#if defined(DEBUG) && DEBUG + if ([self.debug_delegate respondsToSelector:@selector(debug_animatedImageView:waitingForFrame:duration:)]) { + [self.debug_delegate debug_animatedImageView:self waitingForFrame:self.currentFrameIndex duration:(NSTimeInterval)displayLink.duration * displayLink.frameInterval]; + } +#endif + } + } else { + self.currentFrameIndex++; + } +} + ++ (NSString *)defaultRunLoopMode +{ + // Key off `activeProcessorCount` (as opposed to `processorCount`) since the system could shut down cores in certain situations. + return [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode; +} + + +#pragma mark - CALayerDelegate (Informal) +#pragma mark Providing the Layer's Content + +- (void)displayLayer:(CALayer *)layer +{ + layer.contents = (__bridge id)self.image.CGImage; +} + + +@end diff --git a/TZImagePickerController/Info.plist b/TZImagePickerController/Info.plist new file mode 100644 index 0000000..8d9097f --- /dev/null +++ b/TZImagePickerController/Info.plist @@ -0,0 +1,57 @@ + + + + + CFBundleDevelopmentRegion + en_US + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSCameraUsageDescription + 访问相机以拍照 + NSLocationUsageDescription + 允许定位以把位置保存到照片中 + NSLocationWhenInUseUsageDescription + 允许定位以把位置保存到照片中 + NSMicrophoneUsageDescription + 访问麦克风以录像 + NSPhotoLibraryUsageDescription + 访问相册以选择照片 + PHPhotoLibraryPreventAutomaticLimitedAccessAlert + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/TZImagePickerController/Location/TZLocationManager.h b/TZImagePickerController/Location/TZLocationManager.h new file mode 100644 index 0000000..19d0525 --- /dev/null +++ b/TZImagePickerController/Location/TZLocationManager.h @@ -0,0 +1,27 @@ +// +// TZLocationManager.h +// TZImagePickerController +// +// Created by 谭真 on 2017/06/03. +// Copyright © 2017年 谭真. All rights reserved. +// 定位管理类 + + +#import +#import + +@interface TZLocationManager : NSObject + ++ (instancetype)manager NS_SWIFT_NAME(default()); + +/// 开始定位 +- (void)startLocation; +- (void)startLocationWithSuccessBlock:(void (^)(NSArray *))successBlock failureBlock:(void (^)(NSError *error))failureBlock; +- (void)startLocationWithGeocoderBlock:(void (^)(NSArray *geocoderArray))geocoderBlock; +- (void)startLocationWithSuccessBlock:(void (^)(NSArray *))successBlock failureBlock:(void (^)(NSError *error))failureBlock geocoderBlock:(void (^)(NSArray *geocoderArray))geocoderBlock; + +/// 结束定位 +- (void)stopUpdatingLocation; + +@end + diff --git a/TZImagePickerController/Location/TZLocationManager.m b/TZImagePickerController/Location/TZLocationManager.m new file mode 100644 index 0000000..d70ea08 --- /dev/null +++ b/TZImagePickerController/Location/TZLocationManager.m @@ -0,0 +1,90 @@ +// +// TZLocationManager.m +// TZImagePickerController +// +// Created by 谭真 on 2017/06/03. +// Copyright © 2017年 谭真. All rights reserved. +// 定位管理类 + +#import "TZLocationManager.h" + +@interface TZLocationManager () +@property (nonatomic, strong) CLLocationManager *locationManager; +/// 定位成功的回调block +@property (nonatomic, copy) void (^successBlock)(NSArray *); +/// 编码成功的回调block +@property (nonatomic, copy) void (^geocodeBlock)(NSArray *geocodeArray); +/// 定位失败的回调block +@property (nonatomic, copy) void (^failureBlock)(NSError *error); +@end + +@implementation TZLocationManager + ++ (instancetype)manager { + static TZLocationManager *manager; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[self alloc] init]; + manager.locationManager = [[CLLocationManager alloc] init]; + manager.locationManager.delegate = manager; + [manager.locationManager requestWhenInUseAuthorization]; + }); + return manager; +} + +- (void)startLocation { + [self startLocationWithSuccessBlock:nil failureBlock:nil geocoderBlock:nil]; +} + +- (void)startLocationWithSuccessBlock:(void (^)(NSArray *))successBlock failureBlock:(void (^)(NSError *error))failureBlock { + [self startLocationWithSuccessBlock:successBlock failureBlock:failureBlock geocoderBlock:nil]; +} + +- (void)startLocationWithGeocoderBlock:(void (^)(NSArray *geocoderArray))geocoderBlock { + [self startLocationWithSuccessBlock:nil failureBlock:nil geocoderBlock:geocoderBlock]; +} + +- (void)startLocationWithSuccessBlock:(void (^)(NSArray *))successBlock failureBlock:(void (^)(NSError *error))failureBlock geocoderBlock:(void (^)(NSArray *geocoderArray))geocoderBlock { + [self.locationManager startUpdatingLocation]; + _successBlock = successBlock; + _geocodeBlock = geocoderBlock; + _failureBlock = failureBlock; +} + +- (void)stopUpdatingLocation { + [self.locationManager stopUpdatingLocation]; +} + +#pragma mark - CLLocationManagerDelegate + +/// 地理位置发生改变时触发 +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { + [manager stopUpdatingLocation]; + + if (_successBlock) { + _successBlock(locations); + } + + if (_geocodeBlock && locations.count) { + CLGeocoder *geocoder = [[CLGeocoder alloc] init]; + [geocoder reverseGeocodeLocation:[locations firstObject] completionHandler:^(NSArray *array, NSError *error) { + self->_geocodeBlock(array); + }]; + } +} + +/// 定位失败回调方法 +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { + NSLog(@"定位失败, 错误: %@",error); + switch([error code]) { + case kCLErrorDenied: { // 用户禁止了定位权限 + + } break; + default: break; + } + if (_failureBlock) { + _failureBlock(error); + } +} + +@end diff --git a/TZImagePickerController/LxGridViewFlowLayout.h b/TZImagePickerController/LxGridViewFlowLayout.h new file mode 100755 index 0000000..7974061 --- /dev/null +++ b/TZImagePickerController/LxGridViewFlowLayout.h @@ -0,0 +1,57 @@ +// +// LxGridViewFlowLayout.h +// LxGridView +// + +#import + +/* + 此类来源于DeveloperLx的优秀开源项目:LxGridView + github链接:https://github.com/DeveloperLx/LxGridView + 我对这个类的代码做了一些修改; + 感谢DeveloperLx的优秀代码~ + */ + +@interface LxGridViewFlowLayout : UICollectionViewFlowLayout + +@property (nonatomic,assign) BOOL panGestureRecognizerEnable; + +@end + +@protocol LxGridViewDataSource + +@optional + +- (void)collectionView:(UICollectionView *)collectionView + itemAtIndexPath:(NSIndexPath *)sourceIndexPath + willMoveToIndexPath:(NSIndexPath *)destinationIndexPath; +- (void)collectionView:(UICollectionView *)collectionView + itemAtIndexPath:(NSIndexPath *)sourceIndexPath + didMoveToIndexPath:(NSIndexPath *)destinationIndexPath; + +- (BOOL)collectionView:(UICollectionView *)collectionView +canMoveItemAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL)collectionView:(UICollectionView *)collectionView + itemAtIndexPath:(NSIndexPath *)sourceIndexPath + canMoveToIndexPath:(NSIndexPath *)destinationIndexPath; + +@end + +@protocol LxGridViewDelegateFlowLayout + +@optional + +- (void)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout +willBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath; +- (void)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout +didBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath; +- (void)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout +willEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath; +- (void)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout +didEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath; + +@end \ No newline at end of file diff --git a/TZImagePickerController/LxGridViewFlowLayout.m b/TZImagePickerController/LxGridViewFlowLayout.m new file mode 100755 index 0000000..3050afe --- /dev/null +++ b/TZImagePickerController/LxGridViewFlowLayout.m @@ -0,0 +1,408 @@ +// +// LxGridViewFlowLayout.m +// LxGridView +// + +#import "LxGridViewFlowLayout.h" +#import "TZTestCell.h" +#import "UIView+TZLayout.h" + +#define stringify __STRING + +static CGFloat const PRESS_TO_MOVE_MIN_DURATION = 0.1; +static CGFloat const MIN_PRESS_TO_BEGIN_EDITING_DURATION = 0.6; + +CG_INLINE CGPoint CGPointOffset(CGPoint point, CGFloat dx, CGFloat dy) +{ + return CGPointMake(point.x + dx, point.y + dy); +} + +/* + 此类来源于DeveloperLx的优秀开源项目:LxGridView + github链接:https://github.com/DeveloperLx/LxGridView + 我对这个类的代码做了一些修改; + 感谢DeveloperLx的优秀代码~ + */ + +@interface LxGridViewFlowLayout () + +@property (nonatomic,readonly) id dataSource; +@property (nonatomic,readonly) id delegate; + +@end + +@implementation LxGridViewFlowLayout +{ + UILongPressGestureRecognizer * _longPressGestureRecognizer; + UIPanGestureRecognizer * _panGestureRecognizer; + NSIndexPath * _movingItemIndexPath; + UIView * _beingMovedPromptView; + CGPoint _sourceItemCollectionViewCellCenter; + + CADisplayLink * _displayLink; + CFTimeInterval _remainSecondsToBeginEditing; +} + +#pragma mark - setup + +- (void)dealloc +{ + [_displayLink invalidate]; + + [self removeGestureRecognizers]; + [self removeObserver:self forKeyPath:@stringify(collectionView)]; +} + +- (instancetype)init +{ + if (self = [super init]) { + [self setup]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder +{ + if (self = [super initWithCoder:coder]) { + [self setup]; + } + return self; +} + +- (void)setup +{ + [self addObserver:self forKeyPath:@stringify(collectionView) options:NSKeyValueObservingOptionNew context:nil]; +} + +- (void)addGestureRecognizers +{ + self.collectionView.userInteractionEnabled = YES; + + _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressGestureRecognizerTriggerd:)]; + _longPressGestureRecognizer.cancelsTouchesInView = NO; + _longPressGestureRecognizer.minimumPressDuration = PRESS_TO_MOVE_MIN_DURATION; + _longPressGestureRecognizer.delegate = self; + + for (UIGestureRecognizer * gestureRecognizer in self.collectionView.gestureRecognizers) { + if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) { + [gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer]; + } + } + + [self.collectionView addGestureRecognizer:_longPressGestureRecognizer]; + + _panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizerTriggerd:)]; + _panGestureRecognizer.delegate = self; + [self.collectionView addGestureRecognizer:_panGestureRecognizer]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; +} + +- (void)removeGestureRecognizers +{ + if (_longPressGestureRecognizer) { + if (_longPressGestureRecognizer.view) { + [_longPressGestureRecognizer.view removeGestureRecognizer:_longPressGestureRecognizer]; + } + _longPressGestureRecognizer = nil; + } + + if (_panGestureRecognizer) { + if (_panGestureRecognizer.view) { + [_panGestureRecognizer.view removeGestureRecognizer:_panGestureRecognizer]; + } + _panGestureRecognizer = nil; + } + + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; +} + +#pragma mark - getter and setter implementation + +- (id)dataSource +{ + return (id)self.collectionView.dataSource; +} + +- (id)delegate +{ + return (id)self.collectionView.delegate; +} + +#pragma mark - override UICollectionViewLayout methods + +- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect +{ + NSArray * layoutAttributesForElementsInRect = [super layoutAttributesForElementsInRect:rect]; + + for (UICollectionViewLayoutAttributes * layoutAttributes in layoutAttributesForElementsInRect) { + + if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) { + layoutAttributes.hidden = [layoutAttributes.indexPath isEqual:_movingItemIndexPath]; + } + } + return layoutAttributesForElementsInRect; +} + +- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath +{ + UICollectionViewLayoutAttributes * layoutAttributes = [super layoutAttributesForItemAtIndexPath:indexPath]; + if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) { + layoutAttributes.hidden = [layoutAttributes.indexPath isEqual:_movingItemIndexPath]; + } + return layoutAttributes; +} + +#pragma mark - gesture + +- (void)setPanGestureRecognizerEnable:(BOOL)panGestureRecognizerEnable +{ + _panGestureRecognizer.enabled = panGestureRecognizerEnable; +} + +- (BOOL)panGestureRecognizerEnable +{ + return _panGestureRecognizer.enabled; +} + +- (void)longPressGestureRecognizerTriggerd:(UILongPressGestureRecognizer *)longPress +{ + switch (longPress.state) { + case UIGestureRecognizerStatePossible: + break; + case UIGestureRecognizerStateBegan: + { + if (_displayLink == nil) { + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTriggered:)]; + _displayLink.frameInterval = 6; + [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + + _remainSecondsToBeginEditing = MIN_PRESS_TO_BEGIN_EDITING_DURATION; + } + + _movingItemIndexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]]; + if ([self.dataSource respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] && [self.dataSource collectionView:self.collectionView canMoveItemAtIndexPath:_movingItemIndexPath] == NO) { + _movingItemIndexPath = nil; + return; + } + + if ([self.delegate respondsToSelector:@selector(collectionView:layout:willBeginDraggingItemAtIndexPath:)]) { + [self.delegate collectionView:self.collectionView layout:self willBeginDraggingItemAtIndexPath:_movingItemIndexPath]; + } + + UICollectionViewCell *sourceCollectionViewCell = [self.collectionView cellForItemAtIndexPath:_movingItemIndexPath]; + TZTestCell *sourceCell = (TZTestCell *)sourceCollectionViewCell; + + _beingMovedPromptView = [[UIView alloc]initWithFrame:CGRectOffset(sourceCollectionViewCell.frame, -10, -10)]; + _beingMovedPromptView.tz_width += 20; + _beingMovedPromptView.tz_height += 20; + + sourceCollectionViewCell.highlighted = YES; + UIView * highlightedSnapshotView = [sourceCell snapshotView]; + highlightedSnapshotView.frame = _beingMovedPromptView.bounds; + highlightedSnapshotView.alpha = 1; + + sourceCollectionViewCell.highlighted = NO; + UIView * snapshotView = [sourceCell snapshotView]; + snapshotView.frame = _beingMovedPromptView.bounds; + snapshotView.alpha = 0; + + [_beingMovedPromptView addSubview:snapshotView]; + [_beingMovedPromptView addSubview:highlightedSnapshotView]; + [self.collectionView addSubview:_beingMovedPromptView]; + + _sourceItemCollectionViewCellCenter = sourceCollectionViewCell.center; + + typeof(self) __weak weakSelf = self; + [UIView animateWithDuration:0 + delay:0 + options:UIViewAnimationOptionBeginFromCurrentState + animations:^{ + + typeof(self) __strong strongSelf = weakSelf; + if (strongSelf) { + highlightedSnapshotView.alpha = 0; + snapshotView.alpha = 1; + } + } + completion:^(BOOL finished) { + + typeof(self) __strong strongSelf = weakSelf; + if (strongSelf) { + [highlightedSnapshotView removeFromSuperview]; + + if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didBeginDraggingItemAtIndexPath:)]) { + [strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didBeginDraggingItemAtIndexPath:self->_movingItemIndexPath]; + } + } + }]; + + [self invalidateLayout]; + } + break; + case UIGestureRecognizerStateChanged: + break; + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + { + [_displayLink invalidate]; + _displayLink = nil; + + NSIndexPath * movingItemIndexPath = _movingItemIndexPath; + + if (movingItemIndexPath) { + if ([self.delegate respondsToSelector:@selector(collectionView:layout:willEndDraggingItemAtIndexPath:)]) { + [self.delegate collectionView:self.collectionView layout:self willEndDraggingItemAtIndexPath:movingItemIndexPath]; + } + + _movingItemIndexPath = nil; + _sourceItemCollectionViewCellCenter = CGPointZero; + + UICollectionViewLayoutAttributes * movingItemCollectionViewLayoutAttributes = [self layoutAttributesForItemAtIndexPath:movingItemIndexPath]; + + _longPressGestureRecognizer.enabled = NO; + + typeof(self) __weak weakSelf = self; + [UIView animateWithDuration:0.2 + delay:0 + options:UIViewAnimationOptionBeginFromCurrentState + animations:^{ + typeof(self) __strong strongSelf = weakSelf; + if (strongSelf) { + self->_beingMovedPromptView.center = movingItemCollectionViewLayoutAttributes.center; + } + } + completion:^(BOOL finished) { + + self->_longPressGestureRecognizer.enabled = YES; + + typeof(self) __strong strongSelf = weakSelf; + if (strongSelf) { + [self->_beingMovedPromptView removeFromSuperview]; + self->_beingMovedPromptView = nil; + [strongSelf invalidateLayout]; + + if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didEndDraggingItemAtIndexPath:)]) { + [strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didEndDraggingItemAtIndexPath:movingItemIndexPath]; + } + } + }]; + } + } + break; + case UIGestureRecognizerStateFailed: + break; + default: + break; + } +} + +- (void)panGestureRecognizerTriggerd:(UIPanGestureRecognizer *)pan +{ + switch (pan.state) { + case UIGestureRecognizerStatePossible: + break; + case UIGestureRecognizerStateBegan: + case UIGestureRecognizerStateChanged: + { + CGPoint panTranslation = [pan translationInView:self.collectionView]; + _beingMovedPromptView.center = CGPointOffset(_sourceItemCollectionViewCellCenter, panTranslation.x, panTranslation.y); + + NSIndexPath * sourceIndexPath = _movingItemIndexPath; + NSIndexPath * destinationIndexPath = [self.collectionView indexPathForItemAtPoint:_beingMovedPromptView.center]; + + if ((destinationIndexPath == nil) || [destinationIndexPath isEqual:sourceIndexPath]) { + return; + } + + if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:canMoveToIndexPath:)] && [self.dataSource collectionView:self.collectionView itemAtIndexPath:sourceIndexPath canMoveToIndexPath:destinationIndexPath] == NO) { + return; + } + + if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:willMoveToIndexPath:)]) { + [self.dataSource collectionView:self.collectionView itemAtIndexPath:sourceIndexPath willMoveToIndexPath:destinationIndexPath]; + } + + _movingItemIndexPath = destinationIndexPath; + + typeof(self) __weak weakSelf = self; + [self.collectionView performBatchUpdates:^{ + typeof(self) __strong strongSelf = weakSelf; + if (strongSelf) { + if (sourceIndexPath && destinationIndexPath) { + [strongSelf.collectionView deleteItemsAtIndexPaths:@[sourceIndexPath]]; + [strongSelf.collectionView insertItemsAtIndexPaths:@[destinationIndexPath]]; + } + } + } completion:^(BOOL finished) { + typeof(self) __strong strongSelf = weakSelf; + if ([strongSelf.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:didMoveToIndexPath:)]) { + [strongSelf.dataSource collectionView:strongSelf.collectionView itemAtIndexPath:sourceIndexPath didMoveToIndexPath:destinationIndexPath]; + } + }]; + } + break; + case UIGestureRecognizerStateEnded: + break; + case UIGestureRecognizerStateCancelled: + break; + case UIGestureRecognizerStateFailed: + break; + default: + break; + } +} + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +{ + if ([_panGestureRecognizer isEqual:gestureRecognizer]) { + return _movingItemIndexPath != nil; + } + return YES; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + // only _longPressGestureRecognizer and _panGestureRecognizer can recognize simultaneously + if ([_longPressGestureRecognizer isEqual:gestureRecognizer]) { + return [_panGestureRecognizer isEqual:otherGestureRecognizer]; + } + if ([_panGestureRecognizer isEqual:gestureRecognizer]) { + return [_longPressGestureRecognizer isEqual:otherGestureRecognizer]; + } + return NO; +} + +#pragma mark - displayLink + +- (void)displayLinkTriggered:(CADisplayLink *)displayLink +{ + if (_remainSecondsToBeginEditing <= 0) { + [_displayLink invalidate]; + _displayLink = nil; + } + + _remainSecondsToBeginEditing = _remainSecondsToBeginEditing - 0.1; +} + +#pragma mark - KVO and notification + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if ([keyPath isEqualToString:@stringify(collectionView)]) { + if (self.collectionView) { + [self addGestureRecognizers]; + } + else { + [self removeGestureRecognizers]; + } + } +} + +- (void)applicationWillResignActive:(NSNotification *)notificaiton +{ + _panGestureRecognizer.enabled = NO; + _panGestureRecognizer.enabled = YES; +} + +@end diff --git a/TZImagePickerController/ScreenShots/DemoPage.png b/TZImagePickerController/ScreenShots/DemoPage.png new file mode 100644 index 0000000000000000000000000000000000000000..c11b83cab127441b56f070057cc735fa85ef4bdd GIT binary patch literal 52272 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 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/ScreenShots/photoPickerVc.PNG b/TZImagePickerController/ScreenShots/photoPickerVc.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1e50ab5287e277b20f6309b0f479d6a0b9d36e9d GIT binary patch literal 333897 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

-G6y=lixu81 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 byJ#duitPCjj@k2^=Qzm*>ia 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 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/ScreenShots/photoPreviewVc.PNG b/TZImagePickerController/ScreenShots/photoPreviewVc.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c5c621dfa57e92bb7fe03363ced96a75ab602971 GIT binary patch literal 160218 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 Yv?aImKXD1__O} zFvhT@RhU#8@WSjPjf{5p>f;f5I!h4&1Y}q(vX@YpcwOlmUqKe^WJGGIYfBvP2-qZR zM7jzg8=D^65N8A@Byi2+0^T|alYAO3tP

j7WZC}FT#wq;Lx$xVl8AMF7N~L zU9Rq*p1;&zb;NF)fLWxMKQo%&)m|7O8EYr1XH$)m3IMza5^wOCO2#o)oFRunl$I260kU)S!9W>##4Z7uJPlB#9ggJ2S}l z2PFtY*Oo50z##+lN8a7(ydSsv4yhNeQnc4py7E0`kArJDhz&9wt|u*{_s2t2RK-1# zmkPSGm)uESx;38kj((Dgh1a;WpmDal%1k%-?wuW zfac?VU-5)Oe#Q2;=*WPQX#sO9G=0u4pt%H&RET@7>YgI*#kYjbt-5mYxQrn;Qy+dt z?1$wWV@wnRuC?V*QuL!JZ6Eg98PpgFwuRq`*(c5vW|s3=?{rYYhk8WE_+T?BQL;hw z9{J8kBK)ov5Ybc>e$6<10%j->cbY^Z;U%Y}1rU28$tlJi3|c`eG~)1TdS}nviDD4- zl?dMO`;1d*VBB$4#pqlnh}T7My3L0OD1%5aF&;CoWt{WkpUglmagb zO&WRzd6=M-LCro#;}YSSejj*E{My#R`p^S8&hsiUg`Hpol%r}tC)wlNH=A>LBQsmx zp+F+-8+m=!!tgF()h>!W>}}<`tS5REYR86Ty)>W+9-Jqa{?{WPI*n%_C-3cWUD$X> ztkIBMJnL8V%a9gj9tK@B*mPMW{mx%5Zlwev$5|^|NtzF4XmZ`HA$e>|ukYw0oP{~l z;46jy+$HA#15-2|N2NaM8~%?EK(@OB1~vnbe7cchJD;s>>^g!4s2&cSN@jC5_&3WU`kL%RCG>+`5Cs?Ciq}je)g5x6u0R`HbRaW0D z?wt<_K;VInaPg|Hc?ZbY;HRp8hkQ@M)~Z~dy{Bl`v5k#Rq8Fr;H4woUZFv;nM#l59 z2Ivbtck~X+_8V2nrwq=hU}8%x>}_|Xv1~X8ai{?a`{25d%D|BlB0ITQYXKr#LfrYC zS~tO6j5n{c9vF8FoA{AfC2m2bM-!{uZJ{SZ5Ftyi9McB!XE67`CgDpYxCq##=&Kpp zEVAEk>n!#{PcVb8GziVy#C>P3L)b@h_RLW!7>W=r<=T>!xZSmPBsb6O?7)0i(+(UI zZiAo`c*hLG-Fj%E(jd?N*CSGwF0vunxsQ&fz>bCkwMqr>8}rev+K5Fh?X&Y_X6m)< zR}gnAo+zgFKBtX|UHjQl@{5%2F4k(pU(HU077uYbH~(a^GsnTRiE|Zk7nYRtAZ*uz z8D1*G4+|mV-UjoHi3f=l_$%ig%6mSZP$3NC6>%@@qDEJVBc>*-&v|~>RzyVI(}@dr z7Ufkh}4hNC%j}5+LEu za_VW=d*o$6#?RiHDgw4AEh~xsorxP28J_Vy zO~5oS+np(4Jtdv5HxyLsWYLA%(0O0?C3)DmInAriQwl1tb{;(tcPyDG#U64GAhvFI znx#wFdz`U#MiZ#M;f_=~1t5op!QMUw)$jm5$n`wgiG;Ig#G6uEo}M!)(Aj#Bd(Kc$%RIEZx#j;57%;tnM zG@VM2$>NV#`RT{AZ*&f3u<_VC2+Y85BzKnt%>qDD_QJTXiyuH&ly!uj_}+?NR<-(On} zmwMe8JF=*IKbTNXrcvha?rZ|NHR?|nTLelVsnChiF#6!X!KsH`NJ}g2@5uFBL?Oud zK=js!h$cDFxCqZd+B)1ZYCj9EZ8adC&pX>c+~}5kcGM4h|6nXRBv&2i50uxgR}Hv5{`HO4O=Mh0|H4xm zSE}gf#*vIS+IZZF_3R4DgOwaF$1PJ&E=K3525)7YLg-Ov^uAa=5%)gi}N16ZN@(TM<~7O%2IEW1sx1Rgv3AA{F-r>9uNZ?1->er^zf z41IJSsa$8noG&y3`7c%1k|Q^A1^WuK^p+^v_b8MWy(Pr#ftL*=+3?aplZp0TOwis) zkQaS|Cdk=KsA^w8E!|)aoT@EHkxov8roBWwb92h+h=%KL!r&u(6!hvS{9C4x=#i$jdb`?)Xp z1UD7#$Uf|86>JcjwRoC(O)Y;o$?{$M5_Ul!m))Nf-*?Y6?wmp2t9SVrT8Hy$r`QnO zhn5SkW#n#g?eoEvhs7dRW6f$oSIe5b%9_~Wf=D)2O8j!}KqGPPiwa2fPbeF*KIPFT z-<>V*!!K%)M`-ZJR2mobwA=Ud8 zZcZO*tq+Lg?tgFpY+F0`Fh2fm`x--UWGLj-%uuKD0Nv^eka|U%iW{D`w}k?^bDm!q zWXM`^$*b?7)2<1$Wd}K79|epN=f{F8L>g4V5&)FG2bLr7wqS`~Uk6NWDVSicBbP=^ zm7=^k5oUm1;SRjMeZP2-IHOvTPHEyB&HP_VEpVCT9K|GntF)kiNB@m$wE)J!oNsW6 zD!uo8Qi#JYuNBIKtTs*4Vqip~5oq$;H9ohbe)S_3?v*gJo$tMFxGNv`-(SCW!5qpu zvxzJZx9Gml3hArP9ks)DLE0^4vKLcq_oGbzNg=Q`pS}>ia+RK11+&Qak=bZfQwH1C z?|X$Z-T;~g+p(LL{d!|N%Y(r(SObTVf9X7N-)(Tch~BHoQ4&{)Xj1u0WW0|nsLJ8- z4vwkK6~LBMO42BcQb5{Hl^?gBt-BgK1H^D{+|x>N6DdOW3-?`12Ts`KiDgd}h)Tbo zm*HPOzWF!RmTzhnWer10FLn8Ryc`%kmT0FIL>_bCs$nz>VO?u(=e9ZiSih%NR!bK> z+0K@SVkL`u7%u*uX&5KEyu{X4IoHw9-*WcYj!gk}Nvlv_iT7)``+~|y&v`jdHdA8f zIqb#{WQs9d3W3R+6%_ zYF<(&hz)k0EKX=tK7vB2vbI3;(ZDu0+-q|>u zA`!yCi`n#nbI*)~A zc-5^5&I`bUfys=NgZv@<`}?B}Ke|m}iy~|1}Idg*+{QK)S zoO|NA)@%8I8cJ9z2Je6)w<=oey^?F9s#p-6?8g>i~cdqeo z_l`y^)39&&R>;i4nQQ`2ONiIYE4dqs7djLA=7&dD%` zKBH=ANF-lw9{nC?o{vTQM9K#5GRG<|iC(~R*JsE_N)tAh&g!ul0smMkLaIWiu zsQh`j;?6E>y1n%|VhLvc=6d08`YYN^kl`8 zh^{9;bK06r#y3S6W{H`EY9L&`B2KQBOD()F>bA(5KofwHh^zq_TMa%MH_^f{*tye5 zzIEANYs{XbyKgmm5eLV`Fy%w<5*XkgmKZV_+z(S!DcRE^2lL--jubOSd^q>FU(Y?j z-H7{0q8t<(pR>rj_8Ii)l5D|3;s8+VEcB#0_o4sL%IUP%ni-yZr#0Ht3$7L9FOm*^N$nvoOxP7c|aYM_Jd0gAe{Kx|^xVkp|b5`4mKb9mhJ9V2l#9-xcRQHd)ABMoZa` zHB+kf;6Gb(wn3{#hMvRd#Csz28l^UE(-(@dXF@iFm=N1dDF^=5Swp9l-JyEfOL+;U zT{ca?B5C|2Be#&&i9v>g zPGwe&4`}H|E!hv4GGE|Co+mk^MZtn<+svW5C4H0Ue*4*ANcTgr)rJb;v>{(c`a-#_ zMN?|@NX4S;)M>{Z&D;gKE716OzxhciewlTp?a3#81QUiT3Yew8<46OiE(m*BjZd(N z^)_SLwGj?k7`wRU8MYH{bvQbCdt~J2Cb@2}yCArzxc41zf^c}NEj%|ufoTm~*+#Rb z)tc85P4S#0lAF66GRx{vJMRY0ecONUt@R-MLd*d8-X^GiT^Mt08pWZWi)V}kk}R4{GJ=0PPo3AhB8JIH zP3JDXHsh}84xUZm=%BXZCBG+bAnkkSs+DtJ3?*O=dj0W69z29iS&kwSiE=jeC=N}{ zl?#ow6rIW+DMyq8^#maB9eM6iPU(!=a;F1d0$^U-Q-<9SW`|YF-WW@iyF{OW0O-CB zZg`vR%ojm1&dPU`OYmg`~6;fBwr)5=uDSVD7CAYZN?#9>KAg@9F58N^2up z#+h1cZ1Ae?t2;(oFb7~pQThgB4&*6EWq8;^JiGGOW~3kr1mVW5)L+z8TSD1J#X2!9;i$-SXtP8T;_X zpy4ZLiA1s1y-l=N1+dI$x)E(6{^RWhvp@4Y?^t6r2jK8e;u z?BrZvS%?#=kQg^6zN$OfUjtaDX9l&_qZ!R|@LV1bBdlb^ zFz|loZMFGI{)M2oER=hgA;FHkD-Ix4Kxw0*wc|8>=%28>JCe4~F)!-MxDycDeP`+3 zuRcqT&iTh~8_{6NYI%?M#7cfW_ldNn?Xoe>TGi3wz4R!wG>37(aR9rXlP0_sd)n= zH4b2s@B&PNvjjEq3QSaOz$iHzh`of)UizKy+{@A+NNhM|)#c-T_vieC>axflA5awM zS)(ms_s-cFSvRC%KT_sFQcrQGo;O5ENExyV$9fH{-u0T>J<1`j>BTZxU2EB2z0sq* zDxKy1L?$C$QMKTn(fhDkXSVjHHI*zL&T-li+Q)m&%qf{k(S++ki8|CarVz~l>g(#A`amlp zxS*@yZQ@4bj&b)Y(t4-L>uX4jk4WexXh8d?_k=#5c|$k6#n%+foXI{r(FSO}JVG%F zh4tj}3*=6R!WJVNCArRh>LL0ivKDa-E>DZ4>rXarcNfmVaw(xe`LjW(ouP>8=V{n;jUU z*R=YQH_pG042M6y; z@{+ja#Qf>-m-gjo6gc5&s7>A|9@~utD)P+p*K^vrf3&Ly{;SDP;F>0Y z7^CSv(K>kNIB9}v47RqxyV@l7Zo;8Zd@_)K>L*{MRSo19lnHiOwxwY)4hA zTTPiJwtVAl4en_}+*{l{J1M8UYVSK@8QiLd)XQkYnLM*d#^fd{fMNIfdRC7@!KH?q z!j1)n;yyUKSPZ+Tt~k#z2Tpkiosfn7gMg@Aj|)0YxM?0iEDI|~&j}pybasclV&7iJ zeFmO0>WZ*+l#oTU7k$BwDF5E)y{i}-ms7Wca+b|>TN7HlUC0~z6vd3-I<+KF`l)8~ zs9p(G%U~&hePF&xOd?gH)NrHIqpu1 zNk`jL`a3IR3}Mfit7}5js;4&Ly(9~Vk1=`C&ZwqsA{Q`qsm~Z?V%XX}7zIqgG3msA z)ov7YT>3gQGnZCcT6o>+ylZo=19Od{>ndRCr;;_~FEq!GEn&Zso-wPEk833ad}_Lh zVZd;IC9(q z`9Dhv195e^-Ha31eUt91!FX%LeL-PwwujB^MV{_VG8^Z8@FhJY?LJjL7zd*Nt~n~& zm^BAJ;$B;E>;cu@vz>!fPKKrtj@5N-!5UubT6kmKVlf_D=6gjTkp9o|i!XXklj=sz zL0DUiT#Mm*TwyqGsW7C6fxLja>in2>nY2ci#~o(xPBFxH4p)3bm8Qa3$t=mesI-=0 zqEUdPH3UoSQdf9LIstpQU2l05CVvP{)7Mbt2_py#u{S4s+YM%k^+(d&0{8>3_9k+~hBe}sXg49G z3$pCELz)W=Lmc-fRgQ*4b&C7Q+^jMB1NdQJA;4*r>}H8XnuB5RU!f$Rw?$+xXw-DY zt&7osKUxL&vIdK6B<^qSu`hclZHRs-_Sn^Nf5$ze9$5o%!!03U{U*-)q4GS0^OLgL z*y-+1jo{vsjhq6S zG}4;YH_MCl7!pGLXdr6kxWDw>=lzpPcfeA*#2eodVum#Wg|Wi?^Y8zCFBi;{d7oc8B*E0kh}iIk0j!;1T;uXmjGtN=Dz>A(Xk zy>rz~28x>~Eu=YV5mJ^oJx3m-m6Yb+%0}SOK}Kc_g!glbELbT2A?s_tRjl=csUK1}ve4 zE~Px=!KjI1A?Qp$1wFs((&I);){ssEt{g_Z{lo8nuv$KUOv(MEH=z-)0WuEh?dPi; zqP7(wSFR=@`gbf3Zki`80ot@={c5@{5d4mMD|o0iEKtfq* z1rsCpuD{-B{zhz0X-i9D*g+>=h0Ek#?eI8B@?F@}YBCNsZ1xyyHsUc#n;oQx(g{U< zEJc%RV`qG4~k2)n<3*OPUAGa&nX7QXtrwqa$I~ejW-s?~m}brb^4D6Y zKx%2IwvE-cb(Wx_??Cc)_ovWEM-mN^YCCbaQ^QxJLykRBE4;;TFFh3~!|e z8^V@-$?s36kexBJ^x5{Nk58wRBJ0Q5Y|WmYRkzJ9Z)c^sJX#EDB zo5S3T>}h0h6TDOQr}W#~lEz=cFm$I6yvud2x?3$af~mB|(08DAQZ6&kxrneos+6caDQL5h5f)KzH{_t*V~aU?SgXYq zLl-T!2fN;PCEU)HR%$8MK{t((aJZvgWE=oRsS8gUs?QR4kXf6D>Eo~*Ho#gb1=>*y z&M6h#1}n3ViKgcaqfZzk?2C8a7Wy%!|8UCkA=paiLEM>*?SX#`#i=GMNIz*>h#pO) zrg@j&HS9pP@Z=73L4Ay6-$Q6&n=yO}eL-mnn5)%Flf4n$MR|tCS#6V#*Q_?L6bBY+ zx&P3Y?_l`_Fb9Ew;MABGOA{9G?O^lF)mUqG2P+!0nw)xzDa}t_n82v&NxtqtOGo8* zrRhEl4JOCEeySL34A=p~7~b}@=Fn390^y?^;W@S3j#Zss8?NScWqtv+b@2dGJZ=a? zO&fqF|-k~p3z5CX4mRE=)!rTTwu&2pTiLt;n;JCV?O1q`|(4m1Pu>} z0Ub<PUk!;C z07ohbn|OPmhnM$2*p2 z_^*U*Qdnd`0AYX^1mLjLBc+PudfMDzhZY^)&%tM7%(9NPRDf))6^BMsV@`7H5!I1$ z>}#?6Rt|2L&7b=H58Q~Xor!y?2PfEMgGVFQDe||ZfQ8sWBZ)vhjHe4p!}Y=9)6xfq zto*U|b-|4l|F4#QX%GorZ}0-krW^7lD>u)Nzq;4kp<9`jU9MY*yQpuKF-Uz>n3_i_ z&8Sgz;6uXq@$1LRfIi)8^Oz!|e3O0JZo3dyapIFh6d-W{!rx*fe@F$W`d8eWE~lLt z_chVdaE?gkOQ@){U6^!OEv=Lc-3wPXL)@!@$m^6K0vSH*TPiRyOfWFab$>h9so-jE z)|y^5)V*Ur<(9g9NlgI+S9ny*GZS~lIUCQV4{Hx!OP9S@iFkLhDX+NxiFv&#Hx*Q+ z(U8JvdN{&<_H;~cluzaH{O9Yrf{xt025(E_HT`hLNB{gj2&v5=&r%{wSorFle!c!= zc9V^wW$W-_Xwy$e5mnr$0EhywfFe--se%`BKw)NjC`y_M~t zgft#KcKA6)2Un7aQkE6;MYfq>PX#>1ERA6b3eIfiZ|jZcX~?)=cz61D6@h!;ep*7M zqrdxHbpCaJSO73*uq5Qpc|RZaoH)6ig-#WE4w-7})7h9^$SX>%Qd50bjbldHBF-B} zX|l*-sqm!JEQsOsIce(plswP|p;SY|=G0m3TKvdpkrSC+GE48bjMBjBAx3l}*Zz=Kaoc z7!uj!$;ZO)z=!~gJt^q{yHLaNvQx#s3hQ|-=bbrl@JclY7JxCmf>g$_sA^eGPX?E) z)8`U*A+K(%j;GbcvhBX7x&HbgDcj3F<#1%xgs5Um*CCc$F_&jUq)$<@Rr)fvvBcd3 zuB0qlaaWF-BCvtB2!W&@-`7~3w(Z?gg?zn^VZS#+;g+7XnG^ah@P?K(0ox%`vpTeN zdtSz~eH@kG4TRtAiZehgpAL~9CN`r*JKHuj^)OoCo}FYX;P{tMe~^-!hQM}=l$_qz zbC6jcv5IS>`PH06SKt-KGqA(|Gj%q(ksC=A?z0#wA4E_uYFlto`vFL5ZJ?8c_9GJP zouOIu2}Fm%)ix2=061A&o%%Sw<=1RFI2RZQEJg&c zCE5Y~L5qLL`(`zSpLdT$EdPcubBm{9;FSq6{g{e}n=TddSaaR^eI^Ok;!x=hAE26r zNU@Hriiu(}3#n!|qHZ&WA>jmP#})nx3nX$ryoa?&M$eE`tje{CCPl-O!ph8*g%mfG zEDXZFB!iN0LRS$}p2}&OtX{hMWV)mg-hPvmu=XG9!F z+ijE>#o__q4(*o&K%f7H1!yT-GZMjkFBX-8(LDAdevTaglS#0> z=$;deq=qNGxuyyE@p zQB63T*sQ7FPxUR;vK0PWnHSYm&9QxokADR==mM&X4*pxdRnM>VG`G43bJ0#~!h%g1 z8&r1$6+E6@KZFN>dNS!|-#@fTfb51#`KMUpMI|I6(uJ_OiWAS|o`&}wEd#g{U4=jt z&9eP)9GzF{-kca9aO}wM(X=D1)|uA?dBJBZn(vpUb9c($I<&7XM0bc6M#`pWF-M2l z<`z?{C^`lAwL@J6!D9qGmVHgsJpyr>TisJp3UtY&5(nw9nmpFMej~q~y;c2ncE%NY zyLXVez=xvk z_>=D4)fAx_;_DUaj3QX_U?aS#=*HB9tM2)QT34Q5-D$1#l(FA#rx(aHg;1>z&^*DZ z1+*JHCwqk*$4!2y*}C2)5}ghGF@A5XVTUfLDPg{9AO`YGtJ{D%In`lds8+ssKbc^n z9OaU5(@BPue6y~8?RmvB{d8Gr@;iz+{o>N>;AqQML@2IAp>2` zgt>G+gG=47r}~cv+n2R`FX#dBgwyv)-8+e`CCbZB(lXm)nbipWFPaC{eWUMZZtUca zrQ3{t?rC{B+7lO6`V+JGVe` z4eR_rQH<>pp67(WNEBXlUlM>TYDq%QDta!jM$=aMjRG4(x=*h8w!W^otLP)=Mmu-y)8Qe=cn#u;zXtbw@dS*3LD>K{c>zm>%vrPOXh`f;GzS#UUF0U zI65}$z6v*k+6jL|F9J(q96GTLUXaVrXsUX*UyDUJQ*igYQ2*xZNYF`TUkcJJI5F0J zaothSsjRq*sbc|0OrGJJWcHXv(i)oLx^~@t_9c^R990AB28XbXwVvtJ0xR5JM2w9u zj23XQr1Ti$Sf0nYQCfkOEXbDP0?I8EG3JvMsthacHJS(#9G^K zy|RgyV%`zCg32$-g^45{t%PhrF+wBvunBC98Ateb-}qQVuZ2IGn#<{AJUCq*PT=Ie zP1S|Zzy+h8>QeW3r=ft?kzLSqF)?i;&R^d2$2rqjFj6kNKDDZQ{!3Jc3bs|(#{QfR zKDl@|uEF%R?gr~3jWvIVn|_>j_i*+g?G(U{E>@FC)s`DsdyZ5V+%Qv)?@8y(g~EGi za`_crb$9;HLHsWa+@>$6UWArDjh3^_b4i>IaFY3bDsJl7iwr=F7S7}u{&L^`8))0k zq@f_y3@$?o8*BC;4C*KH1AVE`l>uz2jafk`rXW~wwo~`hRhTgK=yFFh=@i`96WOzX zJYdFr!2JGjLG?eV`^RQaf|vx?-OE_PN3qEfMX!%#Q%&d69Gv`MUz(HOd@&kmyCZ!& z_cN;ds|$aQ6GvGZuirbuZbN@iUopEYl%SY5hKS%9&8iyp^pDY<%@LI`3y`OosDr>P z=I-V6MBVirx$Yq;LKep&Xz;qiK=I3^vL__;o&5uism|Mhxl1;XL)6{RRel0{*F7L= zrfQur(QYK+CH54!CB(Vz{J$5wNv(lI*hV7%9{!(OvjeJI#a6HIc>U4YJbam7s|qZQ z>p=ACZ+GV}C%n{l4-%N(-B-4u20c`;O3@CI8ZeRO%o>~H&voyR^E<6U-A*n!tA04! z`B6K8LTmj9C)LmUY|>NssL_CiB7ch4NE|4^VqzS$8mWT*O^e|rOClqvHbuG(Q@Pyr zwi7Hcl$3ge=MXoLkD?DO6d^+T26!siG4BUqRrjob)tM!aTD5VA#X4`ly*Y)pSBSJv zCRAxQ7;aI3@ElUH>Oi=}`5vqpoUrfgQv1D4zgeVktwPxXT?iUh_q_3(Sd%_>Wjo38 z5)1(syfNr)42MI)T!3}bk2?@gJ@0d=;u^jHbVeOY>TyT~y4S&->#iS>dqbQ+xcRg= z)d*pdlBL64pjp}v=A%kOS;FsjSqSg*as$=JB(ySgXlQe+ZrVbD>D)(I(%?{o!t$W- zA)2yz10kRIfmFe45cqS%sJ8)^NrDRvKh^BD)xK-@aSl68M-2Y!;Z*h$S~n4i?scvW z7ze#BZTh+uo<@eiLjl+G(+v!w^3nU#cF+I)<1gIu9csD$qadQ1_uRt!U)^rSnO5dqOYB3Dc)=?&@k=!xPKL zxw7%z4ROi7f4uW8zwfr@o4YTXVL;M?#ffU<(7A!1!KZi3tJ%%=Ljvvl_FD3*?7wpl z`uiXk5_xQFWvgmDeqye_mW_SE4w;>tNOTW~wpSwD%_m4;*6>k{$m9xH&rTM~cRH#bs z;@`SxdfBHs`F8F+^XYuo+E{KKD*K1Rz+?{>WVtd<(F-Z(q)T*$PXpo0n5N{dsj*i8<*hNVi?&2n6z;KN647zM+ChK1Nlo zm%2sB8re9F+DM5ElvT0Ke$qepRYo=|o`by(S(i^)?&#u*7wAK@I{)1}m1x*9Y<&kXu&q$Yeu z>Q;EJE@oNxA`Hmw!gc3nou+xUTd1Dm{D%b#e||7#<>x(JuSd3sr5Aoa2lNW4uR7`; z`&171o|Jg?I2__`iP5AJez%Ai2Y(ws!7`Qld=Co26^`KZis{#2Dh^|Zt~I%r2bC>1 zKnMPQlwM(ocWNVZZG-`z?tbroG>)h7O2=S#6QUB)oM{$jv|QB>-9MzJT{nKK ziiD5)ICUE@%cxUb+0fO8aAFQ!7u~Q-UXqq+|EB|!rKQc8edE9DWki~;9r*;ble}5I zMy{4w!hoWo13w{raBj-yV}mmA|*O6)*fs3M3HU zv5DY5+$Ea!03pOS zfZQv9a1Z-R{{2luk*LsZP@_tyIQL#+Ntv4`!B)je0ZL@9^XhMb*+~vF>{NzGy$$dP zgZmHsg4bde40p{Y5l+7q7L$0lf&`f20yKAn=e(#_>s|Qovccx)Ik?QrBSmBLf)N0dMcnY+>UdM}sufDo*?n(ZZ@(75Fq2qpe08>D$zyG+YVwu6|(+~kNn6{k| z)CHwDRQu6ja{1&<`YHB+LkHftPI0e7PDF9{8WcqS@M%uzeP!Uq(0~6*)KyIiDfam9 z6H?Vj6@aov*#~fYCJcQq%p@fpjSI}O$!&MlE`H;;nmU?ww<*^BJVb#fQgw+ zy7@2n`-hfFgY$(x6gf<3Y8-+t0WHexrzPwkl>^sIdevj@*>3Pkd54M%(lm@2@H)C` zgxwFw*QPAW*$>+CY0VcdLi@)eReAdtiLO;4)@W9A59OsX5Tn-KW0|#*wP#e&npWfjazv%cEcI5P`D$Bo3QJKufQ!r(yyjx5VJ-PR z{7QH~dNE2;qD@s!2@tKR$H<3$jFq5md_vu3hJEzJ`LH9aSLgG-;17Y+G+pwl++i$c%{LU{jk z-x=P|;R&|BzOo zLx=tGAaS5Wv$M9K#4>QbMdgMbu!1uHy0W*Tl-YxpvG?E2v15es*r2hM4gU(q{aIA3 z9e%MRMA#H}U8?E8Q!k&=e<9TJEAOQBdUcNb91?q$90M$t{`s%lIXjq{WBVC*Z#(pK z#}i~IBS4SPo-%*casT@AhjY+lA=~!@s^O82;q+-S=C#E}d{wGyDW|}5E|g{lL<5nx z4vI?G%^~ezC0RSE`Nrn@TI@JS=aha|#rA$z+*QeQwTA3>a2+%1B> zGb;1FeTil0UXz7+0O(|B41#fgitQ-M-ut! z*oX8&U(TM@*BubEzKV)kBk&aWty@yW>sJ1S__^t3EyG!^sKYRClfB92sNxlg@pihL zJ$$sl+0zmd7BJdEd~ok}wFl5++^!-vE+Kb+JuAJWxTmn+Kcc2wPsishbwA|gEfu^v zNUiZ!kJ}m8)nu38996NAV4U6XlD6Nb^mw|3K7O`^=NL*7si}JHxnJAv`xn;;wqn_& z#*kn)L`7Z1klmSj%!FcJ=$-avN|FBm)7u(yfrSClyW%06q8|1p^X?Cif7d$o2*eZ{ zzP8o@FEVi5e!kY?_IZa$>9{jdUEM`ja_Ga5GP)+l3~g_<0vy(aNVs6+ntoBjN0y0> zbhSaVG#zaHXTqZaAm__Z<9y za^_4O>!a-m3M(@NIgHn}aUELmD)u?W2gi?9z9}I>WwnS#A}({tKFpw#wL}zyb!P1; zzi8ZZ9rv5+nivYF?{^CEW7P^vD)Un@BI4@gjmf(d?DQ!i%Ik^lGNmP?@BF!}L)xfU zo6JNb?k8Z)Yd>&TepTgR_`p@lm zQx!43U~*JH9QI!~*6<-T8>G%IJeLJ#jbP1&0-+|i%^N@`=yOugsc3-kA;2)BiCyuB zZ)ah38Oij1*PliPP%hF)?l2p%^!wZqnsorVipbJ*-zLMr*jD$0=z~ zG$n)3&LFu#5K}|#X4_V}!yEH?hqa+ZHlD8M5d5Aui8p+RFW11OgzXtFJ0*B_Ou|B* zl25HW-qKu}M1D(ohPEQ0!@j>yf*km5cdn?cb$3J(O;O3-5CG9fqa?+5~o7#^nU;N2br~D zk+Zj|{Q=#rc@|cn7@v2=x6R^A->Tz|>2~2Ndz>Qfs&)I(n8yyl?YjJu(9M{A<-$=w zAWq_bv;huKS6FNn2&uZw1+}1LgGtk%Q<>1ybY^m8E1V5{zL%HJ1HUg?RUT+#mo!fR z3Bo8l?5_=a{$@J14^Y#Z{~0EwBX$6xFdEsNhvvQV+)GB>!;BR7bM~W8(Y}08$;Y_h zWGfllOX{LaSMJ%s3&ouoyz7$Vnkt9puj8vchb3CQ*_ZWM5VN-Gp4$#m;U>s$G?EsN z7j;$R(Mte3IaqJ_jZvw`r=skp`mjZHnvU$kZ_8) zE7M%5;bUO%26_m%cT>9;UM|u@al@eDIDVbQsCFi7mh*i3DkBwg5*FG{6{$FQG~ zf7pkeyIseN^6=ktW5`}nZ3;mSwQWv)GhQ{bavsNIop-t{1J*LW1M5%_6+DXJ^Cmu*)_+o(%{|fM9PHR7Js| z+{Jfd<+T*O^zm%FNm)56yMskjNr2RBm>tNCK2^~B-ILuu)B;fU_oWrBH8>Y6ESS2* zk;c%t9m4wjXTN=VM z(1u4Gp@*%Kaet!;{6RmFQ%z}Jlgy$hHbIygV;L>&)5ELHW|sphRC;SDrv3xPa^68Bx7}h)Qpu?W~~V zz4U#b_gws0ilbOoWFIc)o}c$eKbWaEQM_mS;_FRb+rW}?61M0=2k*HwICi&utGGy- zu$sU7VXC$&m?K6IJOddi$sqM?kKdC;faLAuZ1ahQb?r%im?+gnVY?u2*J6mK{d`@2 zl#)hob~00yZ+G+L^^#A`&!GNXl!jhy?`$Fc1=VF8 zI<87R{Ia+AQ)P@N9bZ5(`XR@Bva6H1<5cNOh#zk@EZf$3w~n)dhvFWCnJP<+RE7qE z@Yp$(W_?tlu4*{^UFhc#;j@yu5MwfzJ@58zigp#KfHLbf!v-|$4H`ao82R*M@GJ1& zvI*{mg}8BKv`ii|!t{v>FT_Sv))<{EyFUaoJOm%ZS1X2%`1(2VxA zlNui>=#K&(H+C^JJ02^RCUU!;iRbTU@{D4xOs}{r%d4>WRuoTocl~kTE3XUN&U)>Z z+c|lI$V?(@8%jYkt!Z}_(>?qpl%ft1h zE>Gph?TQ4X6x(ZyF3X8oy_9Vs4VrI^u|X^Kc-B_C5N#Fn$l~ycqTKLib)q-WOK%$W z3Nh!Mk_dZ7&^MNXY$?;IKuVZXJh{~+(KfmpZOot(o>#n*4?!sai zcY|zm%5vEa;R^l~_UjZnd|soAMrT9R23amQXNOb$kN^B{d`fYzBktHJ0!>DD$efS1 zyL*OAmIVycb$UJ(mvf=U=_pQhfeTGFe5oV~TL?|P%i^6Z0Lkf2#|mhd4w#ic0(wk6 zAG>YuS}ft-fK1g^G+w&V zFt6EN-CHLn1bX24noV&RN&8TG46jqEq9&vvqMkWk(qXP9Z$(42hdEap;1uQS%8)v& zm$cjQj<4$HF{R=??vZ}#A{vdl9U|@+a9*$UstcP8T1Eq(`_)Ucc~vSN%{4%ueIy*< zQf<93_D>t=Uf^JB$BK9`G`XvE=?WRHPq!7$piZ(kWXQF^0huY`-J15a+HWXv<+xw53RzvVW6u+an9VSL+-Ssv zZ^htL+Zq`1-ho=jtttgqLnK-RWXN^ z;mGaPengLA6zECB+>4T=nMV8v=S?FSbUTgB#FbQwklQ9%5MhTN)9*g?!?!}KAZ~}M zc}Q^=+Pz`8e8ryWgS0(l`z*UxDhd6%jYGB;SjJEa?ktQphEYy>X6ttwlUhDQfCaWF zV{@ex%jzukF8+3R@3^Pp*5a!$q%%=8X;%weWlL3GzNz5W}@fc=I|(0rn? zcW;|Ms|#kF9@`V|tu&5Dkubf`SC2tbs!@tonYQ5#Z2206eY9-RkP*O*O6YC1^wMCB5}xG)w(cz1w`EK-L9j(%$6wDFE)f^ zT>2fPH_8n00hC_W?jL@?zVPkVyDIC<*uE2;OrCjKc^r;EBy9y)?@$Jkw6?8c{wPQ& zm>n9)QJXM!f;FbEr{i3QXeAco(>JG?qo8`EC=0iudSEEFjY7f)Ds{ptMlh~e(TGen zyH2`ZkosZWl!JvLU~=Wz?8+!dL$%i%+K}_h)0?1lF*a&(mhle+0okpp7Z~Vl_ucMs z7#OTZB~OZbpiFdSw=84nSlS$RB^r&98!I|I;4P**LbdAC`=7r&pMe$GSiMtm&$6`V z%PCM|DIyn~!^!c4)8k5FJDMN?w zAEZqIB?M(*u$qvur&ESsim|KQIJ(!X;{NLvQb13pS!(LbE05icOg=*H z!(C92U^784PN~v9g)GWA0pHZsu1CHwXS5TY7Y8h2_eNpQI>!oss=Xe0{h(Cuyu zRi+@EPmyO#Z{D)IIJ&~2l(&w-`yGdnX{{ScnMiC&*mwXHN>H+4)|LDxC3wwrmK2?* zpNMpe9n}~Gro^azX5OUt8XcFO-Pr9)R~-;GO=q$-s21GbJAwJ1S4vvmH>>8>q?L70yi;U!Llb8OSrtgPC245UQYAjYGh{!YJdzk)} ziu;q}SOsGHV1uZ@Kl^H($JmM&p@KqHbTm{lm6Ia_^vqq=vULvSoz)U6DXI&sZ$>Br zV2del?4y0;{DPIaAW}Gw*)!JbiPH4DN7X{pZuhkqHs=^Hfzk>?~@0ZI7hw)U$KYvo( z3m?gqNF9f;WAXdsC5hGBZHfrp#gE|ZWF(LX4BZ<8 zSHTgrLXv{@%wAh@zx~?A#$YHbuWU>ziM#I7SGBCojQ24gsi2uHlK<#ndSKt7vnSZx zPsQEcT8OV8#cmh-wFaDh&;lb{8w-ln zgj?McmS1I*N}f*(?>4PW+EvISJgneeffFp9npQPJUfqt58eCq{YPdo*7Mgt!@#zKw z_7yhfGFY9(RC{q~Y^=zZCR~nYYj{U&CbW!kWp6D3#SRe(1`kGcNv~uVWIeod35|fx zrcQnK<%;tjvJ+iaDd^4btIa#Om@Wwxy9{G1k0*_;lQL4_xmIwLN^26LJ4RYBqi*-L zYT1n@q?c7aSkk*Vg;5`AEM4z%9UIWXN^xIE>?pb`?!SOLkDYRfDtdd&jF0J{BbWhO z{_S-W-eusMSGq2RT_vanh|>&WQ*){z)K4K9wawpg`u0a!*Q^YtxNm0hEuFQAG#HDx z_kE6gXdU%zZc#|;qKkDq);CX!U488Bq#_Ccb;?QdJ0Q6$n_Lh`jp?M5hEsgliDlz+ z4mgv=K!O#4n+QOjSxl87eweET7+c%rZa1{I!4K?>33X5V%%%c+fLVDVLB#}()fzF_Vc!8V`|)A8xTDoac_|_q|Pb5 zPJy7&+A$ZG9tJ*)Lg%<;DQ@-Z$)e6GlmqFW3r#YC3`+YDBk2v~qWtMUmaSM>sgA@O zj`hcR=#E~0WSW4_J+3US?6vnUT$+gMR224H_K@;J7TJ>Ah`DxsK$nLI3lf4t+{Ezu(^f7{LvzUF$lgYYnQu zeYjbQ)zR3B)e)Y}LJY8}_Dm>@2h?$sZcddwIN96!_AZ9P zpFd(MyuZJJzM+Dbp2>o{b&vp5njrn6xJ%#tacp3yswf|n!q+e=iUER&+Ey;+Y|PO? zEfYpBUVaewu%A&9@b)k`y)753Ex&tsE)cBJr~1z1rhAhQo~vTNRXOoHCG1ol5B31s zM_gZD{!i7}^OyuZeUrC>CdghugHl!?dk5~l zteaSiBc4xsBeSmR1#pJq95mnilA%{6m6=?#eIOpj%dMKXQ#J8rb zimDrFa=U{~^t{{t+xxzU{g54g{TeTs*#{C6WWU3$@J^h7207V#FgIZb!_)whZ3E?Lf>KmH0N`@UN2 ztpp?V5@+LHWY|INI$xg7WAETZj=N{l)ma(NY=PwM<*$bR$yBi$=RGcvFo^Rc9CZgy z#@)cUB&nj*U2iAtMbBM(YIfFQA&KYPOrpwFq{$@YH8=^(WpA0={n2w^_mh1bU{PX7j zc>lO&A?d`yET&MOHcnTj_6<@^0IYxr_9^T3H*2-A&05LepBjtt1on zt|yz15Nu*`1H+%$*m*Y?9_`^;pKZL@;|HIjyPQYdwBN3LQ1MfzY?`fb54}EDeIM)X zv+nu7eb!y~Yz=qD2fcOJd@FO{Ms>F_TXgbstTv{>1DX^)NVMS>xTOhv%!w>a0X8%< z1CdF+iKN`iKkA;|zg?dxWcae}bd25293F5eFi4}81|If-K+v*6gsK6*+LnD#Vd&Y* zjOzQIqwX1w7>1{Fn-?KAOszvL--I&qiscS-qdBH_ia-bQ2Ag6v`&2C8RQJ@-{2ujx z<+{IpDZjeOyYLjYpF)ov91Ap}u~g*9w)!#K42BTLHP0EwW$Ax_;RQSHjb+_Go2$CbIwW*(X-0R1zE{l7H(@))%Pg}CqQxv>TeZ*ct z-NSdG%$ttW)yDsFJDsQ)qK{wdJTW@x(0Ewis3DlaCtd}hO zF_DJQM?r$Q@SILm4HEqcEp7dMQuiJ?lC3*aSM$0%PSWcbdq#P2CE#z= z{UMfon2*8o`jLMod&8$iHCBCKJub{?AS zr|yJ5b6G-$V5j@SgjyFTeIQB21>+1|>*QZG^yZt*fl1ugtVQU9#v$ zSM01eYts?A%arRo%DWfW-5nj2h(QabX8>Nj8&MT#j z?^^WTgo~Mgz(6X&vDQsz9QtAVJw4i8ps|yC`a*1}$~M;-4J&V#`~AKeefKK>=8~Oj zVaAm~87<)%73DXs_s$=Pxggk-U+eyBz3tpPs_wB=dZ42z4}ay|(jgB1XK!zCfIso{ zDQc+$TraQ^ZbP~*IIqV|TlPOEaEy|EpSnwrGQd#*a!pUCXc*lXPH*^fU|1-B!~q`? zh?J&rEkTxl&jTw9*66zXi(JV@L%EpkvasV88ikJ+W+V_N0rB9veK7_*_ zZgw0vC*`cZg!B2Ec_>(Z&o|Gly55<$hGlKFbOW=sSvCT)$q`$`5u71)@x43$8BZn0 zfX!C^z)&zP8T9Vz6EHjZvnh+}bK_s^a|oN`mcctGn>Jmtk{?H+`s{l~{1~YwbIFb8o>s{+-vzs{*A3rjgnNOmbz2U@3 z!lWPg?c)3ICXOgH3a>P9RvhRVu$xb zbjNC!lMb|=eh5WUUZrxW9R9^VY9GRz47iuZBH>$$e$=LaxcK!hAEnk(x37s_nyc_7 z@oy;NerI3ZYR>TB&Q1FY&T_lcPsG+ATxQ0l)|$K2QU_$1PS{PjB&`j>ul*>uC;fW; zy_}(!UaI;cTIz1`1&-op=fOy^FAFigU$|mdCQ*YT}9D^1RN-B?%e@Aj}wG*N4 z%iA?hCu!fk-ObXk{~j1<<;S1s>H5?{=_M`na$eRR(E-xEHB2dIEBEmdz2BeqvEUO7nk~pG}S>>GHq<*|>v24s5au50rgOPEdg#VyR?C zjF)_d;U7#W&|5M1UbQ3i5N=}2U1fl*v1!lS}Ya*iAwg?Zc^Zq-{uZuV_se+BP8{jxdP$MnqBBc!EXZ|JHS_%mnv`GbvY?487-n0M+PsKDMRJm7m7%BFO^ ztL9tX3qYEqL+Klt4xH+fBXsPq(=fT6lx#q&md3(!$1+Sf@-L1V^tB4E;cYfF|Y^9qn z+wNT;!CzULjN=f5d|xsiTxCNuhJB)q&qB_X&pS+jZyiQN2p{}bC82^vvYdapB6hTn z#~d?pL^KZ`$=GyiQK6zDEM3meG>fP9!BA*z>rB*)-6aF11&6-0(#hw& zZbnBWj6m^$N@AVtXMDY8Hvk>LJC$GMPkV71q`oZcJ;-*T*IOM=x#i*6?p_vT-a9ca zDK$NigVun?#T&gP+Y?XoEv|M3SK*=&H8^JMQZ|JkeR{DTHwIC}wfC*#t%T>x!rtgKMTebYi zWOuFQ9A@IugA^WZ%lwL9IrSQyG4T47gXQVbafVnv5$`1gA!}+oL=n~X@GO*F91F{u z%(qnCtuE`(V{~n3)U)ZAyvNFu^U^P|fRE5EWIyu0L6UDYbhh~uOmXd9Nk$*Sbw8@^ zm9&tpfV#Uyc_FhG_Wk);tM;A_J@q7qTz6eEMWgZ-O)Rtz$I1kb!^U0TqcbBAw~du5 z=ezff**ve`3%j=39jMEO=jMx5bx>^dl8AmLJ^}{PnSllI(GK8fXJ+#aN3MW3_%oQs zsr6rE#WrnWZ%wNEI%0qBkPRmcd0G@G7D)_^IaR?BwjHaHa~vZ@6-np)eh(}^>=L9$ zS$MiE&S{&C?s+htg$NRfZ#Tcd4-!76zl3&_LC@9s-5rh(2E`sugVbcQsfCHhFXERz zm^ho+``eS^BqOD>8@^M-)9d|v6?Lz05$=Ysb=R$~)B`{ylm}|8KV zdJS#*jUcJ=vYlpy`v0=ac%&Yq|i%ix1Q#K!opAOM%{3328b_=PqgDdr>C5NmF z?!aWS+D*4RDHB8|+pI-gv@A2ZFulap&VfJpl%~)4gSroxmlCWDQ&Cmq*4TX_?~mhC z`iG(^af2wcM^d@1o*+z0*P0#$wieu=+6>=?xF?@bwH$WgYsP!qj2TyFTaQ zo)EvZ)rRKlur)8vuj)1ccrmmN$4E4l<)`V>h8q9R*4gB^jU-XH&O(qL%r%Ibg|`Gq z?;D_~^#G;_AD~IFb^~wb1Vu=_A44i%pyfG1x9>9fz86VV15<#j+kbLZD47}g;{Bw5 z?28H0_|}>nIjFN>yd_{PEjqdF2_0oT&||7tP0l=<0y2M0m-2eQ+=9H9yBgt6{lj2A zm0hJTv+cJMB82-xM3&E!??9C+>bi4vsz057Ei+Tkj16NkWgc|nI;Pe~KzwJX5p0cm zklhwUzOW;={9EloF@_1Z?Fzz?5-hl5(1%uL3lvc0WWaHW6D`wn7h{p6J=nJ4J!4%_ zMkD_}e0jUeflB53?HY9ln*@ef5XW(+lPfBbk*ND8kTY8_I-WR)+WIOkZ}+u|i1rHroZRjsvTMqEZu2i;b zMpy4}r;#|I5og>3mb}A@umqov=^8pkvM?T(!13(KoT+_aN<6kuJO=#E5c$m}#zv&q zo4**yOdfgY{Z!q1Ly=nT$gG8?WUox8)s4ZVqeW*S>y3Jq_{cOP-H+-t06U4P??D@i) zu*K{h^Nwm(C;Z|(?VDf3J51yyng*O+#xcm=wO#MhpCcEjMYD{ARQGw!uT$N5=$qmR z0~B}fx~Qh#g(%j$!~!bi%s_V*w=d=f4l5pQ>lJ$ z_cbv<;IvWwLw=jJyQAm8e;aeLjlx%*(r`U%$!eyc=vl4ZiM3}l z+kRL3u@4>g5$s^h_d2gjWU8j`88<6iu3tU8-*AfzBv{CSE~hv9=8tguMM{i)X1%`B zFTNOAj7VfjbGCzr`k0kWaURG7Ff&Gn93oE;v6&lZ|6_5Yo-%XWbE>p;mqo^ES?@LL z*5i!nws|6DVs+F#9F(4zQ^#}_4-{Ynzcvnp(`CvsO32`4*|6I zHmdA}J$()X5C4fg`Njfq-SW4JP3EG5EfVM-lYE;hg~ycWG!EzFraJ>>(yw9`&`sx{ z23*Oq=V|ew%mC^mO^;R}Wy!z{H_W!3EN|q?%CaHG!G3M66c%T=&S|tK)pDw7)~PHm88~UOtDbn@rwx4!6z6y5f!X245SfClpsFW$NFV zf7mF(@K;ZOy@Zdc?p;eROZdX|VN;gte#$7{*+TVHGF{f=P+ND!u9fOH11QKVSJ7Qo z$RH;rkV}gkkdrWTTFF|XCStu2$;6jYNS$Vqd9M8(k{eiUym=b~26zBc@iPi!?^VdNx1OAZc9Mu6gB$wtMt& zv)LJ>TDSfvpF^Nm;QVz!(QC9<3)wRFHl3?l-_OkV^hy9UL}!&%@4A<%?p6C&xS(j= z+#{sSFhId@J14K;?QWYbE1eoJ1)&NRIb2=l>7|0N1OlPbTCc0QiYtT62zT(3Ro&Bi zcXH^q&06rO?yH<2KNI(R6of9N*+PEy`4)A*tL|5PIsnKtkh0nD2JxV=+)A4stWv`6 z@D#J*{IaDlW15^lznuCe%MvqtSJ(cMtps$dj!=m_i{cWb2EF2%pX$D2k=;RhjsR%n zB&nYO)L4H|2Id1I=Gk=7?!G8y#c&PmLy6x%nx| z3==T%!dqf-Qql6bG0#(EfQDUi@#ynh_A=vRyWA`8r|H+fTC~gXhyFeCJvuzY(-O}% z@N6XwW+;s>WDX!^2y1d`gE~^QRBt(K>}?-7S)0|#dstp~2pi)A&QBWdAuIw!bo+tb zj(J(9H3*^9-R=dd_c=sgi&9s#5B!=QePRDq)cxu_$Q<>Jie4NRg{N?Zn!IJmf$~+v zY?gsp09J2H5U$v)%Wkox!+Q?4Z%pbN@R%qoXR4RJVf3na{D&Rh6gzdXP5boW)Eg@J zSVx9Uk8x*hA4%1n-d}HL9XiQ8IhT~FX?*G5LkNS)(PlkgZ|o*)!NWeWWbJcm@F zjCzoC3N(e;_nJP=(d1lkgjd$d#k|}r$8g%A#WYp4*WqZT#*AT}PeurTKmU9^5iE*- zGLZ%H%$U*v&<`M)t%1wca>^G>m#90wg(s_L#xdXsR!;M7pJBhQGl_jqlBr`Cf)h|p zuQ3?yo<6zmb@u(KndTK`_;>0hWCT&Y*RxiktZ9P7^w?_N^J9^VIwV2CGGr`dr>{Qh zzVhs1D6$jJ*S9~=zY{TU`W!*wj-9`pSD&~y%|Bj88zrp}7}BdBX@W$c!SR&NQ^d2M zX@i%;DRm#<=t#Pw?8Y9aRR+PHq-Y?bze))8#T%VTkK$fWS+n#AjPZJRMnqb*WgN9W zOxq@4%DVWl{-<>!NcW^0tc-se6URuid3HNV&sm~gEp-}XsGyA%Z)QQO9VV!1Ha!d* z;Mi9{YnWgz>bjp{sz(ytwAp}cLvlch`tDKU{XKP% zpSFJnpy;cRzJ*c1@KpKI^q~o#VAtJbrABX}&k5X?ii|EhzMv}dddCbX z8Yah_wec9JfmM`<4%i{=;diON2c#4oy-jp*m-`wPc3Zp~Qr2vtDn-6(ONX=xXsEM{ z)7i#dL#lgff?nPr+Ia3Sp^}MDV2+~`m59hSaxY&Z?B@nVlio#q!m8(4;WLc*{&K0^ z!a$;HA4D;lj}J`P2m!$ zz87v0a_SrrsK9TgMYXm6W4+7%Q7c|~@U@50CB|Xx?lr|os6(yod~F4MM4(C$R1O`@ z&4;n6vDJIFQoh~EIYp5TI0A2In)lpc?=+3AI!=)gZLQOkJue2Q?F9Wz`%C!lKvZRc zUf5}j0&BgaG=R^NFEVkbQjk5e*zTnMeIxZ|`|Za!BZ;Zump95hoENNTwBAYACNk2& zz;a=7-Ie}My3vA)9JSlR+hv!Offf~h&^6m_0`)eZ_TuXWmuqNHF_z37Ux2G83eB z_vme%0i>)*>i#v=JsqsiN-N{W^o(=lhxwP<$^*;eD{iD30EUTA(d_nmO<-~l7qMt< zj;X`z55#PZyROa=f(N6!VNZ1SVi$C>#$tvvv5XF?VimK=q?)Zx7$%UwM{01V1~GcGWg5epLemGZm*MZp@X?<<32NR6zggYCF+IU(L_zJH=4gZBt!x#Q06u9bM% za?>HgqR@!r`I{e)Y$aq7v9CPS?f0;;`u_6|b@e}dFWcsb3w_LL$l^*Tu5;)i{LN#I zMT@p97JSn@c3G+Np5y*h#s$AK9LvzDiXgk;$=+7!;DiO-mbJ#F=@b^twQB0Fv9hMv ziII5#C_v-=dN2RqdatNEF*aGJzXz|JY#ZhEo@#i`iQzf)G~=)&e15|5Z3FCq_de7t0H#O)j=G1KjO;*>e3ejXa@w?HVY51Fayl}m)LK=MEr zHs){QBo_=dGk-bUJZ>r<{()VNzLg_PCAGMI_SA6v+IBzf_kaJ_G|Dq?rcEqs^TPhe z)!F1mZX{8-&r&FQ?jgtvZHXa!Z-8WD_DvF+^)w0gRvVu{1Zxf;sOko#KEYUbnS9@i zWYvt}joo(tL}g`0ym&ulxzAv?zD04~Dt{Fd)WgHQS>b-(vkACVoL#r4g-xEh=a}SI zYUrkB+H1Lmd~Sk*u_0>3EqfD8wVp0GbjCX%n~PdG(D}_>125Jkju*tYcYJu#FZ1)f zrdRsc^-V8;IC&&p$tb1woMCBJ9|Ilgjqrx%wj>U&!505eI#1cNJTK+$3RZZpCJ;gn zrQ$7_&zsJ>5donug38i)Z_>~5+f;J3|DLfQ-pt|-fCH*&oF(B^?JpGwwU^?Fd*wr<*fw{5pFZya#e^O^7L;S;B)v4*cW*yT(8G&n)5 zIJg}eJ0I1`B$Q!Fu+Q7@O9d*R*G&CmD&F5F@i?Ad(oLhfTl-W*j+~FZ-wezp<9l{v z2o_OyO$l7>jezk$mByhBn<7MKmPJlM%WwxT&wVDREVO_*^MQDtSXPA9N|JUmtz&6g zTr>Ucnf*$Dk(vG~g2;91W^U|dNne&!_y6#dd*L-=mLJsMWzIp$sl{UdH-svXK8$&* zv7Airo4Xn&OEum{h+|s$gN#fv-Iqj^zzu#H>i(ztb?x%1Y{0MlTMbe69#A`jNAO-; z^dyZ$kyu`Fzu&#zKZsw~x8nlgE0qowS=mrlr5 zr>RpXB;y%5R}LNkp$+ZgR~OzgKL-w>7?JMdcBprnmc zZTWD8Wgwr6!0qMZF~jJ+9DIv+Q|zPF?*k>OMP$$N^*O z+lhq5G$vS4BYRmC5-5d+$oOpT9Ijv zne^_-0K8ejxnuN^kG#S3GS=>hIQkBFy&G0CM#(!@p!03*<~0$ufK`$>KiwDaJgECa zP&q`T5%3M%@ z^A7=WW0^AsM7iP4tpDUJb?ST2Rc|d0t|X|3BD`D#Li?SbRtVMPe)x6Pb<)W{38Kf0 z|C{a~@tX8MrarUtSst^cA#Q(aWa4t9%?851yU0?P}cX=xG|Gghj`1s zXr;h@YWu;My2>#{aXiV%83ic71{L5n)w}qI7SM_iZ-}+#9GEYvulWp!!yceze zm&8F*)p&aCu9F^-R=PxQUf&Fk$ldGCZ(0|6{hwj^@&VDsATo z#@eaEQmIzC?hIA2QTBs2FK>O+WSGAkvcg7$;9kOl>KJs$$|g%X&VrX8t)~o+X2%*f zAxX%1WCkcX0|(Oz)I~0rHIzoQ3h^1(MQ!r8+KCOf{4j0vS7a&}*`6+VDM5hfJN#TCJ@`8}_=Bo0xloF$byS z7&1&pdcr6xSsn4p0_1$$H>&{$v(mEo z!>$~4wR08jt{Lt3@{J?vtSqPp8)VL=gm#KVw14k@$8g@ABepQUudM4#6#Mu~fY=Fn zmr@7D9k#SD81y+TSbWb&l%okZ!i+Z^Wp z;b3cdC!wXF$_2VW%v8iG!>&-yDxZkG9L{Mf{dhmiLNZ+|zgCAF1xXXU6%9 zqqTLvTQG(yp_TK#IA_Hj6uCP`dIl~U2OV@y4lcv(t=Q{cw|nKqozN0}k^lf807*na zRE=g}m>jl1C%L*uGe8zH3v<@l;n9@%1wB#80Am*Hj4(&i`)ft7SNw|Ji{K~h`0d(6 z?$1j_Os4acuEgaCM?m5#H1PU91@VqFi zh<1xKb3UN2tNp%QciTt4gblV-HjlOm)~=(-bXHKF!%Z+KX>0pOs=MYU=ie0ja?g>Q zbsOFV(zwp~ybn_a*L<{rT8}Odvsw@M$}t}%T=&s;kPtqbByeU5taNRJPO|M>M5zaY&%~b|9p9YI93>btec16VVB3_Zsh3&Q=V84 z_4r*gSvY?oZmlhoH1y)b&- z@;HK)l;5!`6s%C5H`p@0--XRzhRoxuN#+G7XlEqZ(2Qh zFkA1SY8ShDk+AA6w)6y-*{vjxRHy)QJYc1lUv^aUmm_sgf8(24z{+#73fsXl1oJBW z{USI0z;ENfOib0N#CK|Fvw}uP8dG3P4$`gS&9?K;wMTo_AAWMjHthahs=Iei0=x|A zis~}&K@_uHdORJaxAE5-Wa2qH{P5k#Y29Jkgy8sn)#T_nc;XZ;So|#dTCEI5smWH| z7dtA2^??QaJu%Q5KE^_-k$f~ETBzzF>aG|@^C)t_QsX67?~G+zNEB5!22Sww_?U@! zJegvOJ)l0j0ba%bEfeeEd%UEn`pk+$n{C}3(pWdX?i+I~Xkw>qvbD}388e$>q?a-E zcW^n3!Fc(+Y+JT~(W@}xWuS|BUm1~i-MQ`o)PrBryt4(DTO28`fy}3o%z(n2Re>UC z>sv&+D0N4Qq8n22Sc{e8@@cbKY8Pt7-B?7qve+V3&I`h3Fm4(G;%sPJ58*$Pi5!{M zmz_Dd(2I<&-6OpO!9~^qpJ83K`_P!vq3Zo*O=DXxTyT4pH%lvH%hfVrd`|*@5BfPP zP^=sUBX0Ob1x-w&t6v64t>Yf{?k#DL<0b`n-4Q^-%T7N$M&0dyd*z*8=E$)XLvM0Q z?;8ICO`rrL=O3h>$=8Xt!*GZeGU`S7S6f1C=DKBy&)i& zM^<&m3!==Yy}09CR=ZN34^iK(F6T@K`Le#}O!`jV)^2t@wj2rh1g5CFz75u~8q7t9 zu!v}IT5|{rmPe5@vseYP<-jd6A-XL1jk=>wQ?MvBcr6XN?)9i%FGLn?%O0F-TC6U! ze_zouIi&-a1I13lPhNM4Q`78>6!;P8kJ3B-m$NrG(MSJ5U-$J8>LcRXRQE`}ePT6e z_3F{=Y+C;^=X#Wf!@ZwVRc7&mB`2X_f&d7avVb)fA5L8dVd%AGqW~(nf_snISdA?= zX!!`scX!x5dtI7k0BagWSlI?6v!;% zC0>(_|SAFo%PjDDI!89{8ff-s{8h4l3div*M12n zl&36-f*=oCAZc-Wd5hzI1?}s+3Rz|qAz7UFo~x_R=^wigCDb^!&a{M)oaNaaJ#sG$ z)oqj%d9jNReEI|~1YU2ky3_p=8w%?YR5ZPkydGh%N$;4I?iWQZVke|XEotpnHJZP! zY`#x&EELg+&^QY>^Hz6Z9%Ih#h9G@A6hpR6=E044Db0Pv%lpE;*21$<_c3+pP?$5d32~n7RRyUh6PhLpa9rs73 z<7=y|aNL_HP3t(X{e2W7pk3eD?y>#iHPc}m)Z3CiOHkbwBSd(sp(eH+tg?^nzAm$>H;ao1>_ zCYnzCp;m673^3Jw+FS3ei*WYV(u3^t4?y30*xIY_{$Wv`A}+sBg`{Wl4>)7?S~qOZ zLA~>F+?F-&idcsk8dcN9s7OBoAzPEGwM9gNP(;l+Tq2sR=o~+W@QyH5q6NLG zU*O}8rRVv=WY?A!dqZ~Wf6sAeTJb>gzO${0m654h6*98io2atQK2GH?d8E`fN7FcL z`UhSvWbbj_cPs8W{od>4WdFv-=lyFRvXAQ14`xeij4cp>IX=Ko&mc8*vhlouFFTBx zmjaw^=?X($2a?~vq8<#%v z$c8(;&e&h6;+p(+8mXxslr7kQe}t&XB#29%xW7A(EMi4xS5|HcZ=Sx2V!n#eoTeQ7 z-K}VQ7xn74pyogrob3WBkv{(Q_GfOY(sg%FR#!_Ojo%!1TP_1$>f01|wjq@a+OAT4 zliI^)=iz}W*VInk6=FWeBx)8lTmMNN&yzZhr>t9;0-kmIl#fR**S`gH8!UyV|aLBOs{;i6!&7gIs79EC>(Ir zjDPY*{Qm#y)xyBM%6biLNv2Yu&-j0AoLS`DGR#7nP`sXd*~8ZPa7Sa$Ig2v!6jr72 zF|LX#sMx2T)qx>a=aIzpqjJVMpiJp%IE(NIics(74a{&*lEg32c0zC4lRo6B zsX!9X`AV(C79m}N9+8coR*fKQ_L2|b7TN^NxT-q^+em+E(QM+Ret<9`U0AAU76lBf z#MMR8j8v~azq9WlyckKl1lN1i?j$jXGLoGA*RU6S3R{(V%#(hsDhw&|qAY9U>so$M zPYp?=PjVzKG2_58(+Nyd`*+3G(Fe`xe%H5T^u;loNJHAM_fhU;B;SrNj$3ognvnKI zTfqLUr^ta^8mQd{Mtd={lDx?)^=e+aC(w+Z^!1Gt9J&*m*wTU2bPV?ZsXFdv4<%^I z+B3~Ipo%WzC45cUwz$l1Z|^DYhxT7a6g<5Z&3An(R6gyb!z+BbZ|`z2uf^}P^`uHP z@r#V(-uRG91&%_&KP-Z$`EJoU(6*xC#f_^aPn+`J!gsuWo49+O&*xpS>80l$R?)A2 zrHp+!z0h+%pVC3TBEp`RbKKKP-#uxfGL>FW!^6+dpVX#&N3FC65i)@yYU>|Nr9kc; zUj~lFXwI^klr?z$KC75$KT5GRs-we<2Y26;UVqC=Sn1Cx?(fgaB-441rn};x5OgmY@VUg2N20bt)^&9wf3TF z`{-58mnDN9!id|w1p4ojFOvBjt;eN*QR#V&<&cy}E^<{Q|I{1$ALdn(h^W9y*LcL; zr0dBVDwV4Sp6kmCQg=mDQP}7{gxTbga>1%wQ?_&C*IUswH%!-fOGLHP@#O?1*m2h- zL*S(uD4{|;6~`3!x5wst7{DF2Pay?f_X^VeUDQ>PH-zaAh%b~`io2}(3t4iy@dbrN zC#D2`bQh4g+qB6hdQN0;W?&bJ4YS2XlaOl2wNI-$aysYiMJ9>qWY)9$FJzMvaLfvP z`l(qYkh~7<>m}tjy5N84@x>5%mVM?{|V%Y?q) zV?FZp#r;@@DP1sn?kt4NzGoQb z(ebriE{GcColCxh{Kq=&B>cE8Jgu0IT_f&@#-bOo#NdlF5H&?CzSgxXkhWjvO*oOY zuH>?C#h#zFnj!<*%oD^i7-^_O)5ps1;MsAvuYBx?uzKtUi&~PR>g|dZh+SAuTonQG zIRpfyEbfhDHl?BtHqG+rstJT?OpUTEr5z+r_ijZOlQiojQx<3#%@DoECAtA#h-V*X zwmHI;_>Q>9Er6LOS^zggB=|gH#t)V?$dQb=r#~vgg$auygKaqO=|_=5x?}N`I;mX& z1vbNxFr`JJDelf@;K52Iu^A4=qpVr4cvM^rRF*Za_n_F+{5Ns0NgOYT(5?(*b<>RDWl2ZE zC{eyhc9~I+4QqMPqCK=_i}vK8f4VDPXK|&{$Z?1|3w<|B5}L$4?C-!-R$Y~+dkli1 z%99mKj8+d>T(DZ)ZcymZk1*10vs!`d;(gs^dh1@m;P7c2Lhj|SNOfW)XQb?P8+Po2 zZApMQSk-|WqMfU_ez=5e#)=h)*v(=6bPayE`s`;L;YgYLVvL6++KYX;=(nd&gBM)% z{xk~!{WX$kDXz??s#?2JiYY%HhhJYSUyzY0xC6X zxqSy{Kz8H1f=nhy__$YQvJ-#cv7!-1+;zJjj7!bW?=ITLyDx3yy%;E6I0qZ`ETf91rx4-}R zCjNnb@W(Lm5JG=AYZ4-CKR}_uG*OdT1{SW`a3ABm&mZZ4e=lFP{1yMS=le#p>TrIPCb9)#|hcb?T9#STYZRnzV%(#AdL)NBeWC|xQL=rokZ=?mjl zR{LK@BirrQ)tiE;v)>p$ac+QgdAdXC%A|D~JoS_oTj!k};_;MQ>oy`*BR!q>^zZp@ zv~-a#qFz!S+ACqV#f@gGH{^Kgv8!)MKX>+%9RN8Cj6>$fsCURqWk;LrF%Q;xZ>kQ5 z25XqG?J4i`of>c*a%s)5PHk+`A+}G|z{6JJ83q11`%GYwB|OB|RIGygJZvVohWjej5{z|{Mj~&XvI*l;r8Cts?0aRP^DMv)+CE!yi-t7Wx z5t-q7KJPzqgt#FZ)_K2OeAdHbPbd5Jc4g@Rd8N7rLtB9$h@~ha^#>U63~bjSOm9hV zZHNbPPjygh6OCBR9s1Q-{KyEKR&Dxom_D)KA{oWV>eR#bok`#GQwBrq4CFAbHUopq zYYJTL({GA6d#XFa-F zF#5U8E0o|_JN>|*cxWr~8GPfFvezNA)`3*VicT^IGe@lUP+?itM zi)Lfh-Yy)=QjDLOzwV!Y)2_F89)cqRJ7KzVR1YoehyqXP_VM0ctpVb9;C<)l$j_;$ zPp6=b&FJ)-f8DhFJ5Pc1L{dlGEkbp->C7EneZgh!^HUG*jaF~1zjKc~ zsqfq<6j*7ZUItg3Qj-^nmx8(Nd@Gk2rVLwhs7l0&VL%t@jDJhdbykSEY3NUI^h-uw zY%#*XKA&zGo2tCK1MGEUv@7?w6qffq;H}EG+8morU~pF$P}XuB z>L7~ueptz>VuNY5z4v8uvipH|oK8CL*C{jL#j)aG+F?m)%r#E+*|z5Hl5x~+rG;AW z#Q3ns&waoOu{E!JRKIdC~~bvD+QHSgc#O>ip!V`fxB%b1X~s9y0c{_7agSq-pu{whg^8sfvtkYXyYX3klz8I#YGSNLnhH$KU(d8s<6!82COsXx<0W6}&DkG#mpLmRyRr}0t}~=ehS<6+QL$aDsLbZi zMomb2Z>`aflWlGcWuQRW{%IVVZrEF2d(CnKcv6jER!V8XM;zwga>B^H{uhH%z3lUF zrU-dTUd$#Ra)(;kC}LG?S3Bf4o1(5{zhMx8i{g^$%*YoMS`Uf@KHHJl=WajE@27zQ zISTw@nL@Y=P|@M$=^k3-i)MtuN%+nvy`AC3>PjESll7ml*uzIjfQoK!R*B+13{W0& z51(q=+C2f{aoqc2Bdb?LRCy*ftPwae%jCds#6Gke8|$lum{+o~ETgd>e?Qhg&eP*g zd_JYR(*89xZ1Xv~L%Sw!r>&i`syk%%8P=H1^Bp@-6?&sH`DgVh?ubk->XNyi!Fh7> z_EZW-k?-$+2SZy#0__>R%tu9%W#_^4k3crYrHQzID&++JgVBu34z}C!WPNk10fw|C5wVW5qEz*h+F*=u(*WYIcyHhW?ly>`>S=F`wP@ zwSZ-jU1*kV~s;dgFcz!ZUqGG2f<+zM#6}(tK0=-*A%cb+_ivAuOML-1rjC8J{j2}ET6D!$ zMJ=0QuZLl)Z>d^)v9+rY&(#B(Al0rd&W!5?uUg2IjYM^xkdEQeGwd*UV?11hjwmwZ ztN@wY*cBX~6|hUk%Qj|S;JwTcrnoW+lc`Hn0_8MPLUeO` zuDU_`U%jStLtqKoAUPvjcEV;8W#c40qlcuEiDDzVmcDVn61Ck+Qh-N+Esv8ZSz35a zL$mwxEoZYQ!JfctYW`RM9Gs4#^?bjv#FgDCcIz(fEHUi3>wDQTr3r|W$CUN5km52c zGqEA;U<-=C;8M>EbH6rpg-}8h)T9@bB**A0K>p z8Vu@6SdUKjiwgHqjYN}lL%MMvaAkKqv7AK6d_E1KCZiIc-|&ZIY8=%_FKUn`tpe?ITxUbCjc-_8!Z7txj+ivRbi?=gN3qCGH4JWHyq!m%P9-`YADuxhw zQ-xn89Ny-0*jtzh`+XUB9p)mw0h!7DthnNaK#Tqf6pWRcKNuLWnHkY9UU1{8RZc^Z9gZ35H&XN*fYPF~9^pI3%#zG~Q zR@z{dGU|I>wenq|;0WX}JzcI-iF@08p>Xc&UeD;AKw4 z{emm8Qu|_O=nv(1PV#)DUULtb|0P#>{X&2_mF{*_c)e`9jk0q z4UZ>r-RmIAi>rvXJ)rheM!1f7xJlTWHA$qPX?Ko$4(!mZ?7Ln2YSlermQ>Qd4k)&TNEWpj z+m;Vy^VdTY^9rgUyXHBZOa+iR&hu%p61x@mk1OV(?-UnbR9)e@I)%(9mv?iH^Ow4i zGeOz!V@i&Wg6UWaJeY6y{cUVCz^=%UtZnx3D0F_-;3dOz+)|BI$gRsI^-(O$_IZdZOylRv)1%y$1pxWf!b@Aa+(S&i&IY(Hd^-l z213o2ITD)T>)DvyX$ZRqTe5S9vB~eW^zHZ_#1JM%UoJM~At>lB>u+u*^D~*|QxNiy zq18%UbQ-e=Rd+mfkw8%&hTI)1RS7T6<4wabVMeb*EoT&3w<$~rqtQ%F7z_kQUblmB z|3h)NVyfc4RZ!Q(rr6Qe!pM}4%0X4jY_-( z3S>>hIz2%@I~^H72PSG_x(<|`@VC{%aMxsO+FRij>=AoxPF&p^R&a=j^ArFFoX^tbcpY zareW>kyqf!ci8hY(957(&S7MsVeka%!d;_wrg2a0v5y;}ck(F@F^8t=oHz0gQ2I9_ z@IqYeZDM{vp*ONf&Xnh?P-E^gWWrvN zBUshG<8)U&%-@Xwm~CCua436vP_1n}TBNqn&I2SlvPRBvx8<$k9u}S+ksuMn=4nw3 zKG<5`v5yqLD&4hIb*%q+FOT9QAF@>Xs|Uxn8uc`jb&3HuG)+v{Vd)Q657Bg5g%Y(2 za8(Gr_5Zp46f@jOA$pu30_v{yx?|nqX?L=m1aM21_29~M1bhK2wzW#Zb`yXXWU!@^ zYPc7ED^}{a%e){8t?1rg%$PfC@q0^N5i@5;k_nZER>EI37=3lM>q?j+k?&* zt$nf8)!3%u+YJa4fR23C|0x6{Q{wzMtpu|EYKepzkPyQ^J1z3I_-B}jdnKHn<*+q| z-^3(xYi|4|3@V@x-$}YF2X6IMT#~PXLPnde0sr{ehP`7=*T}T8?uTIK=Tmd8my#u%8&SLVsQ+@4QoM&o zr&&sFA@tJZ|GA}tOWa>xQ6IOsEz51eWp=CW;&Q&0<5;WPQ%?HSgca`E8t-})TKDK- za!%utFU+`WLyc&bd`D44`Tlzdj{N+|Zvqd95dSeq5%pj(T5l!(TsXmAdR(s;gOxrf zy~F=>)hj$Ne}9#o-ykMG~yN?Y*C-XA2Q9FPIh7Rbb!Dx9Z%2tDEU5G zalxC;Hhu@RKezB86T`k_z}-vBxdd-`b9bNfeX}**Xale=SNEpcg=;jB-nNnD_C|9U zUtKXj2#gd06ahi5>cGyb>In({s1CPrBQI^Skj1u7cK_)LHG0jY-A%6W&+=r?U#V-= z+Z7^=R#3$Y_yQnIous191oHBKV**th|03Vdf(cJ!A@%`a)w=-C(jI_xx0;ZLvPz#L z|0op~$uTL7I)_kTJMAS!fEcmoN$t8D1rTQWl$hBZM#+2K7>k<8ac|Gvwd1ZSu=G&F zMC(rQmz>k6b70`4e6J;zEfEM8`9*|$2O7Av>`g$xb$x53zCzqB|GJlfqSgRjw1T9d ze%Oh!*dvbM^m6NkWlAr8h2mb+l}bNT2&!5-5&H9z@0T)~p@&pU$$0XNkO>x_Kqu*Z z*pr-2^GO?PeHYq%6rbbNPsDvj{eRyDkoKTI=1(5&!v*aR?8g8AAOJ~3K~#pI?j9I@^ubJX+iclJ@1f}e!=K6r+#DwD6WrCj~$0tGDL4QsIE zZ)9v#$){lvKNHB$dEPvof59T4!qf+p&>wWOHIz~{^H~bLs*#K+iU^hZNFx~KuPsZE zP1!oFa68bEx_$ZD{jpiGNzx*(v9Qe!B0QVZ-LCGfV-{YMHBwfrrBbB139Ahg4hDWU zD7g(^f|J`@=iZ2A$^x#H5~|ho{pbpRRR0K)0MB0^}*_BGLcjM{(n@RU2fZ05{11MK{C+W5S#(@ zDvaoP4u)iJz$B3cn1cGPp%-mnEQlKzh+4tO+JU^6x#v4|DJN)j14$!JO4s*RojN}U z)qM^QT&)!-6aX=0$0sy(H09izR^Tw)>!IMwJF@Dc?ua~*BcdJOS|68b`TY5g=8QT? zt2Y?in5igRS&|Z+DD;`@PMvKhCP3a&>^v}~)9yYJ8S$sX4|XCujY7??x6g0q{e)3O zk6Sbkh+bN@qjB1E-P8Fg%c}T=TOGY6)A&X(tp%5CU9CCj&^l1Vv~ zPg{{NVP&~ti)b}Gc1+xQj8oXnF3h>X@wIUyHmU|MF3WEw!7NLR za04T_Ob#r9AG*je3D%*Xi-o=ME?d}W9#Rdw8xOO$Sz!)DRS*ADRXeny7+%;r z4OLmkFA))nY_ZP4$84QGk5R;1C#dP5MA|Zt)%M?I4>cT zlC|0?qNUrR%U5sG*}7ZaZvu;ZSgS`zBX7%1AR-*%^m?&wsKOvc=Azv&ZjG*rTa@pa zRQFWoIUT$`4D)%H$ZWZG?pOor21b>HZ+SwyOh*dms*mYnwpg=x9wF)&C69L^-5%QcBWORk;ZaBNUWZ{=*s4*to z>-EfR21bxRhQ|d@T>Jz9X%|JCwTtKUXlHYa{kHDmcmCd{?q%HVimI{`lOM5E^bzCd z*my702CkpL9~I?skZ0#?5`T!M_bh_UatbnVUJcWkri%rtBC-DDfsIX%&2>1<>*o~&s)<%R3z%jZ2R z{Fqzs_aF=7AQj;i431o&kr^eJ({Q)?JlFOBLR2s*}OBqs;_Ne zQZ;yRsg7+sj;WQa3UXUY7)_<>z9N0~;Lvkj?JK-z=07khl)d*_<(_tQix#a9mBA?QC^O=Uj_ zPmQxz6qia&lH5aAdism7QvkEVoJVVmC-Z>kTKCOXzdx)0*!{<})cGUa)o7T`J)rPf zl+|_UwE&f)524=QstLlv+j?jrauVYF8@IellIM1^j&fqkiLi zz;$0n5M}U~!YwcLknK-@)HE*2$4&ovjbzSvVRIs-#{U*}PaCq_n7rFauZGvY>!;xm zRugDzZ*5xg+870E@|TJ)P&++TS#wU2G8 zyEuHo@YAPsJs~!x?xujq01;tgT@1O|lWZ2@|DxLJA8{+(9~x!an_6 zN$TIjcwfa`eLL?3X6n1vwq0sQ9Gr(2M}1KW=shfE=nd1nGM?f zp>AXM)!TRWoA;8%irPWv&n0f10O(Vb=iWW*;~#UY@<9VJ@U?!)r~PL3(qLzJ)g9RE z{veuN(Wfb3;gr|q5_i+bh=*|v^V`w(d{*`Q+J-q~2bBD#g&8%ExX7?jC0mQzo!lK2!3|k5bd{CQ&er<eD$tqcKz2ImW{fYHPx`b^0^G z;2!9tZ)^n;>v^E={N%*1j7C)WeDKax_YOoz@=Fn2uTHAN(#LvM>aGwP+V`r7hDK{y zXiBF@1KCtXEqYO*2JmUWTA}#B9s=Qqdz$@RtG^eKBbR0xEQt9C;kHP63rxi#oh%eh zdR)?nv^?A-F_u7gaV>ATXJAOOwzpYot zde|-TKcAg#7%7aOeo;Ur@F89bMrfp5igO5K_i&9 z9@JfCW3!3lE_SNIg7m&}v6pMHY*>82KrFDO!&@2maov`{1*iVk0*lVwaF@s+LS}lq&fi0RQJlp%(Haf_p9)#wd%l0 z&rk}$XJ%IO&3)kI1_zs9Ev@7N+-n_P#D(74Qpde{ZL5i*lWm%-NEK|O?)p=w!%jkz zV)8KCvAJPk8&bEK0o!C(m@P1qDUv?(IK7_-?)7l99WR&ZtX~XG-oIj-8p|q6aNv@C z8Zf@GBe`N)c3~5h>MqbZT}?-+!Y`rQxhkIs_ZEStjo;JCCi~^9R@XVE$=?uo3&UDW zmu^Ex_>_+MN=nL=arfl|k^E6Q;~6%=#tAC|i_>iIhHqQ?SFU?L>vq;lb?*Zss3sSF z@4DmEbIA6#86KI!?#r&q7(Ik?*;LV=9>ih~e;I#T@xgChWhGx8TKb5Hl0 z9y30PaOKA%OMjuJV4&>D(~>W9IH4$NVuEMVwf~$-x_qvFN@p|61WFt zTdsf0F%Quhad2i3kStP@$e=bp^_EQ?r18$tSNdkfDHbF_D`6+P_uckem?F+s$BfmI z5wE`ee8zJo{daK9A!>hP?_C29*1PJKk}Y^h(+4{ipR*#8wUpN)K)t zj!x&u_U=ojP%nryz*BdE+`CAZ*i@4xe(~o!{c0*eO2cW zXePbZ7matZk$7{A7zB$C!urZ;GyMdXlH-Fyb5&vQD(xqQHy|H~4J%lt+3yz(ouV3h zjk2RO%Qpo_jd??r(aX@-jw0oi#0JT%RI7@ND-8(n()4}+FnwmY0 z{9$j(ls zm&bO%1axj0$Cl_5*x}98`B{y++t1V!64vC?8%qz#Oq5Uam0Oxe_0D038ZSqhsk@w* z2ak&;-dX0`V?;|o>VC7mhoddTVz%dx-aG%@8;dAqi0$tLk<_&s(!14Cck%QrTwSI9 zU7h?vCw}!J8}c+gJ$G+&rq!sGP{0caHqO|>C1yOSXNjISGGWp(%NZH+0?i!#Qg{coZ z6v~Wz@jgQjNAm9K6fww&9O_C6SY65W?u)w9*o{?ZyQB7ZX_0Kh z-HN&!NRX)R;pY7Ul4Sk$4M~&WBP%uDLFg+f6@4&QI4;(%wsk@d>>FKhkbT8v7*Sy2 z1+Xn3uW4P=5R=?z^Y_x?qctNp8Dnc^M5C+U@xAXA*>n&dc@{fZPt%bC9H%w;8}@{o z_x(Y0vY&FCF_?#+r@jlLk53yA!sxV3>)G1Gdw7%5@Csg78ZBzoJ-kAN!B&n_Xmb_)i zfVa9Mt54SZpgWT{Ygz!-y|x5Au1!>R+GjRPWels{{Ls*2d}-shp>uXnH3@1gEr=DCs%5_>`Agd(&5bgLAmp7ZA&ahGWx!*@$A z7-_et%rfy`4UptpHS{}+UO`10otC7Wk7XzI$Bg%yjZ4frtNY%f=IK_jSKWmfo39@5 zFh{)9?_}(OO>??R>J2(Le7sq0t{fdk))TesC18*%;;zSjs&y}&Q1|d1O~t`07z8nA z;{2SiCz@f`9MQTrKwA0Dt6ir02Tu5{Eugf10;_3J|BE3j39YV@yX4=BA)Ti0eiu#U-(OcSU*Z=!Lj&01Knw%hop zu2uSnYbAlYGlqL0vgH%V=qL9GS>+JV83G4Ky^=m0@n@_3RmG!z*JZoca-9kYB~})h z(mRw!Ftq?5GbzFP9^egD_TVHug|Wx$j)o5hjc!+6v@;;V#A~RqBnk{OewgGjULt&m z3sS?&m>NWZt97_(yYZS&5DK$ z^lX^ZbqVxJ`P^2^=kU9pm@|PNFMh<_v+7%5WJKg=q#AsY&U_!B|*r+?543xH1EB{s7CCbX+B=S7CmA%{p7})0-+;Zw?;wLvEw2|D17`(R^ z6c*V$@2Tw`%n9Xy8d1v~pG8!*+7W%QMm|T|nx7ONuUUP5bUQeU62i}YXDBwT$4DAw zS>`G{bugvue?Wp~_URm`6C*g@^*f6WjEuDhIt&m}WMElcrS4cDRI=6~MrK%P(L{Q^ z;-_V8iF7n5)*iKlA$Q5RvbB$kjak8)&6Ry4>MKCdEZ4-asj5W5+fEMTie&{z;{$cm z3Y=tEmedFWVVsa{m9u_7(?-H}dgsf}DnI&XbhdNGv=19)nV|xd))lFxClR;}Pp7#X z2A44lGz`#ntow_-mvGK(r7VkepDxyXVuzbJ}e|=L*wA3(zL|r^1AmHpS|}; z4%PigCX+k8X%1ndpA9fLo{U^`J{^yzzrLNU;C9xGr$LAqe|FT1S>IR>=mT4Ol^6Wa z&kz|rb^jmB7L$7r=Z!p>-C4iCsNc6%aC1}Uq5icCGdyik_{T0bwe`Hj9gqy;Bqw=k znps*Cx9oXL8V5F$KN9$YV5{b{5kyj~cE;2NOJ%t3f|E~Rd*qf3!Ct2|=X^ev^M9^nx< z4D`KuWaH(8jg%NmroeFli1#!8rzh0t@~7jw5&Z{u>eYF}Qnq_|bs@{Bru3?jXIe#j-SyR|v93zVM;nfqW?HaO zHg1>|hhwjp56(0jJKnwBmCDygGybEQ1mk$;MrpKuAJ6ZUP;BcTw!3`ia}Af6n@JA}o(vB)Andx$TCf>kcM}x`vP}dZfJ0p+`ORX6CY`|TcBchK!z0*f$9Ar zkuM6Og{HS_5BHln7ZbuVFce6Vq-SI*;Q{{I=XK%oNhE-Ru>>VbU2O!u01!Z_*B*30 z52@;!(id}Ybi_B{1Bk}R8+P3uE+@-CAa#lTzVC)e+}j^SkD+v);*aqxK;E!nH8TG1 zpVxgPnc$>NAkVpd)F4ntW>I+n9_cqow^Z}r!AU@LR#PZ1B|bx z34NGms(YB_=gX%%nqQe4ZH_c~IC5i$yK$asPQEb3h1j+BZ?pzV)8B@(Hgu5NSH&<=nx(#Os?V1|4yXOn{&XA|PW{9I8XGcJjXM@RD zc`}$jt9$rt!Iio=L<9W;4jM#b`gVf`Fid?=be`VpQ&H4WbVU&3b3wnO?33%8b-SIW zPjQ?H#|#6sxbG+nT%)OnRHDOiU_IdPsd$m6ZYL@Bdm1j&Z!SZCwo}pL9i31pqm_-+ z#_DeUUMum4^vR8qZaR}Y(Mz*~-)FBaE9!pIQQPU5At$?IJShF)Md6D?cy9O9`k3Y; z40gJFR`yW${xF&i=$X)%*?sEC!3t;7+a;%osV$rFX?Q>|PF8w@;u^?qaJo-o*@249 z^4r?Btn-Ka*`h9-q(_?qcml_|Q;z*W@r{%pA_{YpNG4CyuAr_F7+LMO+kK=OG}QBX z_XL9?;f+>zuCnD7NCjYvIg;FG)qS^Vu=dy!m_0#tbGRILOrteSY;Sh_(JS8VQpS_x zkXnO?Kp?HI;K-&AyjbsN)kCO#CauSeG)eiknVt{g>xWck!92uFh9*3CZWv^AIxEXH zK?CS#x#n)Wr^j|x)u{W@>JBSL3u>s?!?2GgRLpsj0K;>CqB2bX{j|z%+t#%6mJK&p zIH>6GhZEmR*jwP=XRH1deZ*exv*R6X;e$QF!0^CBjq;yHy6&3U%F|Sfe4OwZMo4BB z(v1o?t5gd-7;av0(8O`ZA`%mAp=Q;u41G?*VIxh#`>5w>2I|+tRJU~Q+ie+z=H*ki z*sRJz(7ZA$fkTTkR&&I8-v9PItdt+vcs!-8R%NKy_J{BCTwl8U3^B3;>;6AwqQIfB zB|BSuJ;9N1_1Rl`oChLY2(swM>Eky0@^|figi9#C9>CCS^`X;EQw;=m+<4};U_)D% zmK8}DMI!Y6d!c((KPGHW z4#9&3NtK1{^tc6}BP?`T-Rh6yH@1s~Hd&grQLzZOzL{7dI=o@Mx<`7!0n2|&Fx$u; zPmW_e;Z4eM{!g>|`ID9(c~)WCyhKovmyPzq@Ihe!xiOfyWGm)EuF@R4 zD3~-ZtM)D2tC-(IvtMsjzEtmDCuYqoN_+|r@)&}<^^9}8o2VR{BEt_XHAq&4zta_E z4!UU(rDZsl#w`LlbKe}w-^6&^-$w&*MMWP~l1nX+dDsq$z^ zRhrdsO?BkW%R4;M+I69y49vpl8*%^~=xKOm58wHTUIbl;9 zO6I%W(#_8_C$_Tn!cJf~LVZP#i^iptp~kC9P$sT1x10?B#n5=1nE^CNjnfVhi`+}w zAq|KzwxdIhB!1_QkUJp&j5&wT>K?HKpqQMdkR(N%v0%SvHqD8&Vq$X1o- z%v`G0IcJ-y@*z1+53AtNfp@ zYsqaJTcX~Ahn^CogKR@k2A&cjm9YSl!kdc}JWoi-BLnJzS71Tvc?T3%(3EyS@8#Wd zPF+fh^wZ@~`XkpH9hXeJ{R-;8)&1tpb0%h`Z{#C;UmHUju@R4Zsq*(GVUMx(w^)R#+^Hk zvCaUZl_ujDxP-D{Ld^&{7=+yOy`q;SYH3V%QB{FR4Kav}li-QyN%u|oPQu|+5GYL_ zzF>imJg1VFv`84Sg=7g#SXWnB9I)QB8UtbL+;QbjSEPB=W=?4pCtpb})yCeHSih+a-lQ5-LC&JH}WHPHok)J0ypdOjXwO$O9&g%qipoynOi`|r5i}~D+ z-~#oR#aIA!K#ITKeIM!bo!uh@n^A7|`_XoIPq1}M`>Z1cuv!CBnz-c0r((jv0lt`0iMiQUdLix{$`WTWYjXP{-Y?nDyxItuUHg=#Wg-8~TQ^OO zV##wgmFZ*<&4{3n=wp^hDO&?)VldgnqNKdEcA!Yi)plK0X3DJi`}j{qsH(cjV*MN5 zO*?Kzs7qIvnC4C@jw_qetjX@fJk}&VMcp>p0vis<^rQC>0PdeGZl~+*^>OgJ5OQb#pGUodzmWl$Go`ni9LG6a$5=K$ns}(H84?7yQ zLLQE)_JoUh!Yh<*w`P2@-nZTfq&xobn^W8d{-T8(5OlL?JOTl z&7i?>e~vqbA{7MH;P=Bp0cNzBU-@Ja{OB{!d2}(mJ5PaG-f0LLjuc`h{>Hd`-Vih} zpP|ItKEp9Fl@K|PS=^~~x2>RU=Txcag-Shm;LvtqN85S9RAUC%lLL^aW>T3CPHE)m5_8ZQos#!DmEqb8cdSOy%8L;+`ZmEynPENQ=1aFOX`H~=0I^g zNjZ2z_*qQ({W0#FFF)mgh@NKAWC@-?7AGd?mKiuwYTce+Bhx@iZWNVwKPo+gNfiZ? zf@h_BrB6x=(#nlOwg=-LY`s`N<1Vo!B)q6&-G$i%w-mzg0Z9FE8g7hzxdCUjxjb?` zN5o1x<1a_Hl%qEj4;i$NJ<>K`jrje_9DWX(a8ra5+PRy{AcUDSBtQ%P*c7Dmxx4Utr?epFHjjH;b zZVcPC{yq&?k7Xp~j38A3f^7~#Bjc^$k)s3+|BT_kft9mMogKOBsII6#00?mY?&AKK z74xSzfg<4~wBe9uW9}Zp5u{u?v8dDjJWA(sKF95f^ERH#r8xAZk2~m0dGUOpGR>0D5Z?1%l)V}K*4Vw1ybf*a?Yi-DU<9a+%T>=|?UnD4 zHRybgK3ujkypLWA+m4_P`Q~b-Fc@&VHLWHS@1WytE+-`v1`1{bb~kmmR!LG9&;Qms zQi+GTb76m-gi%QF42Hf?GeiR)KAEXJAgJG`(N}<&(kiCK6CQv)lPD>cv4~Af{v`NT zf|Wc2S|g6Q9c2op5e-1o?-S*F z+Q7-|TgJFgG%s-dk_g)wUm-Zhq2d5Knag&yV$QS8RV}BPI%y$ruQF7cx|96NL;gbZb$}ye!2*HaODc5q>P&nnwOT9oIa|?t9CNU^92|UY&7MPq20D0 zjuDk@bOnl+BL*wNvKf_~#*xQMok?#xbjA`~gqRT?E-y`lcnoTN#E)lbX*`t^tB4M{a(e>%0{|RxDYTbCX3k?fgmAHE)IFkFkz{_$_GMG4b&LUyXhYxqC zN?j~)2|il_wcxj_spc|8?S3Zur}(j2no%n>+)J%l0Ty(x&0)%Q9H`rI0^pDy|tX8Ol* z6p`0oA3S9fC_TV3F(oJse^|&*-e^u~)e!EmbjK^my0DR!S_h6@7kBhC42j9Jlns!do0P?@)Rmc*Z$xmkb@skBQNhI#g;Id z;LQPMnIp1B7umwlGQ2Nw?asJs%upE6qp6K1!mE?in$E7=*4HEKV!+sywP%iNc1V(v z;4`1|T?#ZOU7bD*WivMO9N9D7U2&IepV-6=U8Zn?ZEK41Slm}Tz9zqN5-l;3VjBI} zYK-pk{XxZDELQIc>hc|-#*iHcsJqW{8mU=4CI`hbh<|kdV5=p(9*!0)Z8@N4!;}%d zQ?NIeRUms@;2COvfzmQ0H{QH7yG-{D@FtFTWT|XrNTd%RaHB;Dx201RdJ!P{?Z<_y z#NRNtu|1!;Y5j@19t^5ILWGIvv;LmOb2>L%Gqd+HAnjJ;4OeJfox$E&er3&(+4oCSw432psIF=j}uMR@1N*E)YcVeFa_&3BQ?;JiH-m*ehO5H`dMsnoGL+;@VG? znfS4sPl7N1W$S8k8#kJ$uP|2-L<4gTfnIn^nABbf*;)rMNjU3>gl6S|@&P(PVnWIR z2Bc14i60GLtnlhShY@Q%#};(7|U4_gNuhE5cPZ}uOd0sP8Gk+UzSNmMi1ZcHH5StjUsG@VS<2e=(RXY8`czKu9Q_{Y`;&$BTK;feJSlS7L08&DhE8S(S z8&(fiY-3JCH-!#eWq#I0e%g<5a3O3eFhUcawXAz0Xf=tH z8%fG86OF?yN)MJa3qDs=aCSvLWvx3fG-y?58a{uLzE^cq22YM++NR-gtMjf9DnHS1 z^kHClWvgWjH>$f<2aRc5PbXW>pKi>WZ~F`tXFsm~*;6VD2~9Mg9F!QU>-yX)hFV+T ztTg)_^qCoR2+&piw@k33FuTJNTX+y#aNc>~*=I~84}dA*g2o@|`=`ZJ_l2QOzS%55 z93bmDW601vJL2k21@!^)zz?2hzH7^y#!2viDAR8g!1=F$#!AS0hK;=x1}}c%_}+$R zl+8W1*>;LL@1`W;+B|IR2C%d)=0U(OZU87zONn-xW}2(R-v0wp!*9an+2kj|d4~I+ z_86@87=SQmRyyC6p~ZSY&KL7L|7?1dpiBx@YxCfYA*s@j zHCmI=mU+&mvmkNi9{MO)-HLJGj?MPeKU=g4bq*PGJjy%~(nu7{@$pkC(TtCx0D186 zRxb=JFq>>H6Y?uITXPfHDHUW((m_j$Q2U(tc9na6M}g}>Gtfc76PV%66XNu5!Rm*h zu2+xG(d5Px_Q7R4>aNKi){@NEVunzkOu4h9$zb=Ia08EpFl?usEcHm#^YhHBvGigY z6p$rpJA>VW|7B9$sOs*1!pAg2<_rTr<7KlFXVUqTcsXy#2c~HRFeyAFrw*vp9=Zl+O2GI>GFng91K z`npqo8(;Rx=eth;oF+A2&<<-+0~+=`WN9tT*bPF~Dv$E0YEr0Mf5m$>f^^frXEwRz zh7jr^=7-npwh7QWe)#gHzbo^jmOn6lfDWm691^8pF&ssX5^OHGTD6hk&$Dgy0XuUt zFqhSkJ45Ra^WZ-pZ{7GWKW+hzTiV#^>eitRfr6rGuXnUiKkOwBh=sx0)onZI>8Nn> zU-y<7>3H^m(vj5-l#i@CRwZC^;JkmD_`vbr&~4Oyr@Bkzw1|xeyg-;7<`m!4HoopJ z{jYeh;-SV|UDB0G!#|`{PNJK-19~at8lhEu5rj`Q93jx~9g`ocu%BM4Thsu11;v za1~ieG1t(#O_bbF_gtHs`?f*I4;N$fqDp4V{7&Oc;J@$KX)wU=cXO<0e9bdL960ZZ zlr*?s{XCO_>bq`MnK8&B+-VIdYtbaJl$ySl(8GK?;hfuA1dmu$AmVLH0U~tT<1H)7 z!OhTl6<5|o`C60MW8umPzhWlAq3@VV6uc_UMc*E;CqaK_Q_7EHU=6Ule~dcr7C&(s z&DB7Qe5nJ2?P|w~0D*A`(K7TjqExk#<^T!IN#s8U*n45@lB938Zn2NtzkYob{e4e= zX7-xh14313b|q*jHsU*F+;c!5X_RA+08(m7B2yuYvjF$8?&JuAKEqw4zQ2qKcbv&( zfaUAG?eX|wjHut>!?q0u2p5s%cK| z%C#S1@!RK?d#htuAKuh!TuTy-pWDwUv}=OTAtRE)nN_M{;K3^x)uM$=L{Uh3DJRf_ zMTMEOFztRZzh6M}u(}VIsey1ua0x+Av>T&8%K6eCFE;@pke1+=pf%he2M`1j^FAvl z!y}qXAK$>E;FBu#{T*ozR2|8b!{v8q@1Gv#G#R5-dk1Io`04xZ1L;ZDaTNx>I(;91y;Dj>8+!rp9bL zao$Te9e0O_3c`JilB*P<*ft7$ymlfB0&2t7p`w)&_B60aonB51Z8d)s4U8Y-H5%G3 zgEQ6)!6TIqC7M%SKCZt4pmpfc{RdvA!d5X*6vcMv@Mc7qWk!-SG5L)c!G6T#9O?Va zT<&f+K3D(S{<(+Idz3v*!A@WqNa^H@%f&Gc_p(|=SP=l)Diwg9HIgRR%?i{SLF-O} zU=AnQ%bRKiW>~>#k2bZW&(u2V{?2tFlBeK5FN(k{!_^6v&GvXxcSi;j=mo7FvvsW- z*xXSD7VB)m#KUQv&^^I>6KP`#z&XoXBBY|(Hu9Q^#>*XQNz|R0O8zKQadhzWHS{mS zLm2(+&l*g|*c4)%_t#gh!$^UTxhn7-=8yLG{R3dT0t^CV_bnDA!{fjczovI8>Rvp} z;LI^2cFtct3of=jd{r0X{vwE^bk$4-=S!~4UFdWEzSb70o#UFUP z5`$^{rU>JkoEUA-~ohx7(T8-h+WT~tdQ$`IFOXM(IS8PL1 zc)cKQPt2N05`yxdIYu+QwM^Jy*N4B5NPzP=kMHccdbQ)w-yXjftKEII0+FZ*_+4fpOMSBy1K1C9P9zRIh$7#j{^XxVj zz%t4Y$oBVF-$eVvEJ=q9@V*0qGf&0Qfc-CB3Q|b7dDpgG$!w)!*=?e_!+-eTP%8ASg_jmW*$$H} z)7Hw~hcIa7X0h%jby8*x%5EsC2x3xXGu;d{vffo?|=B>`{R@h@hVq42wS{=DGtnOO6&(XVsq zvsHI#52B*D@!?LGa|n=O|S7^^s~y+E0e5-=IM3%KTOJ za(ZW0b*Z_hu*&1!bxcsjy9z8+Q{muOh$HbP|W@qy!vt z_~_9g3IX8j(bNZcEkT}h_H{p9rXHgRBAB2<91G;5ml;c=)IB8xWg=_U?Xg>FIZM4) zg9oDn>yt!2=*m9rq*awEL11$%KJWc#B6)U{C1T}8C7t5@(DEGR3H+H#kk{JG_3rr4 zN1KueO~iN=yc2hoRSW%`?lh2Uh=zI@LssZVAfaCKZBC%WpUDh6^a%X`^@#!9u%b8^ z5%!2|+*}1O7=BVF_ZZQ)$XTPXPr-4ldr?lAAE~8&pnN%=bQovIs%h(5 z5+^4ztKFouX~yf6&sQ?!`DAkRl3;5m!$mT`Lx`jp9fYR%^738!_`lUg?4a$2m8e>_cnU1=jJ3oZ8gLREzST>hi7{YiU z<_(`^`2piSlZv1RUWohoDVOl)a4&kc3&rJ0dflVxi^}4HMr#(+09&lZW!3hlNA|t9 z4O3Nr*yZ7Sf$43vT(!%y9pWUHTC6Ielaamuas79?aaUhcr~KpmT~=o5NoB`q*-+{m z4?eZ!P*ExK1=d4#e5Gr;>F4<(PyweIvZZwQ2juoZZlsQ|n|k)&gEveJip@*|oFKA2 z4EsRv;nsqZa|!$z^Rl{?Ukz00_g@%Vv7gKxYxUC+0H?~&B*@r3$9&pES zJAhaQpOP7G?aOwskCPsn@f%vvW(0!Zt-ZHR-gubWah*f9e9B-+X`(E*Q0%ysQ4FGb zf7lS~wHOp%eGSC6w>_MLOcG2fgX{lykq*jJtUrv@;O82IkWd`%ua8Y_8Z~&&UNal~ zo7N#4NtD;SzkF;BAXvrMAZu^Gj*T^G)_1Htbk3^~B#zoW_$Dr1y<6>$`=d=N_wO(Q zd7~l7-UOV3)^t>PVyo)TpEWx{lx;7-yP}%iXODz~ZMA}A$s;IcS{F|WZieisT6qan z0aF6~vYO{><|_EmE6Jyud4{4Hky3rEyq0HK)po9k)K8;%=xzcZ5v|*H}YMo?9Pr*Z93Jt~bs$)>IM4FO`uJ z2(q*)EPA&#=PX?7^+jr6|9H(Js;}>*P+mg6JXC^&1(9*QtMxN-aek?;7fW67TV&kT zh-;8-d)1oWKk*KW-8FR3NCAu1`wu@q1~3x#a4IR+Z!o=`r|qzv=%{dC{d9Ol5CXvt zOQNg+qQ3c-Re@EjBG)+jptUU)Z*Cb|kWhfyciuDUPu4lGF-bUx64-e7HDo1i6At=d zENEtLP_TWK=804?EYE!U zH2f5^Pjg^b>42JoT*5yaglgMRC^qwC6N4iwcH3wLS^>mImScD!G^fjon$T(^8qJa%$?}*EzW-}2K37te(Cikiw?ZL^RHBgMP*}uF5nxM zKaetUcrRY&;t`ncfK)HYk;))jwa#NxCf%qVhr>@QETm7+d<-S*2je%4$S%h6Oxt(s zt$_t8aB8Cz@{I=WK=i<3Rt#!Fk`;HC27g!L&dFa{ai~RPOMj#q)0f_qGLRerG0@o| zv$KC4_yHRGwz>luhA>IHvv5xU03ZNKL_t(&!F+V~Vj;1FmzL)=KIzf3I;$(}XWOEO z&%|rgGcUzHPLr9N{ptZ*^F37!8DTkxhtv}WrW%iFPNSDqyFSxGl>RRzDqaj!N?4h%=@ebG1U zaz9&RkihI-M;3FTaWv0z819b|cXvYr*v<^q!!5l7pb9o}LcJ!eZw`}9ZerC(;Ln#! zxUU$7y?CGT{=`2Qd|tFxdMT(Q#nr(F@OZcuV?LB`sBawin}0v`bMxSH)P)hT`a@$R zIYg~Rd6-8Q3G&^issFs)y|t`*0EmihZEr4hf}sf?rx4=smdS%(1h`em)Hril4SKV& zc%{vWD@(j-80L|6Jw5g?n2tkce&8Y3XUC^|CXa1wLAVs?PjO`#gT!rpphNnQaBz&u zg|Z2z6Sve}t$s>!m9CzKSO}n+ zrVTKAZ1t|ag}r1q?BRLJGtdq`Z&PZ&J3oHh{^_vqPV05-ws+_ibmKRGl3NpxE8nX1 zH?cBTF#weoOW%C8asA%#z{+UJ!Djbl_w+*Qi@(hX6aX6rk|9nXuIK|q`+K7b1d;DE z&9x6y$B#KfYDT2ADcG+phn|k_;_ear`Q3tUv4P+1nhTm&Yq~AQPTq{nlW@&)4HpXw zmuY^00qDeAFhW?y1vCAI9VX!r%UfIU;98cxBG-)+Z&{jwV%*qA=(PRE-ya@6O+P>G zV0#0Zt zTGf?Gz7SR$*E`60pdBHUDy2>r>nHq&b1~TmqRAYaFybz8$DK7U)*_*5?#F9!i{pSV zMm0U>#B;lqY1lQ4>oGOA2Kto-O(WvV1xPkF=6W9eA-#ALYwgrk{H)l1e7c`$1$Ege z?x*$UpZ`iFH9ia|PW0tlvm-7zAEU#Jnq zD&_XR+86v@H(ji!0OO`(az?SGWq2m~g`RVVvORu9GR5ukEP=Q?^>{Nr#-f7+VA0QP zF$C+$n1J*0cJ9L%F?XqN_Vaw6XTTnH3YQjNv}g|LJ1!Ti;K)E~0ucK|_7@pJWxeB` zDoXZz>n(8~n2pN^G^ODG{P*L-X;azmd9ABLJ*)GX!B$^F@7m@>d zyglYMH{0I{8>6_ph1>s_WrytSR+063X%cu?(6D>Q=wokM2zYV+XFmWW;Ph!X9xiI8 z<4};qz#~16F+6h21}aag+vccCl}i9@}Lu-#g^y zcoM?a3ga|?C+_o4+7{7F8>yKJB~RSz_Wby(#_$i24VsU?DDK;8?fmZ8E7{ZyWlXAP zQfCXBXQQd`*S<2J%yH*+@Ie*%hQ3&FZ`&#Z#PN#lgm4I@zuKqTNa4L1IH}zWCPzl> zhw+esG($MuaJRN#%m~Az3^QA#|1IWJevWod9JkwhKj?Qj;Fp*cJZJDnk&8QLFm_xM zCGLPm<~bZ!Qrwx_k8p#Y#=PWFJknvS*z+lmOCll_G4!o>cthp`FwzLHJau=hd}qHcc3 zs?~Xf`bJBRy2}j|K$?m9W5oR!{)vOHRTHZt?D%mzemFp7G2uT2ou%tbfebtD*$O?w zmy}M<*POv5{~WVVNVH=4j0fg$6uZjzyt~?ITgD&-dp1?*hu~kgo zSNI|7RI~6y|Egl0r@-2%(wivsIBcg?#=-l_g8{~nJ$okktN6G#d$*#kxo4_sYHM+% zxNA1U4B72S8*+SLP!If6WEA*AYF5%;v#8v2aQoPS%-B|P+@DcJQUAIy4Mw?niRr*? zxh{Wx19ax8W8X`crnsfinR!AXWfm$~#T`rJCmn$&wjkZ{(ThG_ar9E9P~bhE z1cEo;PMa^k7>~;8X`Ov0@Ko8!V0$Z%#A+LvrOK+3wqhjUtGmNkvFJkzVXq_HBXoue znhfm?w%Nx-L%F*)PDukjw6?zv9u)wj)vT<|(jKXGLen`*_Deu0i+fT*<}5SM^E5%K zykxCC9sE!Ra*B_*KQG0*?DhtdTox(qEw}8`QuHdd;{&RiN1nu;b?!L)77~7;GdjSd zw}+={qvzcwf7aRQb4#TGFy&U{s-PE2q>RL9RkQaef+kOa4*w|)*WlP)-L;M2N(dED!peLcjnS3u& zB@Qd8@F3kprhob47Qlecr|>(DI(`Eebyv7#B&@bG@(cOaSm+TYUU5!^O!;UhXQ?s!5yM zC?$7LOGQUO?anN3egGe!zmRBDSV^FrC5Q-83#nY2sFd0&yCz<;Y@TRxK;om;56TA# zM4*wX;AwUPFFAEBS74Hl4oFzhdQ|Cbo$9`&EcYQaHEMsf@t;>O-*r! zuh35O?%d;^i?~!X?j@&vxVE7{oMgt;^$cr-tfu?BF-SCGMEvWVLc4 zhl8&}Enngm0GeH!fUdb5y6IbILWx^d1jC!I_q%`@GhHuSkcF z=lWQ^&os~~wQ$A~HU{~%JDYs7I#mibbDdlhvaz@Fz16CGLm8K*?bFJKsr8d)AX}Va zoUChdGY~4iLBe?!X)h3`S*cW&;!X?n+e5#kMwUztamREygnQfpyg-s|HU zZX4h+36)b~a)9htLtuk(hmPTe8UBK)(?yo%h`GezliV10og@R#Ig`yj7f`%U&YR>-iQl4-Pq zlR-G!{UsO(RN#9-KQ(FAyKo+W*{ki0;=M-m`9%6m@)5c!%Up^FQF8mM$ay>Usaond z+B3*eOF|52U?rL5Qjav^T3c)V;YgVWc(c#CNct=wf9zjYjJjrQ-}39U)uXl0s=Bq{93Gox$<0H+(jltB$wrv$M6naa7=Y&V6{oJK^y?5QB9Ze|;(L!RdCo zRp--zvM9eG|$_``~r>hiVxWG-TuLE+iD^-ZTYZ_GzZ z-T;H>B~?k(hGQlI7)m#<(m_k(zx47j>k9>LKYneKY%2#dw^2!fw>{BlW^MHiADa7n zHujuj7wfheY4S$jA;7-a*T(E)H9Gt%<2igT$Rp0!ORMw@$qb%@t3qo5El^^tCA9|n zET5o6e9Jg*y4*d@)i>GN4Nc4bKL3+BMl4AZQ?q!<;;fe*_acW$910oL^d+APRx3fl zZ)-^=00=7`IBV!NWi3)oQdt{cL!d{!M6xRMUSt(;eo`5iqpsYHqU-3Z;4cVA7{J$K+=mXvB+w6mIMUODEh2IZH-`(}uS9{d!b&(&I1Cs1YEa~b z3g4X)*}gKn(>yN2mL;Sm-;{D{jP_3QB`)!@B}d%S?Y@;q$QQ1~nJk-!FETawv;p4^ z%k8JMIc&5?O*amjSmBIxb^>E}vPtVY+u{>Y@(24HrI`c_o1>yJ4vatya3Po#T`-V+ zq?#7nBc}Kccd1zhl7c`;@<-L3L204}BYh9DgabQAvJf~a@>0y|K4-=HaHh2n47am8 zHjJo44!faL}S+Gu6Nw5 zut~nIe)US9+^pvZeu{6!mGW6l6ZVb4^SjTr$k; z>LX+j%jym3p4%b3Fl)IX#5(U65RmdDZuB4iuNXrB6Torpp)?oDjZW86RD z&)Rp(_EV!*WZ~uO=U~`C`1txaZ`}Bqcv5A*;@j8kl_Xba+K0X=&a)(VSvC0Uc(6*?l|wQcJkZiSgogq#G{kbAU2c?c{;@N?^|C&S_w_owZhv%ky>kmbV6oRT?e8F-HhYhZyHFAv_^%T0Sx;w|)YBiW|5fnNRDRU)3K_H!-r828^0cS%Da z?ic#n6cCn#E|B~vYu>h*4P2=O@hvO6@1k)CCW}=JygkIy!!{X?vIMiS{b%J()2nU= z!<{&3(;6-#s1noCfo+OL5XOV5SA(j2Ip1TlRs!yHRh6;2D$G-j+`{E@GTBD>T1 z4NH{qI9b1X$#>FAWw&&=ULJNS5Buu<{1=jfv(omq_oNCl(^SXeImX_K83=}g{mx2| z62vlO#K1Mim}?-c6D_P_@@f9qLMx=_=}w{MK%{iSenr+Q2dTJ9LDVqA^PcA&ttk@e z$br*?g(ZoTgBIQqcZv|+*+@Z~k<{SeA$3n2u&kx}J_t=C8*+k#v`r6hU-D7dX0vEq zeJCqsTVln_7rl|#(@HGE=i2%1p!EX*!IoMML?`oZnV_1wGa*BhY2Lx8GG4PU#q((= zunZ+2owvz?G>JxQR(v@g&q_4!D;pf)jb-lgIU(ed+@B$^3%PDEHa?*Y3O9>9ga@T$MiSTWkw-s z&WL&hIdlq-JE1ov#kf(-y!O=EkjcmK$k>-`g^W~_m&O)oncFL1@Uct`XO4d>X}(d* z!=-4jSJ}63@j`24gx;Osm(V|+>Dl!6r^HPCA6M6s+qjiQYYQHFN|0{!HU!l`Q=-Yr zIA~JdfGr~PHVJ0rh9_P?#{`)bNLoQ8@4$;`p3fy!F@mJxN(xoi&-dMT?)mh+f9xmf zNX9UBa=_z{WMyC6LV_`jz#60Tkqt5^S@%T$LPiY3wk)D7md(`|5tt~v!{qRbpRf3> zNd&F$<8Lc8GtV%zsoe!F(kT2U$(l|s!QvCRv)h9ojXXC~jCH5r{MBIfdWv%;U=By{$X#94y@bmZ*^~6{8k-^hA6G; zew_Sr0>!cC4DUw~5tWgM%oGFxsaNqiK7Ts9t`c&0wmPY;U)P}fT~1C%2jBqn8U=*{ zi65P(Nl{tBIr9EpZXBD0*36h2p)&YR(@wS;5bt1d1&fIAl1y@?fWo)0A`+ZBesyjz zPuY(b3foAJ%CkHpLz{*WRgxGXE0uh#l(l`wJlum-I3k~-?tqhNDj{%*L<5Gi;q7Eo zJ!GB_j7w}KmKS}g3D!{8cijy?bvi9sTT@`^LMShSTgH_DIk~$Z`!N=R{6sI8ZRFF_ z^fq|JUlE{txqfGgpzh7#&+7+K zO4J?GBeGiXO{<+YQu?6Zv&kMy-Y&Lo8Zw7aJ@JM-0lY+K5%`YRX%NaL+WENkUofD9 zpwV$%8jn}LM)AL%om*j}aw%cG3_r8G2Vb6!wtFfNxcU6X`A~OiiiH!WN>1x}xbMGh zK<~h!=?y3_tDb8Aq~;<@2I+?k%K6Pj7nQ4oXBg2vZ1>Ot-?gDq(wi|IcE42L+9 zH!GUXHN`}nJW~lp? zxY;wAOX3-5vN<&8)5~6LV60x1bgp%3!=OH%_lA;-!E08{Gm&38QRj!~N*he}!|$Je z87Pl~J;j6cs0ZgnHU?g#Vq7IQs$yL~dM^T`m9NLai`9EJHE=;a8tE!8Sz?B2e; z(tXCNJ|JUZMY9T=Xe@@hv%UrHRcMJ5!|$v$K*&^$hQ4EoY_Nz$aI=@|)Zba=7#9!wv*g<(iIyH?#Jc4W09%okApfp0&gIhpGTKTlmz3Zf&6tx)dMe6a=+d|Cxk^wOJ*nTbryw6n;Qqc)9y@mD2<3~Ig_ zq+H5L;SYRoOYEJKRkmv~qUV_et{a67;3;`Zcbh!DJ^5vWRF#A|D|iwi;Aa2pMrvVP zufk{0ZnDe+4V`H)FJgwtnzjg}eJ>Y?%8<_9qGBoe#rB&I5Fhxm2&Yc z=$Ts>5Y_`W#+$s1*oz{=kq8@Mip83zA4)OiOsSTSxXO=6(xMFzwrg{B#Wio2%s#)H zRCa*ynB14wD}Fph-8IOsTKaga^1P2zq(6m;Il;6e>rQITYU3YuCt+SUE9p8HocHo^ zs2;dYW8Gi%5oLdqq>N4GEwoJ;nKQ1tjcTm$&~=Ky58#sW2*wBr&!r#J|HRf-pknFM z?reg{l?KdFOHVNZJw&MF!ZzA4P2v?|c?T2cd&EsrlN zexdnK_M@%7<2x5)^`3p^{XSINAdPJuShlq-$0pIvgV5Lfq{6O{A!X_#>9PJ#B%2erHw$)HU*(?q1n!aJ$ZZ zJp#_>i*-j=y@x8@gsN{F$%sDjf^gRoM!wu_BZGkcvvc(jLdnj;hFf5Al z%SB(UAxpx)V*m6A?0^7$t1!g_H&L}s2^IkevvqOwRrk5N@QIlJ$bX(b2s}=sPz18# zIn<1ci>(OL-bl%9=KRy-Xr9=O`~Zv^&Xci|RUFH0o4I;^r;X)7tIWca#XJWy=lO0K zX*j>{wmZ9#tIH%mJC5bF-e-wZo_9T0H;8n~gD3ob9^tV9Ntn)BYm6z>Yh3?Q3gY=u zx|anC!5A{G8M0P3FZ;-CkgcQ!$ySl{wj7ZMisPPX5J2C3)O{4sgOY$(kL1~jhkeF7)0tXmjM~N{r zrAXCH%$kn?03ZNKL_t)eaRhsgHmdmskGg&TM?|zAgiVUK)UwYUWUJc7953xQ6VGV| zL+LPdAE&m92}Z-_fd1dxpb{{$ePYILtycWwOMH|X*VSxGVD zm&N1h3F8dP&ZM}62J-wDgJa;GDk&5v7f?JY@RjsUl@!7v^;MWp_Z8+(bRh3ytExVP zjUiYz{Ul2@tL91mF!~O_3=e+Ry`L|)#tw(dCLRYZq#~KZi~}t6E`Bo|Pq*ZmaWN?P z`M#xR*?A$-$9WHbEizV>&qp?}B2#?cU3euVLioXq4}5GlJ6)*QV`o(ws0`G_$wQrE zY^hW2GVtyR1rA?GG|$chZ_gYb$JVib(l-Iv!uv|A*P@Q(z>Jnqe9fZkFVrStH}rg? zn0PUGql@7htkrZ*gC1#|%7e|e<5)jAv*7~fx`aF%S||-&5QWF%s=`sB$5o^tTA9<* z+4rxZO`z?npQ_V%CXcdRWO5a?>+)Mt;W5xe)Ha*VRw*m*Z=wTlG$7Iu1+tz4gx?3pj`}VK2WI( zJ8CN7iu827IqxfGb2^8E3fEN^SRo7jQQP;x;F*1^ z1g#yF9ztbA*4ro%6s*qJqePnB(r@$i>-Y!IUodIbHgy3@ z3{Pt=(Vs$uCXEeMie;1hn<+qUPED1$$g|GZM#C!YYBVmRiP@qv`vj&q1UX-jsS$+7j z0r(hkFJ4YRv%jXVq}C91$=RBRr__-!R8sxyffPs{pu)7D?dP~hodGo{A|gq9IQ+Au zm3&=EjbKWaXBeqq%~bqn{3;o&!meomX|TpF_hm23`{i`flnv3Bv|WWzIri?Q&CZZ1 zq;p#HMu+x$M5R$&wNLnF(%Vlqa!v>7A*-b*-17*5;T~!@msJ+?O4x?6pHda z0R-<6_v`x|WP`_<$0&X4|GwfgEF#)!&UXg>J1Y%Ju~+=FFou%ymDj>wWo30u$o;H4GC1 zrD^s}sO!Dr;4jf^`1Yz1EoJrxfVi6rI5~Q(=ScB0v))hbX!Yz<%&Np?rjx8B=!+E) zi~-5pnL-BX^U#5}JNSz^eEPeqokPzg=ure-#T6Wvr>c%PdsX=+) z0cZCO4p`V({h9Q=?c6njy+KdF250ewV!S4ERlQA#x}T9c!=ipylZSz8>?er166vLg zu~eL~DZpwQy4R49?3>qN@x&FpU*f~WMxEvd;*0fWF-59l%R2Y$;8_nIS%*V#_@qWl zB-mvJMPFW^+8^CWA%KC9w|-X(U@6}zmV%38Dm!1{hu}lQ5lwEzb`1x3W!KMr!R5-qlOQy-FMNN(XAX2}y3;_G_I} zncm`NR8k~Zb2}tx|bo8h&y&aharK<}D>N?+Up&^G(cBBFg zB*>raOM92^+I~cxp(M)O#WUZbQ2tCNDx}~)&H26&Q#*T||1b0BEe9st{J}brvdy37 z{H6uMy8OEV`@N>`M79o~pmZZ&@_mK5lzk~=v?Xg8u00s{+S+dFS18A)5>y3Efv#Ms zi3C@#kH2#Mrx1{}))03JYz`ry&Fnu&oKQkOm%C2#8YU|oje@|Z?P}m;H#I$0QMrUv z$B-oT=7}}`7wsqN7WLivu7<|o7|`IL6g*2Ael7RgIr8(P%nj6f_X#vo$6dm1v`5J3 ze5o7mO?iMZqcHe9Ie?@eguM!CG-)N6xyLj}rnqai4M#t^M3LiEEx%i-SG95AwGHV) z?C?OOL|r`hu5535ogqx8gNLb0lD5?%>SS1qGt*7|BqaDJNo31qaXIz_hkjX0UCh|w zR)EyP{P(G6RxSOEK*_}Duo>$PWk!FJ{tv_?3$-=ua1h9U`)8o^2~|ll^-7Pbo2-LH z8uV-nqVc62wE~F`LkiBMbK3j98!b#(>_fNTPbWp4YunqHqfmN(ChbXuz3Y16!SK|A zAdo8!e>o;p4~UVKq?jU19~t@SA|WGie=yWu!!|32H05r){(}`H^a#TbpMI z5-x#_k>ZgFE><%?e;6K~D27Gb`-bbJ{nFnHUZ4QqJiiJen0x#H? zCPez59>|~MBMUFI;WT!8Nf@||xi;DDEJiT+NNnm?jnY^AMFpg>1X@b%cci7a?{Oh9v4i@nN@1pb4Y8Xe9rmNtN2sIiB~bz4-f>}=+}{?k5hjV_Z+13+Y3 zJMU&80cTcfp1t%@8YLtJ9|hzWY1gQQSJ9z!!PBvSfH6L5YmW@^Y0oR#p9cME}L z75kC0X8aD#3D9-X_R4PNVYTG@2lEQvOrZ(wPMRYg>5zzX>|GQa-5(GE1~k8gn(9`P zSL9u!Dw;tjOgdaDBU5|Z_r4?!ov!;ad5S4<0*6z%0QHlfwXxcjv|6F&CIriCM}^CNM< zWDNS|*u(Z0atm46e#O4&qX$-|yP0DFNK#hsjZbHpQ)+KH||jE^S(lk z5=?yP@|P_X`q!+(+KEu6pu}gtH@(4bX0`5(8Fxa$Jnkl5)|3>NEbUN~rCj%`>cGQ} zwQa(LqOoSS@iDEbEN4q`noh@n((ZwVwrTOhT{jQlGM= zp0Jli-0{2Ni>7?nSGg)!-#s@m-``e-f{&u79#!FKEq{McoLpCm5H}RLW-czI*uX3l zJ&#K3Qq%%7-$liu=WJ_Xu#6PAeE| z_=X&Dsjz`300HokE$Q)*J$@1x$g+R3V{XQXsfj*^it7jIDrIyVcSsqR`{ znRU8#<-M6MU%Bz_JTl!m%wZk%1C#`SW?|yNrPJ7(E+`@NWi5rc-$)7>{2pU!I!uzq zLEOs)TP+_5i#;mpB<#ImWPScXDHdJ4q0g9 z?!Y|H+$OS{EZdp~y}b8Wtz2lh>suKqIIbZ@a}*xA)5d8>R{Sp{Rj-(G(m1vN>v?dt z7NN@_7ACr)VMkaeKlwMe;aw*9Jx-VW-U(1D9cRA0u}lHvvoB&ZevGSSMaj8 z1ZiN75rUpTSrVqQHz3Mu0~Q6(Eia2(!zM0FWnan#wQ|2E(@*FbZ~;3NappVB>^qV~q8XGYu0_hXokg%( zjgCoWpeme74`JYKd(+Th=i#|nrX7QPFnTRTwW)FN6?J4Tr&IM2O?bwU9f&U*2b%%0 zOnLL|T0c{Wc+7qlHV6%gvJ0{96IIMGiK9p@wNozK1B?MkUoBxrf=10Kb(}y!~9B-W#JB} zG7~|BGuTmlF4~PN-KNiRryf@K_VC!j1}9!%Lz%u-gjq539rxWT9~WC5tT$0dD@phg zG&{twJX)il+LD)F@JwLCJz5ZJ@?3bni+hxmqeSE}Si1{+7}^kfkSf+Bk2tme$*QOmA zu;SzF+3Sr*+t91h%;WU>)ols&$B2KwO0-D>VU%e?FEurrj>LT^?3prRJ;aM7$$!1@ zxuDJfddY(|bx!~O9b)iDtLZ(8p4G1eNoA?AIsxPU843}NbqZ=UE)*z78K>M{3%QOp zcT%3n^XCMhq#{#Eqxq%k+mXVyH;ms#w#SY;E$%nR$AW{!ZRVf_@VjM88Rsg4ACm$$ z@v)Ig6=o-uc=%8p1mctP%AkM!as2W^ap(OoWr}?;(r^+?v#l)9vmC2u)E&uF^PF8%#h>|uDaBHbPL6xYxxK<}8^!%e>ivo&r{ zMf1-Or$)w4N?eoc8Pnd)~0P;@o74Nb$I6<1=2q)of2UFt!e@+ zNEN@orPEiQMY_6glo+@cK{%oLqBvh%tB0M8Y13QKIhT?Rd&TKGOjp$c{vvbi zM@t`s$KSlTa?L)B-RHbK`vlOI9Af`e?c5zM0!3X$T1)}IfP)@czYitJx1Ub51I2%&CNrgW8HA^rm|f_;8NUE9Jg%f;r&6n z@iJ9}A2AadaaY??WtxLJ6k-NR8GY2YU*^(lHucq>m6cLSqCm~j6 z`80#gFf!yvS8@q!PnRsZy@WkXCtmF4am`EeXWz*%|9qC?yb)G#kWFz&g9XbSGR&IZPquq3HwGbiXZkj=tzZL>~6F&V}^E&{=9oa zOfH&$WDE@M%j5Cp>^#UENVVUk9m?j^kK^_aahJfTLR@x0@fEsEQ@Zu_Q_|)V1SJN*q1}7Mji3JKDGVInV z0=3N$73e~|IltSzPYp}1Gi>1-*$z`p@^p4zlgf|c{^R5Ovsd1Uc@wBYD1PgQL8f47=IiaXpUsA5p@7;atUam2E1kFiWlBQX-&bh&#M|0WEe_W}nm za>BTsaVKXUV4YL<8~virBf@= zQb)h7LZOFz0!z(SV;#?u5q{)*_5bo+E?Wp9*=DA4?{#z96FJO8pV`SU%MWB<8pVK$ z-%H=Ar-Aofm0^^ZhrqJK1`>N(fUU1Kgp!s0v&oZ)y9N+>0l>eGDKD$@IiN~U%dr~e z2F6*yJJt;i6B+QL(Omviw~BkMk|Hsnx{T%paj%O_I&h1nfiEfrvRY0@6qM!KN%@4$ zw)!}3i|E`{WTaNsEtgb6IM}#v2{Fh(KCbR%$a?Srt6@2V&VKH26j5Qrr-BNAd)G#O zjDwn)<9+k86nlLqN#s?69)y!IZhdfX`SGguo8RyJQA-)8~1j+zC)8x%3}vd(H$nqC~BZT02r z=lt6u?>UiaIV5oRxXq}Ujm<*#!R1C5Z$1cbt~;5_*=H{JA(Xl~fUQX#Vwy?cAF2-g zlKiOl6!M3JWaPS)m29d)ymz*I;cQq~O*s@o2zFIBnW&wU{2ccujN5C1A`$YnoLYUx zViK?b%F3Wy65CN%MsGA#iaW1TI3cU71lJiZ$>O1FR9{HyjrHj5PuI`)qJ2zziq|Y~ zNacGU%rj4B1{D`HH4_CV>6VNA(C#>!BeIic7q^KTi}&8`W}^K~p_z_Zgmq#wqjq0% zHL?`__7W|=YyB*T7ZH0#AL;~QaiX!ROXT~*$)_pLQq_37^%>8BxSyy|F4St?f7I+) z9QT^ovbv5Ev3_@Ww2pAgwQ6NXC7|Hkz0xc}aYs$>6yvvFQrz>E$)%oWb-NTOwxG`U z-Y_!c`(D}wkktp_0UXvAG6O@f#GdX>OO zJc{Sp`z`7$0xXD8koPuy-=;c~W!+9U?pYbiQLYv9MxFfH>TmY`h{saI5t~{OOx`22 z3CWIPkhG(?3zq_{(;iASe&oqLz| zBRlDCX*~mWGepo2S_9q(o;U;Vo&XY{(5-eF7t?keceM9o=tUnR?!)k9*2Wn6z^R=v zawE>u)7ecV3wjtO;$qb}@TAY5?<`tNO)YVjlHXcWJX_^n=5YiA?|KPGNUw>yi*iVZwF94VO>RPq4wPjPP~ z!&=^*tj_nFsP{SF2Mc>jg$bB$i!t?d$2&^=mMAaGY+$tLMre~cfH(bPihm{o5>sGV zvLmbe)!cgd#Vv8a+P5VXpw-UMUILTJ%kzJ1o|N*Psg9j?+*GMa;5IV#if8LIi@&Xz zK||ZnOmaQnNP9vRo0q7_(^9T}3SG@Q)3n(4aUe|eO7&s zmszVaJwfM6S(_ z001BWNklS%j^T_itcM{Wp`r@z?@PO<1;-`d39(t~`y4ZZ zY0BdLudi1>f}=60&mNGaww`s!K#mLJj%_zCQLJ$73N8n*zRg5!X){x<`2>jXnq~-3 z|6}V4a^pslV1GeJT?tbA529s&S7JzG_b7m*v3HTgJYYz0Prcx!Utps3fq}I@@azxv zG0TX^tYS+R2DS&D!yr35D>E`OLhf3{D(N@-KCIMA!N2E0N|hQ+Pg6tHH^(NkuxQeV z%H9#eluunrKdq`wH6`R`BvO)-kR;Ag;Jj6a-JhCBu!Zqu;l$Hwx7X65yEcr*n@hX= z)A9WjkB!^d1daHaZNtQmAT;fZv?Ppny15eHyHy;;-OP5m3fW9?h5JD$xsFJ8o||a1 zd;;EbF8oj%S#53;)Pg7X8Uh^`I&LMDR)((!X zuxo?~LYZbXOQ`9>d!}AufEr@V!^>(MV%{Xwnss;uf)^A1JXqF?rdO+LKZI8(8on7E z+q+{UBMW0Be9ZT|KGLXrA?&aXi4M;+D1w)~3@B&@jXvKb|J6}0Z#NChtTd{M9o-|2x*Lgi zq5{E>e(%E*TF-$^Z>z#2Kg3*!u*1Nj>ovg>onCX5>_L39&B>|rF0+w7fP68jAm4kQ zJ9H^yiqQ)E9Yo{e{T6;ek(==!CG-hqjfrZRViPDIv=|`)N<=lOaw+b4az3E$R|Q$W zKEL3K6^?y)Nb^EnJ@xs|t2CJkQ!O-vhuotIgv=yn5PR~4sVukC`^sxkXl;PG$Yf3uGAYA}3Z zuEba7zS>TyO>%5SPqXHG6PU6yNwWAZGFj0;vOjB{QrtLFqH|^x^N=8JbsyQ;z2SATw(Xpd?$@i+JOY8K3?guV z4>&!MGsdB`BtILwYy8fIASh0G9*G|@-?`+@EZ@0e>eLrDUDJ(_UxvmyMC+hTGY?jA z8s~d70x#Qu6%1Xt>t=UNMjnd#0S2Bl<&zQsM_07-n_O3JT7kU%z;PNsig{tK)02`^ zF|m+E^Aiv{5wN3p4(28vtr}FI-ra!5ygai-+%p*f0SFuWQ|m{oa-2V#G!uOl-Vs!V?Op()>aM~3Dx%WA(z*t?iz>-QmPf4dsmwc_5d z?jV&dE(lNjjM(H@j<9%dWJ35S27Vk5`EER7{0T(9*>GJTk}>WJb>Q~KasQVe+rR$$ zv1~X0xBwFnsO0yEoDz1qO?$Fbmk`IgUj3c5+oru!&)Sq20ZBC1NW?DIBNBYh#@E93 zP3iuCW}k4}G{NF8tEauG$u%}<$z7QN5kRq=?M!+7au=PgtiS#IVf2Ji zn6Y?f@U#aT3LiPWd`~7gbBSsYYuxrx{pT6`JgrZ)2uB{e3mdJ(@E8jW>Z zcUm#nSrq9t71RvSu^+0;htQK^Jy{otU_;Ph&`TOz=r$*8kg{!8uQw+(0iax*VNW$V z27UtzkZem^G4A>9_j{J^#-3rW>wQIGENaMBV8s zA#7hd#cp2ek?P;`LOR)i3JynoX%L1l&PHFtmB9YnbD8`W3E5g`8&O+Mt)({A;KSFI z_;?CD(>)K1aHvYybOjQ(ams3&ovc0Ie$l?qzei9`l`Z zsTLj>qjFPfKD$Ku@uV`37<|B0C=d~pvjzF8aO7qnN|{`CkSa5&WG2+TE8n&9rV^0j zVa5jb?j3__&9XDd`=jc1t_C^z_)2$}$^_RT-!CEG4|u`KsnwD9oGTAk4PK+I7Hhod z9Or9*ZFxSA;nV{Egd&lNz>x&^p^AJM@Rh8-tF)t!%ngz$qu*A>{?VoNq+4KeS?p|} zcH6?73PiiXT+tgns|%O>x7I>G(EOiJ?v_9 z356S2=`~T&hEM1=E^^ylRK9I10>evV5`=uWj&#u+1%(O_OUB!DvLn97W4=G?fjt+- z17_UM7xg%@F{AiNCaqc!EaQCwZ8W|ssjdhDQ*!jm8glaaQtlo4P zwK$WEAHz+=Ca>=N_E_A9MX=4dOs8uoGZ*ezuP*NPxY{#o$U%WG#EM>0+Dm&*e)}U0 z?Tn;R_C%-SN?zurl(W;gtjmmT8uPvM+Ws--5+Vc1vULxl{X_f5fB#2c!N%Q^_b!yh zgLFrVX7xtzkZn}mhHHfOpj|L{sksmPFwGiV$r<)Dkr4OW)Cn0w+*w@S(AJYo#t%Rh z2g&W#eNk6B&FJ0-o@|D=N7cx^vw3h4_y#+bplT}_`~ zgo&%>*v%|2RuEYO-0LB3*xJQ+-qr+ z@bcRlny%{tDi5Yd-~Y18j3fWibIVV2Hs=s~SOwL1-V3TB3e2wE>p2~E7jI=I-I55e zK{tvK`1Z$1t{zHq2oyjM1!t9)`#07K@+o%Rh=vE3fwCGU3-)C9!2fb^ z;%mz2V;tan+AZ$s>Nnp~ja$Tz*?404{&O4H&zPFLRh)p~%)C43zb*XE?0wN5cM2>a z(vJ-LgIRrire|x9y}DBNbE_MP z07oO1`pmX;|iyZ6Q7YZh_wv0UG90&*F*?2wiNrm#v1J784)Y!wL z@%PL_&SX>px!X9U{?b1N#hvox|E~M&rC1Sv)RI(<}BO@;8){Z%h`OWrjm)dpst#?!DvZFnmC1J_TQv3WN$wu1OB{ z8b^mQ-Xeeoe^c4n7UQknT(XP`6a6=gyLy|k37KA5->)&?9`y&;f_I{Ub5;w{#7O?& zuSKv-OwKT1-Cx+c*?-&rvnM!XC5AEPMw>*Vp68$5QbGk8p>|wPBEKD*p_Qf2NR_$$ zQ9*l>TjfB=pwV>_=t!m-1Vt>@r0LuKBXgq*4Ax_`TT*V^aB=G4X3S>Nv0WrJB~Zt3 z+=?X=HI-OiZaN0xZ9R<`hrUxsq;_=ws~-K#9{8y2_7GIB{?FF6X4_dc@JZN!cv zr`^DE_Jlz#YH9Y;L{^u3cN4QJ)O6am z_QXX%lAQgT&OpkZHmnqYk7o}Lfv*y#oE`*^6N8Cx0g%O{$L}y$-SPZF-H*p*e_0-S zn{8Gr4LfeuLGsMq-LmON->bw#A8EJzM`c*S!45l{K3!i&Wi%3RM1*k(LSiaF3% z2Iu`Pyj#yh`*<-7jMhx(G-&;-`sw6?dmCy@1+LUH=E(%R71-zqOa#c(-|f6ZuxEzknawiVl4i7!lx;H?r-#Ai6B6B& zGD@kLxt_MtL&havl}310m}tUa70~Ulo4COx&Z)$&Ygw^zw&X4fu2lCF)Yvoo;Z* zV}*zt(i=4RRF(IBlbCme-lf8Y?ZD@G;Q%CrII;?+_^hnTwsJqM;Pq!B3;%UiHl+Udk<&doKo;ppqaVKhu`o$WdkPu znijELsQVxn56e-*_fNQ2RqHi==)d@dwT+Z3t34URe^Gc(4h5NDfBtGq5UJ(MA~nDU zB~LvtL~VZO44J}xCZ&POh(kI7RT+N_LZf+GsC(uN4%A&yTojlQAJ#=$Mi)4oZyP18 z@RpV<#U$2Gh!gG9`_T=YfYDj<;V8==P{3Lrdq!ULpcrdDXw zi)xFEl>U!1BnNn#{m3~|Uh(Cd4e-OP-#*XFD97qAfHIvD2@i@B^?YJXEzY|Nj?=FH z;42$B?CHd-@OH;W27-kn$f19KzIWK*^F4edid;Ec=}?ybTIcP_303Qp}Xv{a?O%7y$a~wMQ0S+Xd5`3`|0QQFK0*3 zJWsJ~82HCX^sMwY!@IRqK(txv@j|T(jjzbAp@%sP0sxsc>@M`*-=gN* zn-x#~qQ7r6^BiB*Yd&1DY%_TIH^WzY!-pZVd`RKGpUe33gSqWOvXt%&EAs=NWjL2A|Du*v+d%PXLCq=U@MXR|*aHD$6{-mY;duWuFR;*(}F)w#*K< zsSq|rM&m`A+cwo5J$>&~xX8Pr$Cxq6s-l_RDiX89^%z=fC}n?ci~aQ8(ubrUxH~~^ zE*ncf)(o<5YhAefItCt$KbmL`|M}m~LbYQw$Y46jxP5ij85$A5FUf4=L!oR^(7)-F zp!2@fb-HG>&366>yw3=(S;f4Y{L9@Z*nfw5G94-QI`;`lT0_7{;Ki`-Hj=@^jO* zY!_-nbFDU>_tkvfx4dDapQjGHCsrP3eE!AXP22_|oAUJaRR*gsuMoe!T=NYUWv5q1 z>g#Q;L&(SWXaw5*93J%DP-^n-K3ee`RKv<2)$3`#w~65VotCj63MU0^JG|O7>AzdfGGvs=e@4%y z%wlVR4%Dd@QZmj;X=A(+hZcpGbpG`Pbx#w!I{8H1{pn7%U7x!` zQfp%`RyH33G-N?$`|)14YxsT1C<-dlLfsqBb~JK!oiC)7MOC}~Qe`n`QvT`8mqu9a zJF^JlEE&H08woKn)=-$Cy?-lM65eBxL`iNA)pafJHuj(_^p8&ZHv zdf>m6`Pv%ZxAtVcxmoMY`sc!{(u%muP7RUn=9$ zh?8_WERucu_b<&o2Gj5%(YS>g06e}zDp*~mSdOq!@wt$_wD?8OEp@%EH@w{%D8GzghEgzu(kOBsDWsjC^d(t`&}Ctn2GYLS(LT}^wK zo+|q8v&L%+atgJ-S%)LPUf!$P18!9KjkTOO$~!&=ebS5Fr##X{dR=$*cPX+x(@7>0 z{Hd&`I zT^u^P7@*H!xJOt$X3Fr~e4=X>=In}pLbxnUqUO~k19R*-^rYn~P`T5VJKDAFbQxM+ z;TVO^;vsN>_4xfQKYY@0U-=*zsvXK6YQN0wyBcdY>M|>#HM3XK%d0RLBMDQpk47SV3-BK^XtP^n? zg2TRioMk`UDt;UGWvG7Fo9+@j!-2*@>gq$+76#qd&Gi0+dpDfZl2GNqRF<>q4rbpl zL&au_$add!*!~g{YqVDw2F|2Z9O@@cv&--yfAU5wM zKin!hm#}7EAW5)Xo8jGYYtfcFdcTWcmI3!Fbi~6S{(gQSP{U~xAi?4CGj^3cku0sI z1V{FrQMm_O&`O^}C6u0%(0;H$1*o7%Hmh{imJRaKTcrf*ZV0`mzkGkHdGu?!WQiQl zx)UkrG`!UKj!@_a+EBPVtH;41{LbbcT@C;K^;TQXgjap7TQ+p~8}y#-HeR<^3s`$i zZH~tneIr*arW~l?T5`lOa%a;!Wvxgg<|Vo_YeO^&SEHHTp^BH&H^tmMSkV3RH_Iq4 zg&zYN%Y6YmbDBz9gYy#=r_vc^XeWyN!$TM{9i!P$Jra8Tsdd&()lH}9W1~lBZ^DE~ zo(BZea$J$IIa_}C1fPe6nIG3pqM=RUF41{kZB=2O_x1K~8fbLjw{z~wa`S2|o45+m zlQor>gX50La&kA@2zHQLy6?MRM3K~1cYH9ku*qpu3r9yfX6LlF(P#1aEoMU(^1dxS zHl(!nvy71o9|ieS9OHA=oqiqKM!7tS=!{ai>ci!I5W|%RU93I6X^l)B8jbu|4Uqv@ zNn3dU?D!ZUnC!aCzZOcKM%rQhli~LGk+N_?U$VpbX*RFQeV&}vmzh%_HSH^oNE6`GOcEAmtZTK3#@d;W zI2qqcvYntmWSC(Pql6j8M8{MY6OAV`gqsP3$<>7xQt0-Lh1j>9Z3(%KWg4CJj_7qB z&wKcBd1@lPzWzU3*OJ?|l10-?5Hiw~Al>MpksT1uKvM#wGY-0nMh^po6uf{)@JtO& zyn-0c0vbp**F2wFlS++CW8RcA>7w%hH(KSlFU3$sZn3wmhd>y&K-H>14-9ulioRZwx0Dcg`bG zsS}XK0e!@sQf7ouq7cQQe*AqHd71%#)SK}115?Ox_EQ^a7&xmTmM-(g@l|qRM$^Q#lA54?Lf|S>f`R!vXEWsyH+5LzY5&l0bfr zxeUcuif2)HTABMw3(+QO{PAlw*!5gg1Bri9 z2dK{$_>Rao4k$7yUDKD!-4@V(Fq&DGNq&}EgTw;_ubCy{8DYa&9ku)({S83;N!^)B zLdUGQyNu-X+B?C+{5|{EXtzRs(@C{rW9hbM8Tnnf}*wf(vKv;sSpfAZH#yAN?(pO(0HQa>DEkCDRrgZTt^Z1Y~C zd{6I9nJW%C94c5g>dD}5&-T~uFSr=1b+=8QZapNpzE*vkvW{2KLrJ30T3g{yrTSjGg=(z^uU?8* zKm+~Gas%rgrFgu79k2~eftJTQtPbKFY^_xkSN*8jm{fJnYEQM^EJ^DSWVPVmC|NM=ZnH)GqZA4mujs@xXhS7Sk|y z353r6MLBAe&Kd4&;>CQoYD|EJwe0y6`j0UZK5ffKU^;x>(Ll-x001BWNklWcw|0oBR$=&L_ew-Tvcty;84^{k9~SRX4@!RblmT-q9;jz`TA_ysrbZN=3W~ zI8eF5p@&IDAosevMwh2mfff490tLRg$nm&zX|}vvnw25iiaQfZXOe50kKY-04$DMl z(_&l4{rGxNVt2(eaA%8^i7~F+bKyH*T;6L3D;mj#U&0ILkE_kM!?Rw$-FRql`)(A;9Af}mK%~D)!uA4}%6i6*+;v?H5(UazgFjG*DMpoDRkTq1 zt`J{C%%f7h;*Bf7dW}q4lTvwhv9sjoCmiVEy~s~0v~Fd0;w>>S!~3#-{Rx8$N_U8E z-v?7;MhB_Bmp&&C5Q(ygX1=K3ka44n{6$m`}13lehmv#i7bCUY)c~=^O@Cw_#*6{gz?a? z`;K!_GB9(S>;fV+I!_DAu;7e(@UFequxk2$waPPLAX+3lt5BPyeLD=FXqFhxv8oh# zmS>Sd;Q!b4A+dz@_v%<_?r~zK0W;_6W&fQ>zc4vVnj~Zn@bT$~10&8R37x>v!-QNw zU$Dgzu584RKuTMJKx&Y%*Kg3%IFuy|{&(fPZz8jlE438uCvTeQM!brq2uC1{p6O*R zwFu=%>9Xdo7@@Pe^f3=m>OlY2;LqPV@YI7VIvj&$m5rbT%FseHEpbPy%Nv(gXVEuN zvO{X|O{G+?4G2AS2oO84=3jY!luM?^hl~UBgDP|6WFkoB!WWSZ(a15R79=@<8oW&p zM+vp+Rl$673=tuG4$njR-5(szY~Hp@+lw0JV(?43f?ZJw-btCJbw&rsoj~AvSG?ug z*Z{7|kdk?CV*k{JLO+i?a597C4l7CXQ(QPp%o#>DV-jhwA^B#QdOZW3atrpwh)l4K zN^Zu>Pntkt`uv>M4i|eueLv4?mJu~^#Y{bqudEBl{aok_Q$AcWqz;Pvm`0-!j^WS8 zcIwwp;(>kO-{zKe=ok#Y;&@KkND8H#@2=E2YO@P!s-duKZ_D~aJ``1%omF_DJ8}Tm zDM2ClvD{95ncbkoPb@fd9}=EJ5W$(a$3wdR*;`Z|1%A_)mUKYOM1vJiM-ON8sv8r8 z6taf{XPVW213|FQ}t{anzLB*trAV4_Ia-@Qg=@^eG)GTgkSUc(y5|o$NZ)Cb$UTJqd{WN zuL*%54RaiO+D|o-h+mQyuTNl?=Hv9`H!Zgu_s%1PWHtix4;CC{M+>k)GekYZzz)3% zPVPc-Ddfj6V(~CcI+P-iFz!WjSlVq|0480_)A;!3WzJ$r9p*=z_ciJ&B5zCGXcV?! zsB7g&t~`}ecNRmb-{J-$TML*Z^F+m+lmiLW&Qv!_?{A@^>Z^l_X95zl6# zJjPY)KP$#lh(HG=R+sFoc??&9o+jgge)t=ekH~>%vzkuth&50tP>NqO%Nv*s4Op3L zn(?cYI;7>PFWp&FsfOsA(??fz^;Mc-dbx}A4xKEUQdFM@5-mAhyZ>4VD2!>rQe->s zJ@b-@m z-VR1?_bqv$_Gd0L1zEotF?!+T*?U{IH+*@Kb zhR&}-eOHLXOTBY$R_Ibuk7#e^uN1=Kmao`M5T>`pT{d^T8y>!+t?!l`)DGh#h-Q(z zt9yXVI@X>^M}1Vg${E8DOk{g?4bZk(a^9CezmW?Lxf4?)7-`w3mVFb+YH1`QjX(j| z07|ZP7WqKV!h26R@lzHJv2;Zq6jQ!?~+u z|IyPWl!-m0+c>6F9?9Lxaa!X3&*L|P^m>bvbrRR(ohtMZGt9U=AH*G6&-vl?2W$3$ ze&{_{*1a3q&N3;}m^Dt}(31yljMWLOOxCXp(Ct*Ga&fZ%Bnsmy8W|3n7kBP8@ z6*lV~QW~`L0s%MWtNhMRb!&vi^Lm$_FN7rv{C)eES75iAemKqZG+U{e-Ya%Nj}cfL z@rS3W>&*SYLBBtKBen){H{*|GO^3@>YgX}F2Q0<21~SW4I(h#}ZrXCLpQbb`_jD?S zpmo;R$;OnC*!|IAnsZ;gJSkxJA))0nJ8J%}1=Ki`+_cJMO$DBWCu7p4++L=^zYRrg z;0ZQ?cgOkPQnz!r4#8x4fB`RZe)LmsfvKxXP2e_g#Gf^1ANtS^mcbCexMUZ}FgH(s zUQ!oDd;=BXudSyub<~rp*{4`^i`TsbB5~u*df#9f(nT2UB@JP_8ci&;Jt0Xv?Ctn5 zYLKa2R=Sy%Bdu4-llQUs6fKbp^AN)2X@*5L)sT93#1BHv6sX7EabGFgKj?SNx;<2l9G^?E@@`xQr195TlXfiNYhD`oUPLGpSiPS7S|Ir zKGzJG&IpZ0Dvdyqx_duQ7XV33Qs`H#5+w!SQX7yCld~nk9#SWwz3eT53p?bZA}<}v z`-8F#-w0o+N%KqqJtq3Ms8Je)?2sw0&7_xCVB{s5C$&>!-V5>szR6)#mmAhRQ^>+6 zAs^3GebFm^!?F zXj2dCy#C>T*oxz^CTqj_CZHjCp3FU?;?4hAyMi3Ykt4{3J}`v#qAQ_lV{a1p0u%B< z*8+;V4@`34qk*Ox>ze_$20bS(bkPfTu=4;f<_X?UxgsK~NX_*6;8|f0+tPF&lBKN7 z$jAuf5yV~UkYlff2AJ7*HpM0}N{ip|EBAC6XMMS@NISzuf@kEJKFq@@pLa@d2+i4O z=|dvgQ(5NDYuemp8mwlgS$7j+`FN#R;X%8TPy$9hBC=9gXkHnMY5M?@U86y(r)Iy$ zf(X-=q-eOIBf6M3?7cDp;b8JX@xv#c_h2q*`WE5rpUz!A@8BVH!?Uy7Hc7Jf=3CJw zaqX1fgL!S~l@>BtGp24!1wCOK+oC<&+r9cGqd^)FOt5#_EOU1X`zG2iI1Y?Pu> z8!#n9t?l+;CVc?dQ7+!Nf)f+ErrHd*`|z(yqW$WQNaXWD5)n`j_6LI~Q{&oF|5JKz z(k}-gEJN)qYXqwi|$Q*-=gfhS9k#E&H6?VpF)SY3!TMUNVLDCv4CsPC}?Ex^}^{S44 zqOR+*yvwXfs}`b5C3GwIc)C)-hvhEu1%VIR@8V3G%NR4_AwY^ zUY9{|2_!bgFyc;GXsQV@vA_G}XCqOzLzj4Fu^Pk*Jfrbm&%?Je~S}N;s2}J{Hi+$5NC729G&eKz#`B<8}EffyrTc4+}nbgh=Gy24;chCP*%i+yaM0!>S(XPx7o$GuT}-3zb}m&e4N(x{-#MQYxlmddZFxFDSQgPX}#V#r172?W*>jg zN_jF;8BA}zR_Mgwb~fEG%VJwBYnV)w{f*aTZr(ckfBXEL`Fyqq$fcDkVIIefaYI7xlI;Ix%m`%@{6Oy)9&HIFx!Cm4Yeewg2@0K#F z)b&g$n~8<~6q*hy6>0Int29*L`<`{b7ch4AGBoZf!N&w&xzhzqKIV`G*NH+-jypIb z*Vok1c9};LQZ3VJCX2r6O#UiK1L<*`r9IiFNfyz8b9!8$O%d8JGV;F9ty8&_j64FZ zJ>HBZmTMXQyBPNMu2{ZSF~vhrcylY`2dk1yG6=}SIHlw& zD)n*Xvt9%Uj{_ zOjS*rZ&nb)e$KolD__XhZfBdtLFHm+B|de|^3bZ6>L31KKJWXx5#Nor+q@y0@WXXt zdt@?irLs-T>$jL?iu+f+LUK8l(;NJ>$DhG3{^T&{W*y#e^vzom%t)65f1JrVeU;vN!gUxm5$}?<`RncN8YVL7(kwRKXGlaGe(mgW^hUl*V_?N-H?k>4B+>3gt3t+R_4?xry_T%!zE<{)93dR9gvuV3-S zFac+$J*Sv3Iy0s~YLCt27+n4Xc>!61!(x+lm8+8NVz1F3?o<_`;9TQWw`Z{oC_~J6 zJ5nuUU``jqD7!xSFvj!#r%#_R{Q{aCk}spJtdXQ70Ae^VB>c`MwgrFyLr07IdY!{A zvDyi4K`GPxRM`lY>3y;ya*BB*Uc~iRVUI~Y-l=t+(oXybD;#`g5^(Vd%=~4JdqW!V z_F&sh2U^{rAKGS+tbKZvGl=I}l%oKLuG(!@CgV*>32mxKojJSjPP_$DNUGLqFz5s?S@4#z@1dFP5~8 zL}}l^9E&AQ4DjthEPh&?_bFy}T$^8InH2Z+YWL-vjkB^`H9Qd-v(Vlq$dY2_vuJi! z2Wnp)Z8YLhCVG~1-b1J(%ud8i5u68tO&qAiXZWu?ru8+6-Ae~8`O$Oe(R;26s?Tz! zD&$Wi<9>R1rFGJtdu3*>?-adixbq|BL4&CxJAEcXS88}h^QSe3R&y5!NAK^$PY)a4@-426f54EGIHnz!?cNL zIXuPcgL|;;kDo`8Ux&+L{5LR{lj4M8$eb{l;vsnBB~+}7VqtcHxG#lfrYz}mq{GLJ z;$u^pwB2;xH)yen-+k@NSDwdef1P$K;s{rqJ@`7upf$(!_fx&OY79u;fi@;pW1dDO zZ@~eeZsV3@tsk@ih0e&Cpf>3pSRBKJ+P>Yg_5?rPd@#A3;Cg#*Gm{MVubT6v74P1J z5Qd(cX9)L?pPySUg}nQyY~7i-hmJl+V3dQ?!U&&G(g~scLf0=;(nE32BUnr?XmT6N zMeS&BOvMn0*;KCnSKL>xezw|__=dy^XJgBhP3X3VX}4b&-(5Li-BL^y##+2Sw^b0; zfNn#$bK}>fXWS)itC}(xh(;{Aac4NHQ^Sc8i7f{kY_S|g&10f6Bv|?@gab59RRM#y zTVeT-@x#>$Uc%GIkwk>}Kj+yzDzW2x5))eU`D8oQ`S{PBNgeC)kmVO2z&PH|`3yg| z*&Z_dCSmeocOc!wQ@<`=&+PVk{WB|Z>Us|q^LVObzB$JBszzTMPkB6z5)oz_+S#sw z$#GPsAHl%|@l5+tR4pxwRr(3zqJ@G{$-Lq&{=BGsy~W*0^C_)s;@o4( zG-A8w+{I@a&+EI(na{FgIWtHF+J=IOP&2}Qx=OVY|5Cb}(e{q#vG^+LH{vj9oSI3& zi2;vh_D%6Euh?0|zeFjfY0U??`aYIW+_=fi)vX>(UQDR$eTu_Zc3ur*PCYH+ZXS$k@%6kBUUDOAG?n=-7RO364X z@arLkb;?roR0*L1+Fji9wQ9gR7dsXUlw}gto4zgXvHo1+(BDvuu9Sn;H3H9}h-d}J zYl99~Qj_=AD`{f1oxLfX*>7_WK`awn5oDZZC(7-Bm?drQ(?hT+7eQoWp?U2f z7)taYN7q!NXv6_rM{%bxTo-1!`k^-^Smry(u*AyKF*_~ej*3N#OGzkln&xE>i+>$k zt8a}vveb8*1-P>+k!zYz9WrJ0aHG#6sH~xy1rAO1s!#foI_#1V!uLbSmz9pDjkx87 zYH}0uS5$e_`BX=$eI7>6R~YxVtWvEjFhP2!5naY82gz^C4xmHahl_A}%?>+#`QQx} zuj9|7Yv29ytp0AvOEog8L}-%~vkv=|FoZV%2g+UX&94>yW}VSAVmS`olVofO(VJR9 zFrsQmq%w*G=eWzF!bmpImaz?35evMXai(>**tSmR_aRBJ3J)BqX6D%sv zSLuFeCf>1GBbzuDm?Q09HJCMI&1?o^$Ui>1_QQXkWttrOru)F(L=#(DtmI5H0UW5y z`VR0%1_GWns7?j21 z>C)2s_TKY`uvREht`fv@W?y4roL;xVYQ{Z=CN4cWq5o2xdh z>Plk5&L^7$IR81l2S%8b%XFd{Q}KtHU#wU{&|`rJZ!Rij0a#FFNu0-N97-3uU_M6e zY!s*&VQ-};&Tp$NK~^$mztBFN-|9<-2U+1-2&b1{lj7O^c~ATAWe)f>e}21ZpjZ4s zfnR+M>}<;$Mk1B=xl!Jj$j+}151o9ycW6$_%;MjKDxm<@LF*7+y!(~KR|MzJzFElC+_mX zFIYkTgVoQuG9t2?BMYmAEe!{YmF6iayO@<384=0h9hdaY9TlFQ%J+)-*US7;`TC@nyiE5&%JrtPWYfme#X*8tUhe&9*hs2`~3{mbFf zcYm92X3Nq--H$d8A!RH-^9;v>@;OUdO_I5T z%KqAKK79gy1U~S5BBe@KGj|a;H>=pMMmktEKRWKEjt79#mj7Y3U$@AlYdD*r?P?W> zA)%NaSgT9ZGGnJEtdc`^HPT*Hkiu+GGN<^l|)&zRRpVlt_YvZ zaeWQ)9#ah+csmUBJAgu__{MimH5_zY7Lr2Sr}GX&h}ClTgHLzBO_n1txxWeRK)FPHGy@fL8$fI=dnb|;1_u}HRbc=5-i2YfFj?g0k!oF> zQEqXL(#Sli`n9=|%->Z-X_fnr4tsNRKCV_bhFRV=H?P*4llzKsat*6&W_=5}0c3I> z<4dAk46NOa9|B)n&A58mKyx`1iP}QoTY9jRpqDg*_M3it{8^R|aUJ}ADI?D-p+c@VI^ zNZfs7ayNBS&JgzBEcS_hs~twO*=d!fR%tt99oWm6$DFI@qA|P!t!_1ff}t?+HN?UD zO`~~4^z($y>|_EhFrHneb4-al>l`$ok`j(VYcfYpPbxVRb6#7(j;ueBI2H2aJ~e0V z8FuGc?bpV0a46Uyo4Xf@`xg`2<$3MvDBLb6?!(#zuo;wjE7NHN^zdZ;{C@BnCdl0! zUj)g0;y(2#DNaDMs@YPhK0z5NHK@f2_iE;W-Hu+rTf9{(g3S#S?C>P7zdS8{L80p_ z*|V>69H`21t4J^$=7}Z5EtENQ-nT~o z@wd`9Z4viYJhG@}2~v+_zGhItD*UjcYkBei}rJ*UykmHV<>ZTo_rtVaWX$oX$CW=^Y?)u|ChXTiWh{A zPH9_9=~<>@EC-XZ@_y7F58cKnV{mmQ6*9Q}Jm)8(I2L$_1owh4kv)QKy6L}MXhFt8 zivIHe&OAO1`2xLBdlk7_mhV~xI=~)XSbsy2Dl{G(GR;X7)3gu2-mX?x348OGS9D&o z^DaAyR8lb<$r|}F#Amywr82&WC|Ye6dR(Cldp_#Ge7#yloI>f=1Ord z8UB0*5m+86R=qG9t~`L1aQ4c?XrkzfKotYAvi0+Bg1saSW)HG4tq>i>?_s@dD4KmT z{_FEUeL6Z_m3CrrYJ0j4BYSMkXp8n|ak8*9%wa#ujfjfcQQ&>~<_7Vd#KFgB3Sn3( zoi;x;S9>efWM_2hmd-VXhM^FQ&L?pGH3^k4eSo%}8NLL6-Km%~F&LoUsvSwP>_b!5 z;a;_nB7Nnbf8R-zd7)FYm_O|4Okpy7Xza`LPm9MVBKOdI3qN>#I;807hb1m~fXMGo zK)nz`UM!C=GlDC|y;-eZ8GEUfrvw#HN)SoLwrE;X2NSY`Q}-e_p(X6l0iy|9*6mL1 z2UYi&IVXN?sWPa4%2cpQDwsv$=2p_!b1jj<6n$ME0zvFMdRf>v?%bgGa4=Rum6VVH z2yIWprSZ?gUNa4q+SiSHIr3efLS3kcI8y%_lPVjuocQSC{l3yGxt!a8g*C9A(JlP* zc8BUy0v@S%sN}?zshPJ%O+=9sISgj}mNLEmMSjR5i~s;207*naRCXdvci2J4S<0O^ z+%;u?l0EAFu&=&n<%=KQVGP)O#c|;IHsQ_sIz{BgJj5;eI}nCX03#vmZk_Z2CesLS zw+;hB^O7i)44S5}UH}0`GmpY&r@5fUeHxsH4h$*Zs$SPa<%vMz%HvEA(NJ4c`{5>q z-|qUirSpnf1~YQPH{{-zQqrF_Va(mE?M; zj@EJX5TcPSRmh^#fJtK`rW~Za-&cenaRH-$wKj-MtB&hs>Ldhhpw=RGdbVb^1{iUf zna9VSiOl`hcjZGZa>^42T5R<@1H5t9)A9mXPjcbY=E`xuxiQf~iz?m_mr5vb50zNe zm-zSZ1GJljfsSZ)!C>w-9s7{(hh1?j` zzx{m|;TRevA?GwJ2R+9U_XXxHQ-0r20k%H#e@8mcmbjm8uYBHb=B#C~1UIpHGR`)v z<1ue)2?eu}A~f zzJ>x8EPBkCTJ0V(!~T&bC{{eau6i@F#Y|sC_bdZqnDS}w8IvG~TrEGDbih+}o{Z#` z)>x?)vZtJCHIx^Rw2U(#C-r6pm7HzK+*Tg`Vq5-Nshs!O@e3CjQ+v#2XT|+Ee~Gx? z{V_}k0P?z~p)6?eJ)qZr?+#%WpmgiP)? zc?fB8u|Y*b#30s%T@diVa4Tbk6=c%tww2?vxMMu5;i0IT&G9VEU1iM70=}88R`d0_ z`>U-kdx^N;d<&O^9Lgw4cvDR9Rt5)Oj?97>eDt+rx%pXJtMg~t@iCjYJ+Oc9|IU29F`{YCPZ1W8hf-nfPqxRWBvsLO=_1IJz|H8hoR3y%40 zwOkr8eRa3o%wGNd?mH6m{*UwC%*{op9Q4;+ze8$o@3R#&R=!X=9O+6!STe=B&@YNg z%;9VfY+Wl-1uTGj8Ka}Z8V3^PY&)}DO6`QhMX>5Ec_F)l?~DD6c#*vhMoC7+83P@& z^0P7t*ja4O7qA%4`HhY9jiG*A&42wGkMV~T>EHN6X4va`KcsbhErUc9gR!6Z*de(K z<<#3-b(m}BvBzR@?~pTSXJewZ{{4R72e4b0^^bB$=s)aBdRU7(Z#oA1DD?PjklEKJ zJ?kXW3BUdMW}|`VLkT<1d&Pg(M=~Hg2ZKNKwv#(6Pwd;z?@X{J%>vh6P@Oz% z2W0ojNnMth(U)h2dd@lP8q^T;ykAT^ZZBT+CG;->%-rGao0=#s&oy1t`4q6e1#z#J zYUipaIK}6>JDMgb$@7jof%y3@^=64XCEeEO2-J^Jn|B{S?Ks};LIuGTQrd^&B@pU8 zLc^RCd?mGb_=fL{m=GGkmYWOX-{bijW7NCVpNKmwRo1PU;UxQoaWBuHPg4=HC1b<5 zs^EgPV(~HOPZ|X`YSn>%u;qH(-<_jpD1;t6NK3tW2}F=d2JH>Xq^K8w#~t`tW!k5p zml-uqJJg#tZf^wqp3H|}c6)`()2t)@#1*pCO0+n1iK0Jjgz}v%w*E4Yp6m^H;r0sQ zG&qqmUi}YmSI^_dkwhuXACOK;ls39~P&Nc3hi>!+OdA?1UtqYxg$L{h?ATsGiln0h z{Q?>O0TCuuhO)hT%FJSGG#8&rISG|7qo-*cLW?peuoNq)cAG%M%DsnWTH`^U+bPFB5+5tQ+2_2qrFX0}a||ruX>qWqRJW|NmmK zX_g0ltjxHI#DBORYGg5Kk(8@mXtYXCl0dyJi8HZJPZ|;ls~Xd6NkpP|HB_cyqn@JK z^t5RGy$VDZI+bC`EZ5P~LOOv!e^)ee*1V>LtcK#fwh(j~-f{%8{39FM(yVu?%9RJn4@ptA{^%jx&f`6tyB)|>0*0!9H!mP z5j%|1@e-Cq0?|lSLy`dqNwjz=N~4ZKl8HY1k}q#9)}2XULrW=mr4owGhUGl6A3e!dvue)eK!cUgL9 zUnW?ASIgqas725;;923F2``CSlgw^O+~;ziokDT#E^MaI6-JH{JvgAifkC6q4{;Y( z6k{&=hr(w{7Gu-4whbOIHDVv)A=Hg0@9KsvGgWfAba^JqrXOEktlGu1bEo$c*Htz= zEQ@>k;mEy*OhT#kT;UN!(2_{lLW*^%5^u`YcO;xl?-r;<==Fu(w+^B6$^mCV0?%G8 zT$FAw?)Pk7Fr>l?xz*k;7lj<9No6+^yy@e!_`T?noc+e`C~T(M@cuL6o+H$r1)k~X z5lyBSJI1KIR8bcm;y#p`X~fJ>f4E?7>Eur;TsU;4L!4wdnKJ2e;%b%QZ+d|U==W#&ohr}J9=B2fO|~iMeX2+iNshO{r=(9x5f9BOq}x$KtK*&5L{Zu*M#nl` z$J!WoY^uct)fHKuJ8la`r~K^vb=juvA{$zRHLv?q0|LeJJX?GwzM5RxiI_cU8=+VO<9O>=59!w5Q)kMAf?y8JH zKm`o=%(n|Pw|A+IIOv&>E>`_ADF4x}1sWEyjE>9azP-tIbLiCd!8jj?`_scQl4H@Z zc4rmY9(#kh_$-V9U(VG!IAwlgE=g%FQp@@I`)hHeh=`9GDxiXN+LKo1IjDl9Yf?!#vj6HFAuyaIe~D)Rmg&`Ip_KQz z6i1eX=-TU(JqqP5XXi&{_Qkht+vbp0KYab-Z&&>)(Hm!)eCtTPn%`Yt-3X);%sr>7 z#DlBbEJYVL`C`L$SYIkXgeyyHMioX^bFbisb@JNHTA`CUyqU*?VR&V97emuFaa5i? zf5a@_?gRmv-IaTDP<}_$n+Lbt^Gn(st34FB@qSwNxmE1eAHHBFglgN#yB%M-tLQhv zk|u9>Bpg>KM==LP5LaLa8UaK_xSZlPMyJAhZLWU%k}Kx&jbN(QyO(w)5OWUWEv5`P zJ7=Ak^L_HGM9u-NrH4+GZuW)8sx@d(%NDp{f`;ZJ3Vc6pnxe{Sm?Fho+!j(5_(3=b`VUJ$nvE%c4EYkN8rFiYRmIQDCc7iMqc$^Yg5JOaOa-L7H8bg zc7d&N9#v6~5B$Rv)@;?^Pm(;1h=y>-XlE$;S$!T{g0Gw(Ym9=F+t_iJ)q0wX5sj3? z#-~u6ddH_Gt4fGs1KzHiOh=BE8PQga?1p|~-hOThK~v)191RfcI60aZ7I)dzwgkQ$ zfMD`+#v6STNPT|nvz$@y##@bq%chcpFvl|mSjxC1^bu20m6H{h3shE@;Wy+tXV9pZF?j*v%{?D#kk**N?6=5REbSzgc+%DY+%ATMHK2gA`Tj-Pe1&A zU2uH{zn%y$G)!mo1m2`(_6J$7Q$XvHCk5&fPPfDQT_0VAIJh$fy+n06=9%_*fS}pI zV)E&$FWmT{Eyte-v&E>FM*1-L2{@Q-C2+E)Uxv8Hx?A$(v&Ko>WpOV?J|H_&!`GG8 zDj8~XcNu7|EM?LB*B-j+#dh;V?4|uP`pa@3{(Ja---(}*J+>-2o*N&5542|it53>F zr#~*aq7?cb6US2j$j1KV{eOB3ODytQYegm_oxMQG4CG~-ko<_UTijo5=eO_wDaEE9 zEc0Q%XJ=#mr^UVb25r5ZrOPV6xAlH+4&CSNPHxk8ll?A`fz<4YQ{3VewZ#K~!d>Do z={QWUgsg4%3cOt0eaSITfgT^OdMpE+)JS3oP<#r-&SL1a(lmR~yX&=6NyX^k3O=^f zC&m36?CGXNzgc|MG#yd4?tICjYMgX0CloY7kN>o}Ty167OUcNR2gDoOoa5BJ!7#&t z(1*<>eKM=%aPIB~op1`hD@ea~tnz($gS(s8DUMf55_F+Ug;%jW3Y1v12koT&4xq4+ z$hW%!)jnuer@wh%j@O6eA#nL*TlTvo6CmYUy8HC^-+o$E*6Q$cO=${O0!D)|E~tJk zi1|z!@4KVgHNL&}qo5o~A>*0g-H>sv?q8=W!XlzRyht7qkF4guc2hoOzqhT8Y3#@Y zB}`&P+5A<0(t!v~N*Lt#)>X>JMyKg7e*Evh5qF$vT$q$9*o=*n_hO8@?lEAW=I?Ic z5mlX}c!Axpgr4A<6f324Pw^_JA?}fE1SNUbHUDOyWp z4C}>mG{UtSKGX{GZ>6|dZ(QPY!t+C(1RqGxmxDFBst>m!HyrdyPgF^bI67oi!}@SU!+YtaOQeuE-(BrWrxIs$JObt?!%Nzw+mKrnLiNc(j%eYo{ke=VVnnGpIxt z|FlipQeb*|aS^4oYgi8~Co=4boIWAdo9(wD%UX!yT`Rbt&%8F2`kbw+{X8f?Jkf(n z0ca;5o+^&o(RoH^@Ww<_Rpib1tvPAtxZzzD9<1fVw_2b=Crls#2LxOdm)1+^k*n3F z!e`M&(=3SZ3xu2zs+&1b@f*dCe;J{$(;vkFaE&z`;x!|yr#od3H34{fqkcV`_?Ohc2- zuJWdgxh4MM0!)So@uo?Qomhc_+C0+yPcrI<%aS6SlTHH&W)RBi|-CR@)W|T3*i)E_`alil@`()x9 zx?B{`fCR}%e%{`&2SFHE*^a>I+Fd@dB87K8eH31$s8_+5UIFH=tHm}l#QWsDlKS#G zoB=IoLsD2ME@8HOe66wLG<=Wncg320e}D5;O)}IY#KvY?fKLt7S2y3WXI?#&Al%$D zN>tY&Hw+9ZGi-nZDMRr?v8MGueE`sFsFnIPq&Fg_%%f7vimn|Bn%=Xj0nEKGnm1Rv z80Ogqn|jmjId#Hb(=%ph`&#hVEzs98)!f4S%x7enmd0H_+fDWvOhl4V!&{d5XcOfj zI^c#OG86bwDWBfHeY_RoH=*Y7fl~9`EsrnL?kp=wXA8`n8JjX;*xxF8H0=UOHH#+Fi{SUDFhDky|WZidxi=tVf zN-QQBIGD=}GnmPYdS5mdX0D1{Uy;|2ek3W|`-Fk#J0o+^XGo zVnCOW9=Jk*h$@}?yRSY`Y@H=~XOK*tVt=S_=Hl#DG*f3HJpRDzZ;E1PLfP81ng(fv zdwu)qK`aB3&Y}TlA|mDq?LNKX>(gg!fGx*9gMpBoXs3W>WnDGDa4@UYxC_0$R()x1 zpj9Hwbi#sfg2uC|cp94mU$8*?65_+v*%#zSh?*`1g~OtxfiEk5-n-F8*zW0`D?rGw zAs*_=B_|*`~-NCYU@3`8ZkNNEsfhHr;>OAu!YT3Oa(kq zK9z2`?hZes9_&Q@Wdn!Z8XC^=cZkd(yrwu@*kDP^m1esq|A$U5-|b8#U>hst^JIi0 zb=B^dliit@>M5K`fI6{i2#bZr_Q6d!r9#B|()@pb_(bqA&4`cdyfoA0mAjuVA8a9B zS_OZ)dK<&J1&~=TbrQcc`n2s42Q}!`!Nbm*1 z6(Y+KL$zC5mcf%=&L`5Fuv|4@_CKsCSSBXvlT}&YQg}tyQdxf zy`;`$e57M5><$(gi0?5}ykD@5;Hl;hAdyXAc~!!hg6nAb-ZU97FE`7IDVN6HGXyXJ z5Xs!fDE9XpfskF#BnfA8z!ZG{yw9d4n7%ucC*-O^RG*&t^yOYCT_irxG#*)FcaL&v z`QSJc`%{U^Q4Zht$D9f2-(6gkVW3~-GGN}G5eILg1j$fW28_T}6Z0H$#cj>={ZO*^ zNLqfBwEa;FtDipGP=b1}jTlDaUami=wh0tZzy9YRc)oRlkDlh~XI7=FMrf!^s(R8N zs$8Gji?=yqydeeQ{)$!ZLL*3e|19i?beK^Voi)n=z9$mA#BQgKGi}(p3W_P6*n@bP zi{cEHMvoNV^H{4zO{v|P3h%@C^T&H?pwr`i`SSN{I0U;x%wQ2^t-r^a!$UA!;(J)- z?lHdTO*lc&e22I?7VwGk(;t8CEH$r5tOm>n<9oueOD#eDS%qBkAx!vBl@L+hN!jjZ z#C7W_32D3?&+Ky5hK8bccR3pQoNcZQ*~YnMIz6re&QXh)%&zuV$!bMmDITFm9{*UK z>Z#s)r!x-oU;a1QotQ3_iR*Zz1=`r)Ee)ME)}RQ34{p89C<$+ zF2dY7@Qt+TyNT^Z>736L+u+sTt2-m2AsO8^Wh0`wetz=zq){NtmUef>o#)VbjZqz` zMu41B^>?&~$o39)muv;`t`SLD|2sXdw&EDT2IUUza#;;91~YYJM?AfoZ(|2Q1{X>! zDR+X`)&3ci-t$i%{-#yJgcI=t^%won&bn%JSR_6Vm>-J?lc^iNvP?A_9!SslZO2M( z|2o=hLuyLx`YfJ(>rStG#9$3H8}N3hV|`r5*JE=+68mSflwnRz?Jm9AZmHub2&f~GLBgr^uO${j4;F~B5nO5I56&O4Q z^;%h3Uj?6`NJBqoiFJ8kFCL8$p($d8V`|;6Iedb{TO%-%_JL<{;P1#=CZpd>_AV1p zk0dNZx})f;pB@T0xZ2$|%l7GB?!ZHbLUe^1m0d`H3GY2UViC!;+U8M9Fz8T8w!=%f{p482_|%`kq0!r^qo#b{l{ zp;5xtDfZ#rd;}ynYcQDIaqFWFi0rht1DCPE`nZ*-!>M|vvjujxL~L^WTOGNIWg00p z+W``9cs0XgKQ*w%xn*sCrnSB5dsq28`{oSaXO(yM*kk)PuyS^g{`}J*SL4g>nNr;K z`NPPoS*mhrX*=dnX+2xotiSl%rU1~*FinI>$pSROD%2n03NEUWC@2K(%%K z1ZMcXF5Of8U7vAvrOZ97+b=JxtqV_Ye`yK>f0bgIFpCio;s?z_ku>GBON-{G>D_m? zP1l+A<=C|@br=f^TaV9DPj>P#%$mi82UbN^*gaa>1bqg2SO{%-s8XIIBXqAL4lnw+ zKPESxiSSK-YN7!~s{{R3W07*naR82A2{jp1r4^!Y{o+=gp$HaX=K4Vgw z)6?qjNoi8P{`6Uz)_XiX@qA|k{fr9h*t=SMzkALKP=}2c4|17l@!sk+T}Nxa-v*j- zu6ium;7z6)led*2!2y*dxxaqY!;e#{tGRs9Chpnpc}{!^q#apM)x?t2M0Kve{OW2}45E7j250!1vy zVU&u#RFb32P}pc-oqdzNbKQv#|TFt9@nJYqTyZq?(ha zu2xWZxjG5xFZV+-{HSXFPTSrhw!XG%l4B_26=BUVAI zKcs=3?*F~s)jPCIW{ChrK)S!R-7qpesxlX6JGTB@k42%bM8BnUsr)j#G_Q}p{O9uk zF>Po4zPhqQ^QB$a?M<$j-f;KfW(~gg^!H%;OsrXtm%3*{`TcHyS{r{c{w=)RG)JYr zDEAc@y)3~U!dHhKFwDp=TbnCs#nE}OIF}$ZAi~FsmojXHhJ5+yVMtTH`*A1U6}B8! zk-VFR!kO=;%f}UVuT{R@Wnk}LGJp32AlwAd6kaXt1rHde1IJc#Kbg}9v=)?_rj}vp zZORwPa!P~m*-kw<(3tVJce@7QkzZ+~=KRt}&;G~mMB~3oy zld4#s9#=^rEpdX2dv}qaGz&GsYIM9p;r3NMIMFAraD=je*X$8_cDT=f zZ|fp7iccWeH>>Z2sNIpKYlX@!@?d@B$0W4u2h{pW1e|>wy z`{KsrlafuEPrFL6@y~c9tV)L!5^2}W3=vsF8CMlwmr{CD-imCS;U3+TyD>gU22anc zj&a%b&aOw1mX=-2I$b%}##1uvN`nl^53R#(Tb@A}KeQRkD@CX?+wvT3Orck@D&D!f@=<+9cDG1|U*=uEDP_r-iQeOj zAZ=38AyCUhzifxT4Q!{X#pI9I10_i~kYtZ!)}XPdID!AA?lvRX1O5(Z4}$bT{M=%@ zIK775hDK*W9@CcacgIgV<~Zx_PHH?o3}L6~H}~g+iexT0Gc#tVxtC=2la>D}d0-Te zjWaA7J7z6rdCCQ01vS5^%!;j1NC{1BX5UK(R(T(yabDiu9pHw*o+e|mfSO!)PXzmv(u-&vvBoO`GNQQ8e1!$1jINNOE9uIp$PbfPk>7?EcH|KR(10sIeunL2K33q_LHuEmiSnni{^9xM-}p zYWRXPP8Cvjr}1t}f63RkLrfoj{=C=Tgk%@E?=aKTfs?(t=N>I@pJ!nYsSic(KwI}o zoq?X~5|3v#L7_!Z{Zus1OKk`WJiYw=_rqhnm`2o^PliDPXq4e|c7akBr z;2v8WG%dS&we!nQe~#?bT2E1B#2_EjQT>#)@QE$Se0|$%w>s5}!L@5n^_KL3S-v+b zo7^AFbLJZ0B0uA=JG_chnF(e#*vpeXJ+Q>GE55b|2UW~Fp%Cnji3V1Ubn_3Gz5u+8 zi_ZI;p7tuDp-@TW!9H=;_n*Vp5*Ha5H>Y0PzuQ3nx8>BskmO739Z> zJ%lsP`a857$iq#(Vo%UFWzwM9ZOQ9hy&BFGuulBFt+u_x?%F#pnc_-{mx%OYrqmDa zR`M1AMKm-*wGJ=L;GBKlHCiTuML-@;CQhInbEU$>>?ti)LM#A>KLblQIk4WOFFKOf z3I7`a!=VwmA=Ji)YwKugs^gtp29!nKY!2%;O6YVl6yJ9O{C7Lnr_RgEerXL?PPuvf zEW_Wk5|=RGzE!5k2Bl|Za74+kxNgs(drH;c_cnWsGWC{(>tws9hj7MW6$*E^gCyu; z_hA@LcVsL4cugo}vR#b05-7dEM&nai&l{VH}|Nbxzd;Inya5xd!!D1LSJanr&vD zq$$5|!WIQA9Y;jv#ithgOTcv8K5|g!xMI%e!M3)?lm`Z#q&(Ff%-Ur=!Y!{mB%G`Z z5-R`PLVn-O9^9SkU^k6pVp>;(7=Oj|ZeExjX8CERmjcl2^!&BHO_!75XXyL4X~$~T zkAHAe2CigKIp8>B%_I3xndYGijt+AiW}QYten!2vN6RDPY|e`6lYaefT^ z>|HmO+rxGrw~bbY!THx*?o{HgU(S5m<*JlZc>5gXobC;)Ugctr$2@|LIEiZ>uXfW- zdtRH|M)W%b+3IuJ?)GNy3Oe2V=GUIsY9FrawmgJ@WH8RV+yO{Jk(3xIEUS`?{Sk7j z%jZ09Lf9^AfFDdC9OJkdlb((EIU@`iK5|_pL7Q1;LVNzP_vPV2Ln6XsSG!I(1} z3==%K&Q4CFrmwmDnSIOtqz^6v1F*$cSTg5Y&gsYrqvUPWX5!Xq5;;H?LnXFL>jp;a zxX`<6#4UbJF100$0nfi>XwMs8>IK{mAUZgL%r`1=!n5%7CZ>Rd6upS=?&7CCfCjxL z&Sz?tB9P;IjhHmM-JsF5^6D~L+VcIy+&&!C{5u}*Blg<@l)@?66m2_{t>RS5F z0Pljb1iCGv31475ujGuv2PR*G>bc!%qCa#hOZ+cRWb#+Vt1V7UG=q@1p3jUbIWO8? zij@Xqi)u9_88%q07)9zL`3zQenGJz%EQVk6O3zs@#xDp|fGK9qOgY#pLb2I#fwDof zcqhJ#v`FSWf)?|>`EeI0tIajGIsgJ}7`(Y5028krLi-3Pu)`s^;i_oZ*SPJ%m}bdf zU`e8OXMj#ZMuTlU(PocQ;XqXM`V_|vu#7s|YIRG9~!6yo3IJtp_%$Iz7wpq8J68w!5 zcz;hNuivySnLCY|Qa(q%mOlLRYtzcrx}Q@O7>RWP&Eqw$<_lXe-8hbXBAnnjRIr@S z;It!Z{oN}qZ~pQv1vdnlhwOTqrqK43H9hZUu;=ph4&#Vu8zho5w@&|v z<=1wHQk2uq9CGqI{_afCKGbnX5HorJSP9|XnKeDStlTNm5270go01KC)l)V(<+L%Z zaTj50;BbS#A+XZ(%vRcs!d9nWk|-&n#8c!sYNI5y7yvj%_0NJ->&2fJ;drD0Y{Q(+wG9XkpGZe|PdM0?kR3L#+Ed?c7tVQZZ#PZ6Jp1q?08Y2Ayd& zb(ctQZc-PteFsxs8RJtcBgxFjW4NfNiqqf$`!=PWOeKhNqvYQIy2b>x&hWIQ%L7!` zR~oYsLYNU|T8MtVCVH!FH*Y2FZ1_!3zbAipnqPJ)pjWA#YtjM2nPPMDci7hk$}oj< z{_g4@$6ci*`|kM2tRcHCr}Bg*Xy-*R@7dz8h?sH|&5hE zlbJCg#306HZO#|XZCIw@gYEnE?32OlzMwJZ6tNE-=JZmSA*26 za!cl=0t8-~;KtPY5t+=AqVzWr;?}jg`woFLfr??EM;5vI_ftI$v+I@u1xFO4J3yqR z&kK)`$?wm-lW?#C=Yi)Oea$dDLyW72_o2#Abw|q3>LmN7jz(1pV>TPQp*judn)?J) zR$Z@9?nLnS>QtRP03>RYV-!ds`j}yQe-N} zq2O555KC z<9G5mNNH+hz`IW0%}8KSu&m^f5^EC~Ja03{)l@~0F@Zmf%x;wgJ=`qbDWJQdYHHzI z713(Rh@@z`(2u3;o_=P!cymNmJ@8!b@pG%#@Z#=uJ+Lg5^fgiWKXccvE6H&~Yr!Ab zMl0!baaX`*Y*eIB7o%WOLALb?jtw|*ZrEvSC+Q!s0{^6o&tmm-_qLbm2YNv4Sx@V`8u0+D&K!pIA>92y66RX z7C6FagZPz4%`VZNz9ZqM-y|8(+`wufe7kB+wc;{Z^KpV3BV)eynQ%j}W}TLd;=zheUw~1}|`7AMq05=szKK;zS zk4z`B*&mWkBX=43aQ*tPU*y7;Uzd}beO6X~&EJ#tgIcs?k5|WZh=48_H;g93Z;1cyzG+F!5<-x1dT(cN2lB1GiPxJfdABT%G zE2qn!|IQGe?ms5O9_=AP+8TJCfBMJozs%9_3@%Tcsa`bX+yF^B5dcl@Zsb_&@7nkq zn=imG)@pVNGz23vq|h|4ZBUlwULP+Z)pTTMJ*&Q|TM?MlQR0$$z7Zt+FijrZ*v{@W-|L!F0x@3^6B((1G-kZK>;#Z_Or)aLJ(>{@h_G7(;<-$~>D)vP-*<9?pjsETr#os)V4VpJ zQ5)71RmgB%l#~L6Hgt5F-V7!8|1gu?OIAetqWKE!x|#blsOVjO%x72ez)-H$Pikuk z>9ZJL?XGw2W-p%gZ|T3JE3}X`U$tgbR06A^AhixYcC$DDan_vxg=*niwM~(c@YP)A z?JG9-_7GTXHV(mlvd5kK5_x_RY9YXDsT)F%ZUa>n9!jqisbGTcJ z=iBcwnA-S6+3ObqB^J0)o=C|(`#Lv_F$&aZPi7yBYn^7XJ(<1F81tptd;sy941s%3 zs$W$>T7QrK`-jhGhOV`duV>B~VR-+Viw|^a_mk1I#pypjX?IfQ_IPrcFZIh=$ui*) zwwr#{ak-2IJ}m&TnwC`>%uEamQ3C0@F7S^JOoyM}NCombP1MZqwnBrS9{GXoJjgX3~CJO32Zr0!mU zCI&Bu6gw&TJvh(Ji%zJ;kE)P#0b}s4&XnxMDYCnC_0D!6pL`8h{$9&kv-tZ?zAEla z%?f?UTA(?mhDL0RBh>^SBFWf~ToYi%yAw7aS6N0#skue?3h6qV&RN_*mfyW5`Y(}) z?5+X+-1Yd%o6)fm>@o-BC=5+Cf7&C)3MdL;2E%a=gYj6YEiq8@ze;!~e=j+pMVYh` zxiD2#35ytXg>+-yjWb{g6Ws1I+_XCvj48m=7<`vsdWb(L|I78->g@i-`LuekV(qm9 z&Mxv*2NSm4Ojd{nM1Yng5KfCI$c}+z@%O&B3CTF#kz6LI=^qg_nk>*9({kv>HYlT+Srl@luUqUpk_hNCDsqs{#^H-cS^)ajhNj6#l`7U(+A7Wm07B5 z!yQcjGUqNN!BjcrMqkETE)@^@f1^@`Rb620b+4Tuv_^b)fr< zs;=|eYrlFkc55Y<5WmqI+97#AZtWoAi9Deq+3<8_<;AS9D5&V%Hzo^J>iX>O=;Jv{ zY`>-c_LS{O2l4G?yHl?u-_F7S>L-`iuw!@sEC4IJYdtRw*%DaI!{d~Gi3VpVzz+=2 z97AFdDe#UEYum%>@8g)U%^jTf!bbYwb(aS+{QDPt&F;j(m;ATSg0gcrhYVI(s!g6i zjk2D!gyj$r46lVI40Mh(9WW(B5MIFy7{~5W8kNfTDQ;tGKsqV6P^8@x2U(sC|KqE6 z2MXdboq z?`%6wIIYQ|ZaV*WZY$Dv=)a_ZeHe zLs#RvSbZ2$bIILzPK`@c3xb7WQ;kWrYnm4hF^(K+#lzrCEMEC8D2rv-qyn|v9=yU^ z5H>2^kG>9jg5%}AA=W7EFTirBmY?>Y|9Vu7_3dQKK&8JrMI}!Zy>cyStG`3lA+WlV z4cmjMM%4O>L&d9!17SqB_ijIB;e$d}{_fPb{2N`S!=!*_a(|DA*hTO*e+~nH-UVvI zAK9kNeEqp}qKerkFK8p0tcOvSVEgGc{7B%zFXNgm* zZ?2j{|A((}(T-5?Db@b??}=P~*m~x;h0ieFoF?$AI*^v`CsQ$DR&4Ce+nECvk(#Qt z3bms<2nOqLas{@q$m_HF;@tHzPmMNvm z8YU2iS4NAohM95XrpQTRO^=o{X-!m630jQuBV@WiQCxn7d*AZ+Z4)B=p&@4D`;)^{ z`C+h&^~TS4^|_3zZM*1PI@Nl7bsYk)XX@y$$^E_Zwz@9Yo6k&9OlM;QG-@iR5C-w{ zrm8>gfkikT%j_@dr3hbaplFi)eOqD#)(>RR%5W8+EYhhG95mRAP|C=L7h+8P-CQ^f z0NQdDG+>{Vd%*=VL@#~G2=dy9A3l!K4+t^)Hw`=dE-$u>@3Px!r5Y`pcytNK z!++!;ySGH}ev${v#WWggo55)g<2LK$@mhHf+hCO* zfI2-4>(#$o89&@HYyZbU%YhqNCUN+!D;?8SEqeu1f^ChnA#9zx5r9J+0gp{)n~j%o zW7`FSbt_0C84SsmK5uSGSk?m{j>Py)qYOKI$NoOt<_RKB$CfQ=0*@r6?A9)^p*x;X z>}|c2mXzA40XCBHQ6vZ=M8r)G#yvJ>EmE4$_P2lKaR|kayL0D8y()BPv1$8W4e$PL znw(ksj-ps$6_UiTA^|HVKvBQltZ3i@SgzlYxc8YL!NEQbH{TA1YWCrQJYXY70a>9+ zb){Z+*rJo;wP)Ciu4vqO)z(j;N^8%?G66_CWX0pmE<#1Z$9nzEcY|?Y1kZDXH>`b! zPauzAb9}dPR#jluRnWFjctQSZ69G0t2Ck8vc8tD@2k$Tk9G{=wXZVt}bJDciPp~+} z%g**tWGyB~zc{VRhqewOR}P@w*S44&f)o19(av%no4FuAFD$Sa*K0r9& z>a#_=GdYlZIZ1hVqh2ypby}#t9z}vGA0MXlVcXg99{0PcSo3XZWNv)C!|u4UJ{wcZ zn0OFpW+1zqBtXEJU~HHzuHG#TIdqnQxIaf zE97aI0679#p}GyLCJ=v5-ami=qTU5J@ScwiYyRHmg%3SLz`Z|l*IPkm!{13FEp$*_ z{s@!$yPDnV)5hL%%Ead&NGK&HbgXFFCI+d|CC3*&BJ6#jC%qjH;240X>>fCst@l@o zMio&q)cEfoP6lOcn^43vQCrpSNocZ6JcbuvWUK2q;m#NWcmxp2!wtK`G64y)G-0u= zUYyAUQlar))*^!x7i-0bkQPD|KKYGlt0n2atY@`y=Sc)S1md-*@x+eI)z@&--=Xn3 zY@rU;0ti;#1Di@A=;CZ>Pph>LKzJ6eoEP^H-Ofjy#=OZ71c3Ii?J~N~$m{p#~7PMa? z{QcQbbG_UVBpok|xZ-cQoms=c7GDnb^MoonxUUiPfHsBpM8xm%_X3Q>!;<@O$Z2mQ zcU9p^%tf4w^{KYvbVqsuo#?@}v}s`piICkhgouVpPemI!^bvyvksX$%6;L=}puSGTIet0yeR>NRRSr8u@2$!sOp ztu*=8=+Jf z$4yqyV3keni}``*ggLXc1;+Y+3pvHFZzRV?eiZR27pV5jM6iSA!-zl0W(WafJ@LhEk<1~-4+&*;TfZCHj}mZb>dt>z3_8W? z^f+=l{r%6spXYpfRP!Y}p7!@!KwidYh|LWsG$SoE#-sb<>DII;U?U;LT~@TI;HV6t z83dK{nEP*J7Vafv+L9PSsnb++3xECduaTp8$q;-T;uP`ir`ko*~ zPD6r)PJMa#5o<40buEcg5u?WfujnM*KUhK_kFb%%QKV!l-MPPuVNJeD(ui38ZVKsV zL`<)3*YWd=ePrQ91&!?fF$hQS6G`I8(}-GDSMD4J^bsLF9SOQU>xj)92x%wg_rnok ze8eOV?-Rp=jyv_qw&lZa_tUsXHp zaUS{bZ635RU`)K)$gk5%<~!)-UA<)E?!_eT`>)p39xh8>ZThQCi4TL7r`_hAsw4A1 z&!zGZXdO^W7VaZXAYVBZDg!sIJVKE*2n)|Mq3);SjC0_l) zy_Bs~@5-P?J6|vFofxmNT6D&+OS5~6GxOW(KhU-o8f<#Y=%A=k8m5-h1BLb-vHsiE z_jt}=JctrPm?B)+d)s3-fkMR}2uq$=wb)Fo>|WUne@8S9T^(ZyFP$3ga_RRhwW$a+ zWrU@~ah@Z2+RgXC(K%5Bt8Bo>u<7N~fu7L#TWmZctFkDSt0Fuw7r(Z&bC7t8M2-d` zj3XYhSoH#u&cxN-7k@uplul$wa5jJc^?lK4NO=L%mfRD75Yw{ea+nN}z~zotC~ir+ zEO019JFuXP6K9+#?(bY1A$n}BxN~PV$Gr5udxv{Nk3Rz;s7hziE}t)-m!Uh=sNcSS zH-GnO$R7u4HpPvQiLL)(dNF_N+26%I)vP~QeF_R(OZD~Rcv z>f_wpf5D-B)P275N)Mg2!KwcK_MgvS_I`os<)KIv5n{`eN_`9>NEEYU$lV~J#ic|V zwZ4>uE8(3iPyb}??(@N4SA)SpaW?c#Ezys;Y8{bguthBnf9WzTZ(3NQ{5ZJdzAz&h z2`jXWjbb$HnN?6_w~aW-O=!FCYdID;y$a~{(1(K{8B!m&9S7vo5b-^T%@YXCidh5K z33RH@2bO+lTs)telYeTw>8c1#9e&vTl@QnsbP};zCvKqF$bitz3nlLkbY6AwWWt@@=RZ!;qUxWAFC-R zKpy5VtgPZZ(l|O+oZyNdHU0)hHtt$A@%}^5@{BVF|-5Ui4?69}~d&sI?5eLH+#eW#~;*V>oUZ^<$|ao86V| zdgJf%l-YN3ex5!=>EJJY9xDigCwVE+T{L8~EF4vXuacfFjJ;fl;WOZUStiY8yK-^=!*j(`6^z_weuB8TKD#2V~| z^v{8pHpGT|QL_~5L*Y%U2l(o^F^^fMjb2o=howU^@U`((YyV+-l>Ru-$;)gA=cQ@! zF07;k!)7PRA{^{LH}$p9{ciSd4e8Li?xG8=UwZHAU*9ewTYoS@V%Lya8Z-OJBTluzkj=S@A+I`9gp<>hqdVAyZpiDC6 zMLS$jp5gfUY(At3<(WW3LxasYl5f^Y!aQ|R1hG^?zHDF2+etbL_S6a*C|lgW1uY4-zdlq;oh0X_M zq+%;c0vDyMl%ElZE+t0#a?(DOfVIres}+Rm?@*}3`p2q_W6@36=et(!YGVwWL8f96 z(*b8|R)@cr@b_lhdKzM1?f#(e6b!r9*VQtZkuZbGM$kEgq+^v8AGjpA0W5b|xcJM5 zO#|{(uU0Zj3sr-d60zego)Con{ir87bUx(+tZsx3JuZ)-v9UGrux9yWckFdZcRvo< zY77Ig~YTw6c#P{XFTnCvtQ%L<(JZIKw5VSX%3Pa0jJ0MhVlukx? zPzfRY5ge1u-{W*x%zZrxm-srwu@k8JskHWOn>z=E1IpoLrWiq*eUrZ~=h`*~x@zD1 zXH~lNrD_~VjLZ&7)Bl{dp;>$q-D5_b#gc*No z4JBCY-gff7oBFoC67}4{VZ3B}!+vYbB27#jlsmlm5GeWk7}3~7*sA#OccE4$N*bZ% z3`ZoRI@d4fBc3izq={B5epi?-JN}O3DSQ5Y9^)nr?_K!5*1?qD1{|H8^xAVRUh3|d z8qFF5%s$ zS`dDG%>M3xi}-}9eIu1hAh@7sHM(NZ z4X~-F^NWUiTxV2SqZ+Y)iy)5;$=VXD76#4wbk27!5Elr3fkSPV!RdAs-lm)#f3z3I z2<1y>nlIM*ecvjQhq)c2kL|2c(ui@ON`( zku4BVXi=zy?t2JP22vP|%fnSQsT!8$3@))aQ;crk{Mh`R9-KM+SdOkfCNDk)iR*-N zaJju7XS!8=df2(Emv-s&^}7`_<6pg=2L<)d{CiymAqin^$G*PU523Sam+64ed5Xe= zqW<1(R|U+sTuA9tXedoXrD}MLtwRrg*Js#=$8e92QW8FP%mn0p!){)++gM$8fc^2TA3t+k?$i_&Bkzd*GEe6G09*sLJL$(Vn<9w z-6Tb*l?1;-h{)|0P*(XVkTCzL!#gDJQ9N+T0Fk+V*ENu>ZL>PN8}Ep-Q9M4+{r=lu zf82(~m8;kFg2wD%B=-g>(DrKjegHWnbDS0=YilX*JF7vFgmvmTN@DC{ZBGdLMImD$ zh?p&G%Bhe`5$+JF%|04#&v7F&Pvkh{9c9P6vT^RuyY+uR|NH0freXW&Q;@@Wmv^_Q zkgS2q&K^8hGsOfdzs@XaL@{HEd0f%JOw%pJ%NsxmRXh~|p+J%>BQe016dDdkC`@~C z+RCPL6H`NK`l{2i+h)Y$2by)Xogep6KYst~KhJot;n%2V^h=%a8V1^DAFN)HPQ8^- zl8A$`;HHi(0?ScFq?wF&E2=b{nN75lMjT#eGI6!;IMp{sE{7UDg;A5z=1nCX92hGWmJ#ePi#|(|gy1 z@OW1z9jJae+^eyl<9+)TOeVquTw~O6T;a~FVO1s+?;u_%-;_$TAxVLk!ODQcp=WrP zjIVug3BNzw#jNQDl`~mQQpts04hQ%N`#RY%x~4P;zW(;(*PEj@;>psM_wlYf#~#&R zo%^w5G?+*lahTP5zBkK5^6`+1vM3>pmN>b=b`K>eM$hpPjr+7Y8ZeT1wxl9OaE$IatCxWaI={?b6n<=S;#LVH8%L%gpz zo$!!AM{foJn%c{-XrJ)7C{TIJf%3Sp+<9UEu1Q7Ll#7wr6|Av$8pKHrv?hy$U1gW! zx7lY)^@SZBc--&LaDP^jrxD?u<`I?d7rl1fWV{a!b(ljOJQO<7fwhs>$x6pGq}{!N zk4#fsnQAmAbSpI<6cZz_g<6c*q9yRMzg637;BmBK)LS>GLH#+uR*8?_k-?DI2lLVI#fbOX zEsJSU1*m^8@v&HzrD$0FM$I3cYy^d62*!pwt!W-C)9B0mp5J=9Uw?ld`{VKLXYZQK z;rTR}Rr%5=H6G~aZ&+CFQ+GZt-L@JKye9R|=tE8Oa&5*cA|!4R3^U&Qz|;-4iVbT^ zUh`X6E}GC~k%W@?R{=#T=}^;fO6Pk1SQUCr1=NE@)$m!`eX9Ovyl!2Pi;uKhH`N)9d zB)e7dex6A!i1W1%`R@1o_1iDE<>aH)3o&Po4|xag51}}Fp1YEr-0F<8+&ds}W-+Om zE>m zVUG3e^Zn!F`pXsP-d8DmPdjZJ=nM8Yq3q-3o?^{@u36^M-S(3d+Iz?Q)fi`|$L&Z1 zme)XWk!p>M5V8U>TNzl^=r9OmmPc+VO{<;>#j=`|k<-~klV!|cKi`xKRAhCT!R51Lr+siczQdz%c)K$|YrhBny^wX&pW*c+Ss+dTLw-m@Ds-m<5QA}M49 z?bm8giA@%kcF<#5RB67v*NI}?SM0WgeWLwBTxg9Q)Xd)@z?{4qhr2di- zL%lVS6mzILQN4PiX;tghPb%48jI1c$YxI#gO_nQjeA{4WR=>&`G^@^0r^O#>pY#0i zxYS(j@x`X*LIjV+oEO|zhtIdiBUv4he5gNfTPvepTwhLQ8@Z)~sj<?$zDcI1vIg}@#{@*l* z3a3$N%Mgj|B#ukp-0OhlZE(jB?}I+9;KXj}r31ztG=+%zU1DlUIv^hVZN*w809dFO z^xB#-@yyYpac+jF7CFyIp^z!<6#O9yW7Qk5@YQB!%!6E=7&I?sVk{@+BcYt)+&gz^ zxj2N-|8%?g2BpWl`-z*eC=0{TUSbb5xP9~(=r^9%C{+By#8JtlIhbFkI2@&a*o+I2 z+X+CyDuIyrMw>^sBZoQ2LBwp9R+j3@s-979P2^Q$lORgG={onmTGpd`>G7^(&ndRF z$59W&M#joFE&R5%1=6J?X0l%jpvPd`pDJc>AEJ*}J8 zPcy3_+a)R|IUva^c~eNmI{-6=Ds$v)X=2_)Xqc?k3Z&s7ZPqB#c(P?3pOx%d zW7elq9*K3+s_ghqzM}=F7GOvDyfMfla zF1zTl&!Ge4ggmvwf+qBuigSRnGKN3?Y?OT&akWa5w`L*@gC&SoX(Qc~tQYy>$y*q= zss^;(*wAHTK&hYM(5XP9Eq3)>q~MuNMm5>|IET(vZ>A*dg{CS#$t_{!?wK(}C{6a_ zJxIKs5frDo`~7D!|x z0QjzTA~Vh41?M4p6)!&Tlk@fZSbWfpb01+HdC`WXu+^O26V*|?3q}}?mR2A|V%3Jz zN}rTJpB86Eh%Z9Y)~vnR00&Jnvk+*eOp_(0)i2I?w=uraiKuxnPn9=`rjLj>v*Zzo zdKp5gl9bqgT|fHZ2)YH%5OyAmYTly#zd|hIxEP*DAskl3hnew3A!9W0QkkC=!M*)aY8vpU-^8=W+3NHfLZm#v9e2 zI`+Q2n#t-K>|pPm6{Zt1Yr<0oC?gdhNe1&eGh8=bEyDBBRy*@bdiz6~y}*2$)=mn! zJI>B;b;`5vSdpOzqiSsM;d?JRZ|eG2i;rC$r-@v@j6umjeTS}uuLvEnN>*aNTJRd% z*^#nl!CuKEn^Xq*aby{=h2Q=P6HK>Ej7Dpq$huEIy^w7g&G|m)X`z*1SY1O9Kd?klj#z7}X{C`_>87_FXCekeY4Rv%lhyv<-Jo3V{tf?6}G^ zxmW4RSD0-?egQ)J#e?7UG;+}2w3Vo4akX?sWSN@vx_mK#qD>z760yO-Obs&Z*~40k z^*mI*1`_P^Fp?3JgjLO{YHS2Oj~1AGFb2GS)Y1$1TpC|rH9OqD9qaI%R+M7$#L&`0 z;RT*>CeyBL$Gh}o;te*l$MLM*Y$|HEWR)&eT{Idi;2u4S7d_n-7F zJ`syeTV|vFP29ERIFjQ)0dWGO_Q$sfLs!@f7BD}3+a0IGmmZl?+Kuh`>gg&!m=r|@ z$p|NqR$CMzla?jE{}yQYeXZ6hnHmL;8SV{d5Ax*mxI{mrT1UG=kI8N<4G8sgL$70RP?xeAcNd2fyFcrk&8q-2nuL~UznCw|I0e&C zKa%|+7H*762#l^`v1~>^yfPQ* zfoOuwgX)h%tJg1I6+YOE6EU^u%;7lkGKBtT1UIq-g{X!t4xSYZ)-z%G%vm-zzqhiZ zpb64~F1(jFIes!1`u+Fxp73KsRT7Vi3z=hBG8Z47$}ZfrJa&b83QX}A~Jm7g5v?3yV6E&ofeNn{TyUGqzDcy#tKBk+(g;s9)v@N7F?mpwU0=8A;e~KARUymFuLLF+i9|P-3muTlwJUVIyP@X`(U?hpc9irYAFsDjL|oPuH>m4~5USn(TMb_u zPDlGAa514$Fs#Ly+_^OyznJxo1uyU;Uu@?8T>c|BJ!NiBDVvPM^0(o3i=)JQotFmTzpldOs^YScdY~4K~we;aJ#Q)M4cDmN(O z8urtzgGNOig1;ke338cAgb3}4*^Mlz_8tSo2wpLXLIFm zaCLh=lh1w=H~+@)j%~#c=2^;%9d}nXN?D}INBt!9wPifK9RQ#qxa`7T_+g`ka0E-r za`Tblk91cXoHfUKJu5-&@E6|eHow8{iMyWwqk0qomU~n%XsKd|N7$)KT!!flh4t0L<%#m}a^Ir4vgf12=q!|aoO z2lp~Em}Dp%OT23H)O^)%JRb9Im~@8dzYjb-VE&%`(EFyB#6+4cNsx9*XLkQL5b+-9 zn;PWF4~t+wpMiUL6z*ytuPT#bY=I;W>x6b>#_%%P%b*{RO{0CO^@N6WvJZ7ZHs^W7 zev6(z{yg%1NB|!^ulSp=wlcCMcG;=b+LXK6%9iw|ErSZrr!GCF|3!{TG*K9e&GCY4Gv@2V)IexEe??2fwzZ}yzy=Quls4kov@8*=58Q0)Uxogc>X7)vLPjKIOpt4kvjKFViO;?997 zBdPgwe?O-qIwKP4jaP^fOB>)QM^diK;Hg=I(V-WnI1AjtL#i?#*V`P5yAz+A6V>%g z7Fs0v4g>#M5JQKf%;JobH<4UKhn5d}m-;nJy&3Ub$)%dMn$I@0HjR6Fo`;CH%O(?h zS&tGUvm<@`4^F@bcu6y{dR6wQGTD{E=arL}i%zO1>TgjUaf--A{aGdCbSW!7{`NA? zy_}xCN1q{NHjwRkhHRS$KD>9h z8gE3L!5je2UtwEbUgzZ*A(IDT2{RQ)Tr>8cP54NMM6r8NRE(g5Em zNM=97PAee_*iZbupC0`@t>N%6UW7atl4x2Ibse}EUWF*o%Ev36IuqjC!Sq@OW=D(4 z4K9ew?>rD0Ktx1)!;d)f|Ay=1q@7(;a3ijSF=9c8hf-XOG;n|pCb12?!>icEq|W$lF;I&M zmP)sV#W2$2q%>+y(r5gAf9E9;py~pNI1Q3fffhA6*-P>hyNtT2Et=~WyKoLUrqpbN zU%54=NEAh$iaaqp`SpCJxiy$Co{B<)ZoF3r8>&3DsC_w-88Zh%!rl+rp`938_yX(6 zcr(8yrBM-wJBhr&m(AY1(%B88AHA}g8Yw4KQL(Bdd)l{HA~B)|BNyP>Ob_}A^u zi+8c*3%43CjS52bIVfELr>7X^?_53ItJ>NVpW-#Zj{m#i>t<>W9Xw6`L`^=q z%{~gBac*Vh+dDnRI^0BGo6nE%WH}IKtul{iVXX?_Fux&{=*Io2~15_&0t zD&=X)Zq0T4%9Yqwm)DWD`=P0;5W?ojSVwh*nv7R|%obeO2$5VnDDYp8VLJ;ZFCkww zTSyZ517+uz80Wfxy7PU{y_$_cF35f?P?%h{2XQyvATUPp?B(IsBK-%F;R`xaVVl>J z_Fdp1Y_fJgNw7?zG|oyng#3t$(=jPgakqflU=qDPb7+$`$3@;s(ZfZ5>U6uqWNkPD z@$>+9>qHK}OB>#J;gU#S!`TP_pTl!^kvpS5dQ{;o*ruxTIwZYv-|t9_#Kow0@-}%@ zObaJy88A#uIsUHrirHr$-VJZj5Z$%Q!ygq#JrmAyA^3&E6I7>@3QEB;|R=2WN8SM^k1elM?)-(Yx!X9j1R!%{5XFBc)jYo zd+4>>O{W!?yqhPVxHwV`PExq5_#Ph}yaRE@OE-lV`iH+xO*1^R=}cr(Bcj-jud&uZ`%uk`fs#8%BdYB%lBX90amdMM%aKbkdVyvo?R~HvAGE+o5 zf9zb$#x3+1W=o`$md|(Z?{2DgfZUQZHc|`}DY)eWdb};CIaV+)_}_5p%U+XX3EHF@ zC)5YwT8&a2wjI1QpCth}=BuNj%l}b#ZP|_EI*{jJ3B8fZ!T$Gl$0VM7NThA0`}$+j z$vBQgfgn%-suVq;EFN?nV;+~)b>aO0&2(^^aMySp&Xm82D3|NTKaJtDrBklY@I2s>0m22O$l!eB=1~JxVc5Np{CJvcH{bVsGL{EZ z^xV0Qlpy!5O7~`X*$+jz6*ycbW)KE8!p%WjbpBXCE>hE-WxFZ*NbNzTn_!9$5$k*z zvjFI1>~FsPZ!5P%&Z;whmdi4Kyc0ovl9gy8a1^}J;10u>o7ntCY!qpp4x#U9yWxmR zT~Tm42-!1|n5N-5QnNN1l_u&v)r{Xzx*#L6kX>`!dMo`V9eS+4R#b#!E zOiIs`?`G%%WyVbu0c$7$Qq+Q*)x5+L!7$BOM0vDGB>S7@g@XahpIa~0^u zw37zNEYcH*Xc-Cm2XnOd9^+m0m|I`fLC|<>h1hJYwPUsfsUBqPwh;nXYTAwDZRJlH zvzZsRSim^F?$(1LYjLhAugo zmTpv<=ekT4x*Pq2%)5+1G%=S)@rjW^OKtOb^RzXTl)g7XNhA zC!Chk$pgxLHr{I$A*49mHTTqd$%|#-fi%>=9*t9d;%4o>j1eg;dWlTB5nh(bjXtQ` zwRZ?v%{=;ER7QPyx_of#r>w0kSS6m<{0lgtj-$_(y`^_X(_`2qjTOMA7$^!S8@wGW z0B+h2?RGuvG1@wo~&CzW_oP}q8-n1}HAGHnj_ z-P`+hz8#f)u6$?If19q(7fseY*k{Y8$IUuk9n23S0&rur~$FS^o z5rB`T9-2EZa@L7G(})dkS_W?Y1>W=TDSoDyEeOA+P&hD=Ydjd=32TI{Nz(+LybKTe zg67dRudv_+coNcu1xiH2N85hn%am)q>{Fo3=rUuP(hjPSBsGd(jzlNQ?W@OVqj=|= z)!V(So##L)o8oJqtQp?wk79L|p;*FGEc2t{9|f?LoZVWe+(}doi6*3pK^_$ zB5mP;y}M#g!-8+tg38G4pOvNKCZeH{wm8k}^+?pATHSC#GOlXTqZ7ak{z*7~l6f)B zF^4h?q9Q!Ov!o+ol2;4wD;Cn@^?c3Z9K}I(`v6Dlgf_hmzH)+f&$X~T{g_yd*1C%pA2S&Owt*{ZS zSz?0xd6)mcG3Ad0d@UEAh8(ufqee~WNs9GtdzT&9hwx-%_vr>{90ra3g}6zB%T?&t{0bgeeWFy#E+xM;b~Z?#)CBG+-aoOlOqm>7Vm(6`=jD z5HAae4n~K#jPcCHQsu)5A0g|9rh_2iX1mgy!evgPiES!vD={`5o4`J>l(LUCjyB0t z5k}s-eqaoE4$__(cLY9iG;<$FWt4;OyAJ`^B8v#ZOBC_*&WF7dwjV9vN!U5@_{06A zhCmt){x4g8pkOb?=LXSxtFZ6XoOIrYSP+Fu-rbT%=e~aG6_29cGA1H($$}|@p%Eh% zd&g{j=^kw=Z}09N)w6}i%HAs$S>GfSd7?y#M%Kyr-c@4har&TpOm3zjI;FjCpj3&< zLPJ+DzUF3tNsc4>*dnbre^k}f>#|o6-YeTdm18|*@D4mMU-scF#0+(fv=li~jwgUp z(yuOT_-MR$6P`S{280}#iW2a}(aNa~rOB;x>!t@@_E9IV^IsUBE?X|*f)#w;Xzx5WUK|Yquas2v%$b7 z6m5QrF2+-c${nz4aIKP1>T*XdYQdXMy30TE_h?$js$Hm-iMaNQ06<`3BWCta^QeT4 z)@z}Rooz->1m*OFNrVj#P*P-i*%JhOT+A$VVCUDro(tYBf-S?YI@P? z9>~dPP|cP{!%o3znTCwbptKSArVmQmXIXSdF|}qtrHBShXsAW` z6-NCV;|LDE^`0`NWrvl$TLs)=p;W9TSJ#F}IZ>4sVlSCbkCAq4?-oaG0~#G)*Myu5>GZeK?!ke4nC$zj!xY$AlE> z`v!89zxZ;he0UFsLNYOy5K7KmwFx4=((|Vur8+{=cw<#@@${X^Z_s?77-)Vki@g(a z^85D}-cT**|KYl>_(z0B51jl(1qd69;^ z>2E#(m4cv_TCz6KMA9*&3CIYr!$qQDtv2=FEoyGV`r^o}TVyDme+{>sK)4JX(*Dve zHT$Q~yh+tEf~aJK;0tInl;OY#wEYaOZ-BzS>{X6ioXtE{_zqrNXa)}>7B4}&)SS=m z2StQS3-;{Tq==-_tguJsf+UwW0ioC0vL{pGhT5||?F2d5yOSeq06Nd~-=17}XnM`@ zsPw-|3k@bG3lQ00t7-}FK|4kL_$XHNn#>8~8zwY;7DNeuzXxZ2$?I#R$c9aief^?Y z&^17dZ6oGk+E^|6lrDZ=Y(s2`YrJ(IH+z826aB}mT}BWa^5u#_0Tv0=m<84v-`NKA1en){fO0ol-K=p7ijaL`K}Ix8=EjAJ@C>eJQn zNb*Ig-S`{#NmoE)oej#zDBXJ%JiqXYyJ)(K1>~$EK?u)AqD}qY>rNa}tyl&64LdkQ_B0h6Z_v^$&t+%(#?8;6XhT8~`s8JTsCeC4LG z@}vHL>9EQ~^yJEG5J*8AXf&lL{vO?_(;1lJaQhU^4apj$Dr|t6G~QGAEWC%?Y6%Oy zpkMRxW(U2T36Bh26kl3UNc|8RshjkG#y{FmDP{D!@b`7QFDB#x|7AV$4}bf)g^wIC zn&e{$Ur?aB~j{wRjY7UduPTk?P{7c7xLaVBYL=0J}_XW;hL-<$ZW?VaqP};*#eZl#aQt9y6|`* z;?3hQ?Ie%i^D{wmd$#}uesJMInq{^zG9NYzkb7$!Yaxj!==jQokfAY7l)kZ9n_HWt zxVZXbF}%;f;lLiZ?cblp#^RpWR%I#sK{Fuh`yw&;TBSyIo6XN~myxP8JF^@Q&`(+o zUpxaIc)6Z;?fpskfO5GRH7K#HUo4t~mDcEn`G+Z1kH|E%Wbzcr-dnY`v{p+!SMj)` z$q_Nl-1c9z_dJY3MXMIpeJU{s%MbrsL3PoCSP7_~v}{EX2|TT#n|Z=@@CE|2{X5}= zWgL5{2jHUw%xdccSLef4#|sUn++6)1t~@})K4vFke}3bC^T*tX_0E5S$?&Lh%Nx*RW$Sqh_E~L z)?eD}GLX>JbW{5=UjDt(LiV$z0`;&<~gWSy0|97Cw*_Ufzi$ z_AdPzE%#Kupw8Y^<0Xy)dM{dp?f*v891We(zlH%1M@OS`14YC)t$%aMQWumNkQUba z)PgoGRTRN$tZjRk7PA+%$>=&dZO?~JHu|MF

QX%0j8ymJuF=G6h>lB}gAeKo+#u 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 JPDHLkV1k8~*MI;3 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/ScreenShots/videoPlayerVc.PNG b/TZImagePickerController/ScreenShots/videoPlayerVc.PNG new file mode 100644 index 0000000000000000000000000000000000000000..20e38b17aeda4f9a56b80d9cbe74484733838b9e GIT binary patch literal 109188 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

1fe9F;OrIsctI4YU+d&&-= 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⪚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 h`;XWTnudbpRW*W;kOBebY!>mBI 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 Ud;vGJ + +@interface NSBundle (TZImagePicker) + ++ (NSBundle *)tz_imagePickerBundle; + ++ (NSString *)tz_localizedStringForKey:(NSString *)key value:(NSString *)value; ++ (NSString *)tz_localizedStringForKey:(NSString *)key; + +@end + diff --git a/TZImagePickerController/TZImagePickerController/NSBundle+TZImagePicker.m b/TZImagePickerController/TZImagePickerController/NSBundle+TZImagePicker.m new file mode 100755 index 0000000..43024d6 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/NSBundle+TZImagePicker.m @@ -0,0 +1,35 @@ +// +// NSBundle+TZImagePicker.m +// TZImagePickerController +// +// Created by 谭真 on 16/08/18. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "NSBundle+TZImagePicker.h" +#import "TZImagePickerController.h" + +@implementation NSBundle (TZImagePicker) + ++ (NSBundle *)tz_imagePickerBundle { +#ifdef SWIFT_PACKAGE + NSBundle *bundle = SWIFTPM_MODULE_BUNDLE; +#else + NSBundle *bundle = [NSBundle bundleForClass:[TZImagePickerController class]]; +#endif + NSURL *url = [bundle URLForResource:@"TZImagePickerController" withExtension:@"bundle"]; + bundle = [NSBundle bundleWithURL:url]; + return bundle; +} + ++ (NSString *)tz_localizedStringForKey:(NSString *)key { + return [self tz_localizedStringForKey:key value:@""]; +} + ++ (NSString *)tz_localizedStringForKey:(NSString *)key value:(NSString *)value { + NSBundle *bundle = [TZImagePickerConfig sharedInstance].languageBundle; + NSString *value1 = [bundle localizedStringForKey:key value:value table:nil]; + return value1; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZAssetCell.h b/TZImagePickerController/TZImagePickerController/TZAssetCell.h new file mode 100644 index 0000000..67051e8 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZAssetCell.h @@ -0,0 +1,61 @@ +// +// TZAssetCell.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import +#import + +typedef enum : NSUInteger { + TZAssetCellTypePhoto = 0, + TZAssetCellTypeLivePhoto, + TZAssetCellTypePhotoGif, + TZAssetCellTypeVideo, + TZAssetCellTypeAudio, +} TZAssetCellType; + +@class TZAssetModel; +@interface TZAssetCell : UICollectionViewCell +@property (weak, nonatomic) UIButton *selectPhotoButton; +@property (weak, nonatomic) UIButton *cannotSelectLayerButton; +@property (nonatomic, strong) TZAssetModel *model; +@property (assign, nonatomic) NSInteger index; +@property (nonatomic, copy) void (^didSelectPhotoBlock)(BOOL); +@property (nonatomic, assign) TZAssetCellType type; +@property (nonatomic, assign) BOOL allowPickingGif; +@property (nonatomic, assign) BOOL allowPickingMultipleVideo; +@property (nonatomic, copy) NSString *representedAssetIdentifier; +@property (nonatomic, assign) int32_t imageRequestID; + +@property (nonatomic, strong) UIImage *photoSelImage; +@property (nonatomic, strong) UIImage *photoDefImage; + +@property (nonatomic, assign) BOOL showSelectBtn; +@property (assign, nonatomic) BOOL allowPreview; + +@property (nonatomic, copy) void (^assetCellDidSetModelBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView); +@property (nonatomic, copy) void (^assetCellDidLayoutSubviewsBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView); +@end + + +@class TZAlbumModel; +@interface TZAlbumCell : UITableViewCell +@property (nonatomic, strong) TZAlbumModel *model; +@property (weak, nonatomic) UIButton *selectedCountButton; + +@property (nonatomic, copy) void (^albumCellDidSetModelBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel); +@property (nonatomic, copy) void (^albumCellDidLayoutSubviewsBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel); +@end + + +@interface TZAssetCameraCell : UICollectionViewCell +@property (nonatomic, strong) UIImageView *imageView; +@end + + +@interface TZAssetAddMoreCell : TZAssetCameraCell +@property (nonatomic, strong) UILabel *tipLabel; +@end diff --git a/TZImagePickerController/TZImagePickerController/TZAssetCell.m b/TZImagePickerController/TZImagePickerController/TZAssetCell.m new file mode 100644 index 0000000..bb23ef3 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZAssetCell.m @@ -0,0 +1,548 @@ +// +// TZAssetCell.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "TZAssetCell.h" +#import "TZAssetModel.h" +#import "UIView+TZLayout.h" +#import "TZImageManager.h" +#import "TZImagePickerController.h" +#import "TZProgressView.h" + +@interface TZAssetCell () +@property (weak, nonatomic) UIImageView *imageView; // The photo / 照片 +@property (weak, nonatomic) UIImageView *selectImageView; +@property (weak, nonatomic) UILabel *indexLabel; +@property (weak, nonatomic) UIView *bottomView; +@property (weak, nonatomic) UILabel *timeLength; +@property (strong, nonatomic) UITapGestureRecognizer *tapGesture; + +@property (nonatomic, weak) UIImageView *videoImgView; +@property (nonatomic, strong) TZProgressView *progressView; +@property (nonatomic, assign) int32_t bigImageRequestID; +@end + +@implementation TZAssetCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reload:) name:@"TZ_PHOTO_PICKER_RELOAD_NOTIFICATION" object:nil]; + return self; +} + +- (void)setModel:(TZAssetModel *)model { + _model = model; + self.representedAssetIdentifier = model.asset.localIdentifier; + int32_t imageRequestID = [[TZImageManager manager] getPhotoWithAsset:model.asset photoWidth:self.tz_width completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + // Set the cell's thumbnail image if it's still showing the same asset. + if ([self.representedAssetIdentifier isEqualToString:model.asset.localIdentifier]) { + self.imageView.image = photo; + [self setNeedsLayout]; + } else { + // NSLog(@"this cell is showing other asset"); + [[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID]; + } + if (!isDegraded) { + [self hideProgressView]; + self.imageRequestID = 0; + } + } progressHandler:nil networkAccessAllowed:NO]; + if (imageRequestID && self.imageRequestID && imageRequestID != self.imageRequestID) { + [[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID]; + // NSLog(@"cancelImageRequest %d",self.imageRequestID); + } + self.imageRequestID = imageRequestID; + self.selectPhotoButton.selected = model.isSelected; + self.selectImageView.image = self.selectPhotoButton.isSelected ? self.photoSelImage : self.photoDefImage; + self.indexLabel.hidden = !self.selectPhotoButton.isSelected; + + self.type = (NSInteger)model.type; + // 让宽度/高度小于 最小可选照片尺寸 的图片不能选中 + if (![[TZImageManager manager] isPhotoSelectableWithAsset:model.asset]) { + if (_selectImageView.hidden == NO) { + self.selectPhotoButton.hidden = YES; + _selectImageView.hidden = YES; + } + } + // 如果用户选中了该图片,提前获取一下大图 + if (model.isSelected) { + [self requestBigImage]; + } else { + [self cancelBigImageRequest]; + } + [self setNeedsLayout]; + + if (self.assetCellDidSetModelBlock) { + self.assetCellDidSetModelBlock(self, _imageView, _selectImageView, _indexLabel, _bottomView, _timeLength, _videoImgView); + } +} + +- (void)setIndex:(NSInteger)index { + _index = index; + self.indexLabel.text = [NSString stringWithFormat:@"%zd", index]; + [self.contentView bringSubviewToFront:self.indexLabel]; +} + +- (void)setShowSelectBtn:(BOOL)showSelectBtn { + _showSelectBtn = showSelectBtn; + BOOL selectable = [[TZImageManager manager] isPhotoSelectableWithAsset:self.model.asset]; + if (!self.selectPhotoButton.hidden) { + self.selectPhotoButton.hidden = !showSelectBtn || !selectable; + } + if (!self.selectImageView.hidden) { + self.selectImageView.hidden = !showSelectBtn || !selectable; + } +} + +- (void)setType:(TZAssetCellType)type { + _type = type; + if (type == TZAssetCellTypePhoto || type == TZAssetCellTypeLivePhoto || (type == TZAssetCellTypePhotoGif && !self.allowPickingGif) || self.allowPickingMultipleVideo) { + _selectImageView.hidden = NO; + _selectPhotoButton.hidden = NO; + _bottomView.hidden = YES; + } else { // Video of Gif + _selectImageView.hidden = YES; + _selectPhotoButton.hidden = YES; + } + + if (type == TZAssetCellTypeVideo) { + self.bottomView.hidden = NO; + self.timeLength.text = _model.timeLength; + self.videoImgView.hidden = NO; + _timeLength.tz_left = self.videoImgView.tz_right; + _timeLength.textAlignment = NSTextAlignmentRight; + } else if (type == TZAssetCellTypePhotoGif && self.allowPickingGif) { + self.bottomView.hidden = NO; + self.timeLength.text = @"GIF"; + self.videoImgView.hidden = YES; + _timeLength.tz_left = 5; + _timeLength.textAlignment = NSTextAlignmentLeft; + } +} + +- (void)setAllowPreview:(BOOL)allowPreview { + _allowPreview = allowPreview; + if (allowPreview) { + _imageView.userInteractionEnabled = NO; + _tapGesture.enabled = NO; + } else { + _imageView.userInteractionEnabled = YES; + _tapGesture.enabled = YES; + } +} + +- (void)selectPhotoButtonClick:(UIButton *)sender { + if (self.didSelectPhotoBlock) { + self.didSelectPhotoBlock(sender.isSelected); + } + self.selectImageView.image = sender.isSelected ? self.photoSelImage : self.photoDefImage; + if (sender.isSelected) { + [UIView showOscillatoryAnimationWithLayer:_selectImageView.layer type:TZOscillatoryAnimationToBigger]; + // 用户选中了该图片,提前获取一下大图 + [self requestBigImage]; + } else { // 取消选中,取消大图的获取 + [self cancelBigImageRequest]; + } +} + +/// 只在单选状态且allowPreview为NO时会有该事件 +- (void)didTapImageView { + if (self.didSelectPhotoBlock) { + self.didSelectPhotoBlock(NO); + } +} + +- (void)hideProgressView { + if (_progressView) { + self.progressView.hidden = YES; + self.imageView.alpha = 1.0; + } +} + +- (void)requestBigImage { + if (_bigImageRequestID) { + [[PHImageManager defaultManager] cancelImageRequest:_bigImageRequestID]; + } + + _bigImageRequestID = [[TZImageManager manager] requestImageDataForAsset:_model.asset completion:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { + BOOL iCloudSyncFailed = !imageData && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.model.iCloudFailed = iCloudSyncFailed; + if (iCloudSyncFailed && self.didSelectPhotoBlock) { + self.didSelectPhotoBlock(YES); + self.selectImageView.image = self.photoDefImage; + } + [self hideProgressView]; + } progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + if (self.model.isSelected) { + progress = progress > 0.02 ? progress : 0.02;; + self.progressView.progress = progress; + self.progressView.hidden = NO; + self.imageView.alpha = 0.4; + if (progress >= 1) { + [self hideProgressView]; + } + } else { + // 快速连续点几次,会EXC_BAD_ACCESS... + // *stop = YES; + [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + [self cancelBigImageRequest]; + } + }]; + if (_model.type == TZAssetCellTypeVideo) { + [[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) { + BOOL iCloudSyncFailed = !playerItem && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.model.iCloudFailed = iCloudSyncFailed; + if (iCloudSyncFailed && self.didSelectPhotoBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + self.didSelectPhotoBlock(YES); + self.selectImageView.image = self.photoDefImage; + }); + } + }]; + } +} + +- (void)cancelBigImageRequest { + if (_bigImageRequestID) { + [[PHImageManager defaultManager] cancelImageRequest:_bigImageRequestID]; + } + [self hideProgressView]; +} + +#pragma mark - Notification + +- (void)reload:(NSNotification *)noti { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)noti.object; + + UIViewController *parentViewController = nil; + UIResponder *responder = self.nextResponder; + do { + if ([responder isKindOfClass:[UIViewController class]]) { + parentViewController = (UIViewController *)responder; + break; + } + responder = responder.nextResponder; + } while (responder); + + if (parentViewController.navigationController != tzImagePickerVc) { + return; + } + + if (self.model.isSelected && tzImagePickerVc.showSelectedIndex) { + self.index = [tzImagePickerVc.selectedAssetIds indexOfObject:self.model.asset.localIdentifier] + 1; + } + self.indexLabel.hidden = !self.selectPhotoButton.isSelected; + BOOL notSelectable = [TZCommonTools isAssetNotSelectable:self.model tzImagePickerVc:tzImagePickerVc]; + if (notSelectable && tzImagePickerVc.showPhotoCannotSelectLayer && !self.model.isSelected) { + self.cannotSelectLayerButton.backgroundColor = tzImagePickerVc.cannotSelectLayerColor; + self.cannotSelectLayerButton.hidden = NO; + } else { + self.cannotSelectLayerButton.hidden = YES; + } +} + +#pragma mark - Lazy load + +- (UIButton *)selectPhotoButton { + if (_selectPhotoButton == nil) { + UIButton *selectPhotoButton = [[UIButton alloc] init]; + [selectPhotoButton addTarget:self action:@selector(selectPhotoButtonClick:) forControlEvents:UIControlEventTouchUpInside]; + [self.contentView addSubview:selectPhotoButton]; + _selectPhotoButton = selectPhotoButton; + } + return _selectPhotoButton; +} + +- (UIImageView *)imageView { + if (_imageView == nil) { + UIImageView *imageView = [[UIImageView alloc] init]; + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.clipsToBounds = YES; + [self.contentView addSubview:imageView]; + _imageView = imageView; + + _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapImageView)]; + [_imageView addGestureRecognizer:_tapGesture]; + self.allowPreview = self.allowPreview; + } + return _imageView; +} + +- (UIImageView *)selectImageView { + if (_selectImageView == nil) { + UIImageView *selectImageView = [[UIImageView alloc] init]; + selectImageView.contentMode = UIViewContentModeCenter; + selectImageView.clipsToBounds = YES; + [self.contentView addSubview:selectImageView]; + _selectImageView = selectImageView; + } + return _selectImageView; +} + +- (UIView *)bottomView { + if (_bottomView == nil) { + UIView *bottomView = [[UIView alloc] init]; + static NSInteger rgb = 0; + bottomView.userInteractionEnabled = NO; + bottomView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.8]; + [self.contentView addSubview:bottomView]; + _bottomView = bottomView; + } + return _bottomView; +} + +- (UIButton *)cannotSelectLayerButton { + if (_cannotSelectLayerButton == nil) { + UIButton *cannotSelectLayerButton = [[UIButton alloc] init]; + [self.contentView addSubview:cannotSelectLayerButton]; + _cannotSelectLayerButton = cannotSelectLayerButton; + } + return _cannotSelectLayerButton; +} + +- (UIImageView *)videoImgView { + if (_videoImgView == nil) { + UIImageView *videoImgView = [[UIImageView alloc] init]; + [videoImgView setImage:[UIImage tz_imageNamedFromMyBundle:@"VideoSendIcon"]]; + [self.bottomView addSubview:videoImgView]; + _videoImgView = videoImgView; + } + return _videoImgView; +} + +- (UILabel *)timeLength { + if (_timeLength == nil) { + UILabel *timeLength = [[UILabel alloc] init]; + timeLength.font = [UIFont boldSystemFontOfSize:11]; + timeLength.textColor = [UIColor whiteColor]; + timeLength.textAlignment = NSTextAlignmentRight; + [self.bottomView addSubview:timeLength]; + _timeLength = timeLength; + } + return _timeLength; +} + +- (UILabel *)indexLabel { + if (_indexLabel == nil) { + UILabel *indexLabel = [[UILabel alloc] init]; + indexLabel.font = [UIFont systemFontOfSize:14]; + indexLabel.adjustsFontSizeToFitWidth = YES; + indexLabel.textColor = [UIColor whiteColor]; + indexLabel.textAlignment = NSTextAlignmentCenter; + [self.contentView addSubview:indexLabel]; + _indexLabel = indexLabel; + } + return _indexLabel; +} + +- (TZProgressView *)progressView { + if (_progressView == nil) { + _progressView = [[TZProgressView alloc] init]; + _progressView.hidden = YES; + [self addSubview:_progressView]; + } + return _progressView; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _cannotSelectLayerButton.frame = self.bounds; + if (self.allowPreview) { + _selectPhotoButton.frame = CGRectMake(self.tz_width - 44, 0, 44, 44); + } else { + _selectPhotoButton.frame = self.bounds; + } + _selectImageView.frame = CGRectMake(self.tz_width - 27, 3, 24, 24); + if (_selectImageView.image.size.width <= 27) { + _selectImageView.contentMode = UIViewContentModeCenter; + } else { + _selectImageView.contentMode = UIViewContentModeScaleAspectFit; + } + _indexLabel.frame = _selectImageView.frame; + _imageView.frame = self.bounds; + + static CGFloat progressWH = 20; + CGFloat progressXY = (self.tz_width - progressWH) / 2; + _progressView.frame = CGRectMake(progressXY, progressXY, progressWH, progressWH); + + _bottomView.frame = CGRectMake(0, self.tz_height - 17, self.tz_width, 17); + _videoImgView.frame = CGRectMake(8, 0, 17, 17); + _timeLength.frame = CGRectMake(self.videoImgView.tz_right, 0, self.tz_width - self.videoImgView.tz_right - 5, 17); + + self.type = (NSInteger)self.model.type; + self.showSelectBtn = self.showSelectBtn; + + [self.contentView bringSubviewToFront:_bottomView]; + [self.contentView bringSubviewToFront:_cannotSelectLayerButton]; + [self.contentView bringSubviewToFront:_selectPhotoButton]; + [self.contentView bringSubviewToFront:_selectImageView]; + [self.contentView bringSubviewToFront:_indexLabel]; + + if (self.assetCellDidLayoutSubviewsBlock) { + self.assetCellDidLayoutSubviewsBlock(self, _imageView, _selectImageView, _indexLabel, _bottomView, _timeLength, _videoImgView); + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + +@interface TZAlbumCell () +@property (weak, nonatomic) UIImageView *posterImageView; +@property (weak, nonatomic) UILabel *titleLabel; +@end + +@implementation TZAlbumCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + self.backgroundColor = [UIColor whiteColor]; + self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + return self; +} + +- (void)setModel:(TZAlbumModel *)model { + _model = model; + + UIColor *nameColor = UIColor.blackColor; + if (@available(iOS 13.0, *)) { + nameColor = UIColor.labelColor; + } + NSMutableAttributedString *nameString = [[NSMutableAttributedString alloc] initWithString:model.name attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:nameColor}]; + NSAttributedString *countString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" (%zd)",model.count] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor lightGrayColor]}]; + [nameString appendAttributedString:countString]; + self.titleLabel.attributedText = nameString; + [[TZImageManager manager] getPostImageWithAlbumModel:model completion:^(UIImage *postImage) { + self.posterImageView.image = postImage; + [self setNeedsLayout]; + }]; + if (model.selectedCount) { + self.selectedCountButton.hidden = NO; + [self.selectedCountButton setTitle:[NSString stringWithFormat:@"%zd",model.selectedCount] forState:UIControlStateNormal]; + } else { + self.selectedCountButton.hidden = YES; + } + + if (self.albumCellDidSetModelBlock) { + self.albumCellDidSetModelBlock(self, _posterImageView, _titleLabel); + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _selectedCountButton.frame = CGRectMake(self.contentView.tz_width - 24, 23, 24, 24); + NSInteger titleHeight = ceil(self.titleLabel.font.lineHeight); + self.titleLabel.frame = CGRectMake(80, (self.tz_height - titleHeight) / 2, self.tz_width - 80 - 50, titleHeight); + self.posterImageView.frame = CGRectMake(0, 0, 70, 70); + + if (self.albumCellDidLayoutSubviewsBlock) { + self.albumCellDidLayoutSubviewsBlock(self, _posterImageView, _titleLabel); + } +} + +- (void)layoutSublayersOfLayer:(CALayer *)layer { + [super layoutSublayersOfLayer:layer]; +} + +#pragma mark - Lazy load + +- (UIImageView *)posterImageView { + if (_posterImageView == nil) { + UIImageView *posterImageView = [[UIImageView alloc] init]; + posterImageView.contentMode = UIViewContentModeScaleAspectFill; + posterImageView.clipsToBounds = YES; + [self.contentView addSubview:posterImageView]; + _posterImageView = posterImageView; + } + return _posterImageView; +} + +- (UILabel *)titleLabel { + if (_titleLabel == nil) { + UILabel *titleLabel = [[UILabel alloc] init]; + titleLabel.font = [UIFont boldSystemFontOfSize:17]; + if (@available(iOS 13.0, *)) { + titleLabel.textColor = UIColor.labelColor; + } else { + titleLabel.textColor = [UIColor blackColor]; + } + titleLabel.textAlignment = NSTextAlignmentLeft; + [self.contentView addSubview:titleLabel]; + _titleLabel = titleLabel; + } + return _titleLabel; +} + +- (UIButton *)selectedCountButton { + if (_selectedCountButton == nil) { + UIButton *selectedCountButton = [[UIButton alloc] init]; + selectedCountButton.titleLabel.adjustsFontSizeToFitWidth = YES; + selectedCountButton.layer.cornerRadius = 12; + selectedCountButton.clipsToBounds = YES; + selectedCountButton.backgroundColor = [UIColor redColor]; + [selectedCountButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + selectedCountButton.titleLabel.font = [UIFont systemFontOfSize:15]; + [self.contentView addSubview:selectedCountButton]; + _selectedCountButton = selectedCountButton; + } + return _selectedCountButton; +} + +@end + + + +@implementation TZAssetCameraCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor whiteColor]; + _imageView = [[UIImageView alloc] init]; + _imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500]; + _imageView.contentMode = UIViewContentModeScaleAspectFill; + [self.contentView addSubview:_imageView]; + self.clipsToBounds = YES; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _imageView.frame = self.bounds; +} + +@end + + +@implementation TZAssetAddMoreCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _tipLabel = [[UILabel alloc] init]; + _tipLabel.numberOfLines = 2; + _tipLabel.textAlignment = NSTextAlignmentCenter; + _tipLabel.font = [UIFont systemFontOfSize:12]; + _tipLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; + CGFloat rgb = 156 / 255.0; + _tipLabel.textColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; + [self.contentView addSubview:_tipLabel]; + + self.clipsToBounds = YES; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _tipLabel.frame = CGRectMake(5, self.tz_height / 2, self.tz_width - 10, self.tz_height / 2 - 5); +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZAssetModel.h b/TZImagePickerController/TZImagePickerController/TZAssetModel.h new file mode 100755 index 0000000..b8bb80f --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZAssetModel.h @@ -0,0 +1,56 @@ +// +// TZAssetModel.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import +#import +#import + +typedef enum : NSUInteger { + TZAssetModelMediaTypePhoto = 0, + TZAssetModelMediaTypeLivePhoto, + TZAssetModelMediaTypePhotoGif, + TZAssetModelMediaTypeVideo, + TZAssetModelMediaTypeAudio +} TZAssetModelMediaType; + +@class PHAsset; +@interface TZAssetModel : NSObject + +@property (nonatomic, strong) PHAsset *asset; +@property (nonatomic, assign) BOOL isSelected; ///< The select status of a photo, default is No +@property (nonatomic, assign) TZAssetModelMediaType type; +@property (nonatomic, copy) NSString *timeLength; +@property (nonatomic, assign) BOOL iCloudFailed; + +/// Init a photo dataModel With a PHAsset +/// 用一个PHAsset实例,初始化一个照片模型 ++ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type; ++ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength; + +@end + + +@class PHFetchResult; +@interface TZAlbumModel : NSObject + +@property (nonatomic, strong) NSString *name; ///< The album name +@property (nonatomic, assign) NSInteger count; ///< Count of photos the album contain +@property (nonatomic, strong) PHFetchResult *result; +@property (nonatomic, strong) PHAssetCollection *collection; +@property (nonatomic, strong) PHFetchOptions *options; + +@property (nonatomic, strong) NSArray *models; +@property (nonatomic, strong) NSArray *selectedModels; +@property (nonatomic, assign) NSUInteger selectedCount; + +@property (nonatomic, assign) BOOL isCameraRoll; + +- (void)setResult:(PHFetchResult *)result needFetchAssets:(BOOL)needFetchAssets; +- (void)refreshFetchResult; + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZAssetModel.m b/TZImagePickerController/TZImagePickerController/TZAssetModel.m new file mode 100644 index 0000000..4a534fd --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZAssetModel.m @@ -0,0 +1,79 @@ +// +// TZAssetModel.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "TZAssetModel.h" +#import "TZImageManager.h" + +@implementation TZAssetModel + ++ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type{ + TZAssetModel *model = [[TZAssetModel alloc] init]; + model.asset = asset; + model.isSelected = NO; + model.type = type; + return model; +} + ++ (instancetype)modelWithAsset:(PHAsset *)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength { + TZAssetModel *model = [self modelWithAsset:asset type:type]; + model.timeLength = timeLength; + return model; +} + +@end + + + +@implementation TZAlbumModel + +- (void)setResult:(PHFetchResult *)result needFetchAssets:(BOOL)needFetchAssets { + _result = result; + if (needFetchAssets) { + [[TZImageManager manager] getAssetsFromFetchResult:result completion:^(NSArray *models) { + self->_models = models; + if (self->_selectedModels) { + [self checkSelectedModels]; + } + }]; + } +} + +- (void)refreshFetchResult { + PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:self.collection options:self.options]; + self.count = fetchResult.count; + [self setResult:fetchResult]; +} + +- (void)setSelectedModels:(NSArray *)selectedModels { + _selectedModels = selectedModels; + if (_models) { + [self checkSelectedModels]; + } +} + +- (void)checkSelectedModels { + self.selectedCount = 0; + NSMutableSet *selectedAssets = [NSMutableSet setWithCapacity:_selectedModels.count]; + for (TZAssetModel *model in _selectedModels) { + [selectedAssets addObject:model.asset]; + } + for (TZAssetModel *model in _models) { + if ([selectedAssets containsObject:model.asset]) { + self.selectedCount ++; + } + } +} + +- (NSString *)name { + if (_name) { + return _name; + } + return @""; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.h b/TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.h new file mode 100644 index 0000000..5325edf --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.h @@ -0,0 +1,16 @@ +// +// TZAuthLimitedFooterTipView.h +// TZImagePickerController +// +// Created by qiaoxy on 2021/8/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TZAuthLimitedFooterTipView : UIView + +@end + +NS_ASSUME_NONNULL_END diff --git a/TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.m b/TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.m new file mode 100644 index 0000000..9a5af9d --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZAuthLimitedFooterTipView.m @@ -0,0 +1,87 @@ +// +// TZAuthLimitedFooterTipView.m +// TZImagePickerController +// +// Created by qiaoxy on 2021/8/24. +// + +#import "TZAuthLimitedFooterTipView.h" +#import "TZImagePickerController.h" + +@interface TZAuthLimitedFooterTipView() +@property (nonatomic,strong) UIImageView *tipImgView; +@property (nonatomic,strong) UILabel *tipLable; +@property (nonatomic,strong) UIImageView *detailImgView; +@end + +@implementation TZAuthLimitedFooterTipView + +- (instancetype)init { + self = [super init]; + if (self) { + [self initSubViews]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + } + return self; +} + +- (void)initSubViews { + [self addSubview:self.tipImgView]; + [self addSubview:self.tipLable]; + [self addSubview:self.detailImgView]; + CGFloat margin = 15; + CGFloat tipImgViewWH = 20; + CGFloat detailImgViewWH = 12; + CGFloat screenW = [UIScreen mainScreen].bounds.size.width; + + self.tipImgView.frame = CGRectMake(margin, 0, tipImgViewWH, tipImgViewWH); + self.detailImgView.frame = CGRectMake(screenW - margin - detailImgViewWH, 0, detailImgViewWH, detailImgViewWH); + + CGFloat tipLabelX = CGRectGetMaxX(self.tipImgView.frame) + 10; + CGFloat tipLabelW = screenW - tipLabelX - detailImgViewWH - margin - 4; + self.tipLable.frame = CGRectMake(tipLabelX, 0, tipLabelW, self.bounds.size.height); + + self.tipImgView.center = CGPointMake(self.tipImgView.center.x, self.tipLable.center.y); + self.detailImgView.center = CGPointMake(self.detailImgView.center.x, self.tipLable.center.y); +} + +#pragma mark - Getter + +- (UIImageView *)tipImgView { + if (!_tipImgView) { + _tipImgView = [[UIImageView alloc] init]; + _tipImgView.contentMode = UIViewContentModeScaleAspectFit; + _tipImgView.image = [UIImage tz_imageNamedFromMyBundle:@"tip"]; + } + return _tipImgView; +} + +- (UILabel *)tipLable { + if (!_tipLable) { + _tipLable = [[UILabel alloc] init]; + NSString *appName = [TZCommonTools tz_getAppName]; + _tipLable.text = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Allow %@ to access your all photos"], appName]; + _tipLable.numberOfLines = 0; + _tipLable.font = [UIFont systemFontOfSize:14]; + _tipLable.textColor = [UIColor colorWithRed:0.40 green:0.40 blue:0.40 alpha:1.0]; + } + return _tipLable; +} + +- (UIImageView *)detailImgView { + if (!_detailImgView) { + _detailImgView = [[UIImageView alloc] init]; + _detailImgView.contentMode = UIViewContentModeScaleAspectFit; + _detailImgView.image = [UIImage tz_imageNamedFromMyBundle:@"right_arrow"]; + } + return _detailImgView; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.h b/TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.h new file mode 100644 index 0000000..4ebb192 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.h @@ -0,0 +1,16 @@ +// +// TZGifPhotoPreviewController.h +// TZImagePickerController +// +// Created by ttouch on 2016/12/13. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import + +@class TZAssetModel; +@interface TZGifPhotoPreviewController : UIViewController + +@property (nonatomic, strong) TZAssetModel *model; + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.m b/TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.m new file mode 100644 index 0000000..26c1a79 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZGifPhotoPreviewController.m @@ -0,0 +1,173 @@ +// +// TZGifPhotoPreviewController.m +// TZImagePickerController +// +// Created by ttouch on 2016/12/13. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "TZGifPhotoPreviewController.h" +#import "TZImagePickerController.h" +#import "TZAssetModel.h" +#import "UIView+TZLayout.h" +#import "TZPhotoPreviewCell.h" +#import "TZImageManager.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +@interface TZGifPhotoPreviewController () { + UIView *_toolBar; + UIButton *_doneButton; + UIProgressView *_progress; + + TZPhotoPreviewView *_previewView; + + UIStatusBarStyle _originStatusBarStyle; +} +@property (assign, nonatomic) BOOL needShowStatusBar; +@end + +@implementation TZGifPhotoPreviewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.needShowStatusBar = ![UIApplication sharedApplication].statusBarHidden; + self.view.backgroundColor = [UIColor blackColor]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc) { + self.navigationItem.title = [NSString stringWithFormat:@"GIF %@",tzImagePickerVc.previewBtnTitleStr]; + } + [self configPreviewView]; + [self configBottomToolBar]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + _originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle; + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + if (self.needShowStatusBar) { + [UIApplication sharedApplication].statusBarHidden = NO; + } + [UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle; +} + +- (void)configPreviewView { + _previewView = [[TZPhotoPreviewView alloc] initWithFrame:CGRectZero]; + _previewView.model = self.model; + __weak typeof(self) weakSelf = self; + [_previewView setSingleTapGestureBlock:^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf signleTapAction]; + }]; + [self.view addSubview:_previewView]; +} + +- (void)configBottomToolBar { + _toolBar = [[UIView alloc] initWithFrame:CGRectZero]; + CGFloat rgb = 34 / 255.0; + _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7]; + + _doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _doneButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc) { + [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal]; + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal]; + } else { + [_doneButton setTitle:[NSBundle tz_localizedStringForKey:@"Done"] forState:UIControlStateNormal]; + [_doneButton setTitleColor:[UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0] forState:UIControlStateNormal]; + } + [_toolBar addSubview:_doneButton]; + + UILabel *byteLabel = [[UILabel alloc] init]; + byteLabel.textColor = [UIColor whiteColor]; + byteLabel.font = [UIFont systemFontOfSize:13]; + byteLabel.frame = CGRectMake(10, 0, 100, 44); + [[TZImageManager manager] getPhotosBytesWithArray:@[_model] completion:^(NSString *totalBytes) { + byteLabel.text = totalBytes; + }]; + [_toolBar addSubview:byteLabel]; + + [self.view addSubview:_toolBar]; + + if (tzImagePickerVc.gifPreviewPageUIConfigBlock) { + tzImagePickerVc.gifPreviewPageUIConfigBlock(_toolBar, _doneButton); + } +} + +- (UIStatusBarStyle)preferredStatusBarStyle { + TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController; + if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) { + return tzImagePicker.statusBarStyle; + } + return [super preferredStatusBarStyle]; +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + _previewView.frame = self.view.bounds; + _previewView.scrollView.frame = self.view.bounds; + CGFloat toolBarHeight = 44 + [TZCommonTools tz_safeAreaInsets].bottom; + _toolBar.frame = CGRectMake(0, self.view.tz_height - toolBarHeight, self.view.tz_width, toolBarHeight); + [_doneButton sizeToFit]; + _doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, MAX(44, _doneButton.tz_width), 44); + + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc.gifPreviewPageDidLayoutSubviewsBlock) { + tzImagePickerVc.gifPreviewPageDidLayoutSubviewsBlock(_toolBar, _doneButton); + } +} + +#pragma mark - Click Event + +- (void)signleTapAction { + _toolBar.hidden = !_toolBar.isHidden; + [self.navigationController setNavigationBarHidden:_toolBar.isHidden]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (_toolBar.isHidden) { + [UIApplication sharedApplication].statusBarHidden = YES; + } else if (tzImagePickerVc.needShowStatusBar) { + [UIApplication sharedApplication].statusBarHidden = NO; + } +} + +- (void)doneButtonClick { + if (self.navigationController) { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + if (imagePickerVc.autoDismiss) { + [self.navigationController dismissViewControllerAnimated:YES completion:^{ + [self callDelegateMethod]; + }]; + } else { + [self callDelegateMethod]; + } + } else { + [self dismissViewControllerAnimated:YES completion:^{ + [self callDelegateMethod]; + }]; + } +} + +- (void)callDelegateMethod { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + UIImage *animatedImage = _previewView.imageView.image; + if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingGifImage:sourceAssets:)]) { + [imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingGifImage:animatedImage sourceAssets:_model.asset]; + } + if (imagePickerVc.didFinishPickingGifImageHandle) { + imagePickerVc.didFinishPickingGifImageHandle(animatedImage,_model.asset); + } +} + +#pragma clang diagnostic pop + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZImageCropManager.h b/TZImagePickerController/TZImagePickerController/TZImageCropManager.h new file mode 100644 index 0000000..9dc1cc1 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImageCropManager.h @@ -0,0 +1,39 @@ +// +// TZImageCropManager.h +// TZImagePickerController +// +// Created by 谭真 on 2016/12/5. +// Copyright © 2016年 谭真. All rights reserved. +// 图片裁剪管理类 + +#import +#import + +@interface TZImageCropManager : NSObject + +/// 裁剪框背景的处理 ++ (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView needCircleCrop:(BOOL)needCircleCrop; + +/* + 1.7.2 为了解决多位同学对于图片裁剪的需求,我这两天有空便在研究图片裁剪 + 幸好有tuyou的PhotoTweaks库做参考,裁剪的功能实现起来简单许多 + 该方法和其内部引用的方法基本来自于tuyou的PhotoTweaks库,我做了稍许删减和修改 + 感谢tuyou同学在github开源了优秀的裁剪库PhotoTweaks,表示感谢 + PhotoTweaks库的github链接:https://github.com/itouch2/PhotoTweaks + */ +/// 获得裁剪后的图片 ++ (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView; + +/// 获取圆形图片 ++ (UIImage *)circularClipImage:(UIImage *)image; + +@end + + +/// 该分类的代码来自SDWebImage:https://github.com/rs/SDWebImage +/// 为了防止冲突,我将分类名字和方法名字做了修改 +@interface UIImage (TZGif) + ++ (UIImage *)sd_tz_animatedGIFWithData:(NSData *)data; + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZImageCropManager.m b/TZImagePickerController/TZImagePickerController/TZImageCropManager.m new file mode 100644 index 0000000..b3a21a8 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImageCropManager.m @@ -0,0 +1,199 @@ +// +// TZImageCropManager.m +// TZImagePickerController +// +// Created by 谭真 on 2016/12/5. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "TZImageCropManager.h" +#import "UIView+TZLayout.h" +#import +#import "TZImageManager.h" +#import "TZImagePickerController.h" + +@implementation TZImageCropManager + +/// 裁剪框背景的处理 ++ (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView needCircleCrop:(BOOL)needCircleCrop { + UIBezierPath *path= [UIBezierPath bezierPathWithRect:[UIScreen mainScreen].bounds]; + CAShapeLayer *layer = [CAShapeLayer layer]; + if (needCircleCrop) { // 圆形裁剪框 + [path appendPath:[UIBezierPath bezierPathWithRoundedRect:cropRect cornerRadius:cropRect.size.width / 2]]; + } else { // 矩形裁剪框 + [path appendPath:[UIBezierPath bezierPathWithRect:cropRect]]; + } + layer.path = path.CGPath; + layer.fillRule = kCAFillRuleEvenOdd; + layer.fillColor = [[UIColor blackColor] CGColor]; + layer.opacity = 0.5; + [view.layer addSublayer:layer]; +} + +/// 获得裁剪后的图片 ++ (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView { + CGAffineTransform transform = CGAffineTransformIdentity; + // 平移的处理 + CGRect imageViewRect = [imageView convertRect:imageView.bounds toView:containerView]; + CGPoint point = CGPointMake(imageViewRect.origin.x + imageViewRect.size.width / 2, imageViewRect.origin.y + imageViewRect.size.height / 2); + CGFloat xMargin = containerView.tz_width - CGRectGetMaxX(rect) - rect.origin.x; + CGPoint zeroPoint = CGPointMake((CGRectGetWidth(containerView.frame) - xMargin) / 2, containerView.center.y); + CGPoint translation = CGPointMake(point.x - zeroPoint.x, point.y - zeroPoint.y); + transform = CGAffineTransformTranslate(transform, translation.x, translation.y); + // 缩放的处理 + transform = CGAffineTransformScale(transform, zoomScale, zoomScale); + + CGImageRef imageRef = [self newTransformedImage:transform + sourceImage:imageView.image.CGImage + sourceSize:imageView.image.size + outputWidth:rect.size.width * [UIScreen mainScreen].scale + cropSize:rect.size + imageViewSize:imageView.frame.size]; + UIImage *cropedImage = [UIImage imageWithCGImage:imageRef]; + cropedImage = [[TZImageManager manager] fixOrientation:cropedImage]; + CGImageRelease(imageRef); + return cropedImage; +} + ++ (CGImageRef)newTransformedImage:(CGAffineTransform)transform sourceImage:(CGImageRef)sourceImage sourceSize:(CGSize)sourceSize outputWidth:(CGFloat)outputWidth cropSize:(CGSize)cropSize imageViewSize:(CGSize)imageViewSize { + CGImageRef source = [self newScaledImage:sourceImage toSize:sourceSize]; + + CGFloat aspect = cropSize.height/cropSize.width; + CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect); + + CGContextRef context = CGBitmapContextCreate(NULL, outputSize.width, outputSize.height, CGImageGetBitsPerComponent(source), 0, CGImageGetColorSpace(source), CGImageGetBitmapInfo(source)); + CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]); + CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height)); + + CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width / cropSize.width, outputSize.height / cropSize.height); + uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height / 2.0); + uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0); + CGContextConcatCTM(context, uiCoords); + + CGContextConcatCTM(context, transform); + CGContextScaleCTM(context, 1.0, -1.0); + + CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2, -imageViewSize.height/2.0, imageViewSize.width, imageViewSize.height), source); + CGImageRef resultRef = CGBitmapContextCreateImage(context); + CGContextRelease(context); + CGImageRelease(source); + return resultRef; +} + ++ (CGImageRef)newScaledImage:(CGImageRef)source toSize:(CGSize)size { + CGSize srcSize = size; + CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + CGColorSpaceRelease(rgbColorSpace); + + CGContextSetInterpolationQuality(context, kCGInterpolationNone); + CGContextTranslateCTM(context, size.width/2, size.height/2); + + CGContextDrawImage(context, CGRectMake(-srcSize.width/2, -srcSize.height/2, srcSize.width, srcSize.height), source); + + CGImageRef resultRef = CGBitmapContextCreateImage(context); + CGContextRelease(context); + return resultRef; +} + +/// 获取圆形图片 ++ (UIImage *)circularClipImage:(UIImage *)image { + UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale); + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); + CGContextAddEllipseInRect(ctx, rect); + CGContextClip(ctx); + + [image drawInRect:rect]; + UIImage *circleImage = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + return circleImage; +} + +@end + + +@implementation UIImage (TZGif) + ++ (UIImage *)sd_tz_animatedGIFWithData:(NSData *)data { + if (!data) { + return nil; + } + + CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); + + size_t count = CGImageSourceGetCount(source); + + UIImage *animatedImage; + + if (count <= 1) { + animatedImage = [[UIImage alloc] initWithData:data]; + } + else { + // images数组过大时内存会飙升,在这里限制下最大count + NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 50; + NSInteger interval = MAX((count + maxCount / 2) / maxCount, 1); + + NSMutableArray *images = [NSMutableArray array]; + + NSTimeInterval duration = 0.0f; + + for (size_t i = 0; i < count; i+=interval) { + CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); + if (!image) { + continue; + } + + duration += [self sd_frameDurationAtIndex:i source:source] * MIN(interval, 3); + + [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; + + CGImageRelease(image); + } + + if (!duration) { + duration = (1.0f / 10.0f) * count; + } + + animatedImage = [UIImage animatedImageWithImages:images duration:duration]; + } + + CFRelease(source); + + return animatedImage; +} + ++ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { + float frameDuration = 0.1f; + CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); + NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; + NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; + + NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; + if (delayTimeUnclampedProp) { + frameDuration = [delayTimeUnclampedProp floatValue]; + } + else { + + NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; + if (delayTimeProp) { + frameDuration = [delayTimeProp floatValue]; + } + } + + // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. + // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify + // a duration of <= 10 ms. See and + // for more information. + + if (frameDuration < 0.011f) { + frameDuration = 0.100f; + } + + CFRelease(cfFrameProperties); + return frameDuration; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZImageManager.h b/TZImagePickerController/TZImagePickerController/TZImageManager.h new file mode 100755 index 0000000..5c11e53 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImageManager.h @@ -0,0 +1,148 @@ +// +// TZImageManager.h +// TZImagePickerController +// +// Created by 谭真 on 16/1/4. +// Copyright © 2016年 谭真. All rights reserved. +// 图片资源获取管理类 + +#import +#import +#import +#import +#import "TZAssetModel.h" + +@class TZAlbumModel,TZAssetModel; +@protocol TZImagePickerControllerDelegate; +@interface TZImageManager : NSObject + +@property (nonatomic, strong) PHCachingImageManager *cachingImageManager; + ++ (instancetype)manager NS_SWIFT_NAME(default()); ++ (void)deallocManager; + +@property (weak, nonatomic) id pickerDelegate; + +@property (nonatomic, assign) BOOL shouldFixOrientation; + +@property (nonatomic, assign) BOOL isPreviewNetworkImage; + +/// Default is 600px / 默认600像素宽 +@property (nonatomic, assign) CGFloat photoPreviewMaxWidth; +/// The pixel width of output image, Default is 828px / 导出图片的宽度,默认828像素宽 +@property (nonatomic, assign) CGFloat photoWidth; + +/// Default is 4, Use in photos collectionView in TZPhotoPickerController +/// 默认4列, TZPhotoPickerController中的照片collectionView +@property (nonatomic, assign) NSInteger columnNumber; + +/// Sort photos ascending by modificationDate,Default is YES +/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个 +@property (nonatomic, assign) BOOL sortAscendingByModificationDate; + +/// Minimum selectable photo width, Default is 0 +/// 最小可选中的图片宽度,默认是0,小于这个宽度的图片不可选中 +@property (nonatomic, assign) NSInteger minPhotoWidthSelectable; +@property (nonatomic, assign) NSInteger minPhotoHeightSelectable; +@property (nonatomic, assign) BOOL hideWhenCanNotSelect; + +/// Return YES if Authorized 返回YES如果得到了授权 +- (BOOL)authorizationStatusAuthorized; +- (void)requestAuthorizationWithCompletion:(void (^)(void))completion; +- (BOOL)isPHAuthorizationStatusLimited; + +/// Get Album 获得相册/相册数组 +- (void)getCameraRollAlbumWithFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion; +- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion __attribute__((deprecated("Use -getCameraRollAlbumWithFetchAssets:completion:. You can config allowPickingImage、allowPickingVideo by TZImagePickerConfig"))); +- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray *models))completion __attribute__((deprecated("Use -getAllAlbumsWithFetchAssets:completion:. You can config allowPickingImage、allowPickingVideo by TZImagePickerConfig"))); +- (void)getAllAlbumsWithFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray *models))completion; + +/// Get Assets 获得Asset数组 +- (void)getAssetsFromFetchResult:(PHFetchResult *)result completion:(void (^)(NSArray *models))completion; +- (void)getAssetsFromFetchResult:(PHFetchResult *)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray *models))completion __attribute__((deprecated("Use -getAssetsFromFetchResult:completion:. You can config allowPickingImage、allowPickingVideo by TZImagePickerConfig"))); +- (void)getAssetFromFetchResult:(PHFetchResult *)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *model))completion __attribute__((deprecated("Use -getAssetFromFetchResult:atIndex:completion:. You can config allowPickingImage、allowPickingVideo by TZImagePickerConfig"))); +- (void)getAssetFromFetchResult:(PHFetchResult *)result atIndex:(NSInteger)index completion:(void (^)(TZAssetModel *model))completion; +/** + * 从FetchResult中获取更多资源 + * @param result PHFetchResult对象 + * @param currentCount 当前已加载的数量 + * @param completion 完成回调,返回新加载的资源数组 + */ +- (void)getMoreAssetsFromFetchResult:(PHFetchResult *)result + currentCount:(NSInteger)currentCount + completion:(void (^)(NSArray *models))completion; +/// Get photo 获得照片 +- (PHImageRequestID)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *postImage))completion; + +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion; +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion; +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed; +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed; +- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler; + +/// Get full Image 获取原图 +/// 如下两个方法completion一般会调多次,一般会先返回缩略图,再返回原图(详见方法内部使用的系统API的说明),如果info[PHImageResultIsDegradedKey] 为 YES,则表明当前返回的是缩略图,否则是原图。 +- (PHImageRequestID)getOriginalPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion; +- (PHImageRequestID)getOriginalPhotoWithAsset:(PHAsset *)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion; +- (PHImageRequestID)getOriginalPhotoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion; +// 该方法中,completion只会走一次 +- (PHImageRequestID)getOriginalPhotoDataWithAsset:(PHAsset *)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion; +- (PHImageRequestID)getOriginalPhotoDataWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion; + +/// Get Image For VideoURL +- (UIImage *)getImageWithVideoURL:(NSURL *)videoURL; + +/// Save photo 保存照片 +- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(PHAsset *asset, NSError *error))completion; +- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion; +- (void)savePhotoWithImage:(UIImage *)image meta:(NSDictionary *)meta location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion; + +/// Save video 保存视频 +- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(PHAsset *asset, NSError *error))completion; +- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion; + +/// Get video 获得视频 +- (void)getVideoWithAsset:(PHAsset *)asset completion:(void (^)(AVPlayerItem * playerItem, NSDictionary * info))completion; +- (void)getVideoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion; + +/// Export video 导出视频 presetName: 预设名字,默认值是AVAssetExportPreset640x480 +- (void)getVideoOutputPathWithAsset:(PHAsset *)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure; +- (void)getVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure; +- (void)getVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName timeRange:(CMTimeRange)timeRange success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure; +/// 新的导出视频API,解决iOS14 iCloud视频导出失败的问题,未大量测试,请大家多多测试,有问题群里反馈 +- (void)requestVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure; +/// 得到视频原始文件地址 +- (void)requestVideoURLWithAsset:(PHAsset *)asset success:(void (^)(NSURL *videoURL))success failure:(void (^)(NSDictionary* info))failure; + +/// Get photo bytes 获得一组照片的大小 +- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion; + +- (BOOL)isCameraRollAlbum:(PHAssetCollection *)metadata; + +/// 检查照片大小是否满足最小要求 +- (BOOL)isPhotoSelectableWithAsset:(PHAsset *)asset; + +/// 检查照片能否被选中 +- (BOOL)isAssetCannotBeSelected:(PHAsset *)asset; + +/// 修正图片转向 +- (UIImage *)fixOrientation:(UIImage *)aImage; + +/// 获取asset的资源类型 +- (TZAssetModelMediaType)getAssetType:(PHAsset *)asset; +/// 缩放图片至新尺寸 +- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size; + +/// 判断asset是否是视频 +- (BOOL)isVideo:(PHAsset *)asset; + +/// for TZImagePreviewController +- (NSString *)getNewTimeFromDurationSecond:(NSInteger)duration; + +- (TZAssetModel *)createModelWithAsset:(PHAsset *)asset; + +@end + +//@interface TZSortDescriptor : NSSortDescriptor +// +//@end diff --git a/TZImagePickerController/TZImagePickerController/TZImageManager.m b/TZImagePickerController/TZImagePickerController/TZImageManager.m new file mode 100755 index 0000000..74120af --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImageManager.m @@ -0,0 +1,1163 @@ +// +// TZImageManager.m +// TZImagePickerController +// +// Created by 谭真 on 16/1/4. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "TZImageManager.h" +#import "TZAssetModel.h" +#import "TZImagePickerController.h" +#import + +@interface TZImageManager () +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +@property (nonatomic, assign) NSInteger pageSize; +@property (nonatomic, assign) BOOL isLoadingMore; +@end + +@implementation TZImageManager + +CGSize AssetGridThumbnailSize; +CGFloat TZScreenWidth; +CGFloat TZScreenScale; + +static TZImageManager *manager; +static dispatch_once_t onceToken; + ++ (instancetype)manager { + dispatch_once(&onceToken, ^{ + manager = [[self alloc] init]; + // manager.cachingImageManager = [[PHCachingImageManager alloc] init]; + // manager.cachingImageManager.allowsCachingHighQualityImages = YES; + + [manager configTZScreenWidth]; + }); + return manager; +} + ++ (void)deallocManager { + onceToken = 0; + manager = nil; +} + +- (void)setPhotoWidth:(CGFloat)photoWidth { + _photoWidth = photoWidth; + TZScreenWidth = photoWidth / 2; +} + +- (void)setColumnNumber:(NSInteger)columnNumber { + [self configTZScreenWidth]; + + _columnNumber = columnNumber; + CGFloat margin = 4; + CGFloat itemWH = (TZScreenWidth - 2 * margin - 4) / columnNumber - margin; + AssetGridThumbnailSize = CGSizeMake(itemWH * TZScreenScale, itemWH * TZScreenScale); +} + +- (void)configTZScreenWidth { + TZScreenWidth = [UIScreen mainScreen].bounds.size.width; + // 测试发现,如果scale在plus真机上取到3.0,内存会增大特别多。故这里写死成2.0 + TZScreenScale = 2.0; + if (TZScreenWidth > 700) { + TZScreenScale = 1.5; + } +} + +- (BOOL)isPHAuthorizationStatusLimited { + if (@available(iOS 14,*)) { + NSInteger status = [PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelReadWrite]; + if (status == PHAuthorizationStatusLimited) { + return YES; + } + } + return NO; +} + +/// Return YES if Authorized 返回YES如果得到了授权 +- (BOOL)authorizationStatusAuthorized { + if (self.isPreviewNetworkImage) { + return YES; + } + NSInteger status = [PHPhotoLibrary authorizationStatus]; + if (status == 0) { + /** + * 当某些情况下AuthorizationStatus == AuthorizationStatusNotDetermined时,无法弹出系统首次使用的授权alertView,系统应用设置里亦没有相册的设置,此时将无法使用,故作以下操作,弹出系统首次使用的授权alertView + */ + [self requestAuthorizationWithCompletion:nil]; + } + + return status == 3; +} + +- (void)requestAuthorizationWithCompletion:(void (^)(void))completion { + void (^callCompletionBlock)(void) = ^(){ + dispatch_async(dispatch_get_main_queue(), ^{ + if (completion) { + completion(); + } + }); + }; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { + callCompletionBlock(); + }]; + }); +} + +#pragma mark - Get Album + +- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion { + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + config.allowPickingVideo = allowPickingVideo; + config.allowPickingImage = allowPickingImage; + [self getCameraRollAlbumWithFetchAssets:needFetchAssets completion:completion]; +} + +/// Get Album 获得相册/相册数组 +- (void)getCameraRollAlbumWithFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion { + __block TZAlbumModel *model; + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + PHFetchOptions *option = [[PHFetchOptions alloc] init]; + if (!config.allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage]; + if (!config.allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", + PHAssetMediaTypeVideo]; + // option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]]; + if (!self.sortAscendingByModificationDate) { + option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]]; + } + PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAny options:nil]; + for (PHAssetCollection *collection in smartAlbums) { + // 有可能是PHCollectionList类的的对象,过滤掉 + if (![collection isKindOfClass:[PHAssetCollection class]]) continue; + // 过滤空相册 + if (collection.estimatedAssetCount <= 0) continue; + if ([self isCameraRollAlbum:collection]) { + PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option]; + model = [self modelWithResult:fetchResult collection:collection isCameraRoll:YES needFetchAssets:needFetchAssets options:option]; + if (completion) completion(model); + break; + } + } +} + +- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray *))completion { + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + config.allowPickingVideo = allowPickingVideo; + config.allowPickingImage = allowPickingImage; + [self getAllAlbumsWithFetchAssets:needFetchAssets completion:completion]; +} + +- (void)getAllAlbumsWithFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray *))completion { + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + NSMutableArray *albumArr = [NSMutableArray array]; + PHFetchOptions *option = [[PHFetchOptions alloc] init]; + if (!config.allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage]; + if (!config.allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", + PHAssetMediaTypeVideo]; + // option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]]; + if (!self.sortAscendingByModificationDate) { + option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]]; + } + // 我的照片流 1.6.10重新加入.. + PHFetchResult *myPhotoStreamAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumMyPhotoStream options:nil]; + PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAny options:nil]; + PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil]; + PHFetchResult *syncedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil]; + PHFetchResult *sharedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumCloudShared options:nil]; + NSArray *allAlbums = @[myPhotoStreamAlbum,smartAlbums,topLevelUserCollections,syncedAlbums,sharedAlbums]; + for (PHFetchResult *fetchResult in allAlbums) { + for (PHAssetCollection *collection in fetchResult) { + // 有可能是PHCollectionList类的的对象,过滤掉 + if (![collection isKindOfClass:[PHAssetCollection class]]) continue; + // 过滤空相册 + if (collection.estimatedAssetCount <= 0 && ![self isCameraRollAlbum:collection]) continue; + PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option]; + if (fetchResult.count < 1 && ![self isCameraRollAlbum:collection]) continue; + + if ([self.pickerDelegate respondsToSelector:@selector(isAlbumCanSelect:result:)]) { + if (![self.pickerDelegate isAlbumCanSelect:collection.localizedTitle result:fetchResult]) { + continue; + } + } + + if (collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumAllHidden) continue; + if (collection.assetCollectionSubtype == 1000000201) continue; //『最近删除』相册 + if ([self isCameraRollAlbum:collection]) { + [albumArr insertObject:[self modelWithResult:fetchResult collection:collection isCameraRoll:YES needFetchAssets:needFetchAssets options:option] atIndex:0]; + } else { + [albumArr addObject:[self modelWithResult:fetchResult collection:collection isCameraRoll:NO needFetchAssets:needFetchAssets options:option]]; + } + } + } + if (completion) { + completion(albumArr); + } +} + +#pragma mark - Get Assets + +/// Get Assets 获得照片数组 +- (void)getAssetsFromFetchResult:(PHFetchResult *)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray *))completion { + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + config.allowPickingVideo = allowPickingVideo; + config.allowPickingImage = allowPickingImage; + return [self getAssetsFromFetchResult:result completion:completion]; +} + +- (void)getAssetsFromFetchResult:(PHFetchResult *)result completion:(void (^)(NSArray *))completion { + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + self.pageSize = 3000; // 设置每页加载数量 + + // 如果总数小于一页,直接全部加载 + if (result.count <= self.pageSize) { + NSMutableArray *photoArr = [NSMutableArray array]; + [result enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL * _Nonnull stop) { + TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage]; + if (model) { + [photoArr addObject:model]; + } + }]; + if (completion) completion(photoArr); + return; + } + + // 加载最新的一页数据 + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSMutableArray *photoArr = [NSMutableArray array]; + NSInteger count = result.count; + NSInteger offset = MAX(count - self.pageSize, 0); + + // 从最新的照片开始遍历 + for (NSInteger i = count - 1; i >= offset; i--) { + @autoreleasepool { + PHAsset *asset = result[i]; + TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage]; + if (model) { + [photoArr insertObject:model atIndex:0]; + } + } + } + + dispatch_async(dispatch_get_main_queue(), ^{ + if (completion) completion(photoArr); + }); + }); +} + +/// Get asset at index 获得下标为index的单个照片 +/// if index beyond bounds, return nil in callback 如果索引越界, 在回调中返回 nil +- (void)getAssetFromFetchResult:(PHFetchResult *)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *))completion { + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + config.allowPickingVideo = allowPickingVideo; + config.allowPickingImage = allowPickingImage; + [self getAssetFromFetchResult:result atIndex:index allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage completion:completion]; +} + +- (void)getAssetFromFetchResult:(PHFetchResult *)result atIndex:(NSInteger)index completion:(void (^)(TZAssetModel *))completion { + PHAsset *asset; + @try { + asset = result[index]; + } + @catch (NSException* e) { + if (completion) completion(nil); + return; + } + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage]; + if (completion) completion(model); +} + +- (TZAssetModel *)assetModelWithAsset:(PHAsset *)asset allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage { + BOOL canSelect = YES; + if ([self.pickerDelegate respondsToSelector:@selector(isAssetCanSelect:)]) { + canSelect = [self.pickerDelegate isAssetCanSelect:asset]; + } + if ([self.pickerDelegate respondsToSelector:@selector(isAssetCanBeDisplayed:)]){ + canSelect = [self.pickerDelegate isAssetCanBeDisplayed:asset]; + } + + if (!canSelect) return nil; + + TZAssetModel *model; + TZAssetModelMediaType type = [self getAssetType:asset]; + if (!allowPickingVideo && type == TZAssetModelMediaTypeVideo) return nil; + if (!allowPickingImage && type == TZAssetModelMediaTypePhoto) return nil; + if (!allowPickingImage && type == TZAssetModelMediaTypePhotoGif) return nil; + + PHAsset *phAsset = (PHAsset *)asset; + if (self.hideWhenCanNotSelect) { + // 过滤掉尺寸不满足要求的图片 + if (![self isPhotoSelectableWithAsset:phAsset]) { + return nil; + } + } + NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",phAsset.duration] : @""; + timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue]; + model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength]; + return model; +} + +- (TZAssetModelMediaType)getAssetType:(PHAsset *)asset { + TZAssetModelMediaType type = TZAssetModelMediaTypePhoto; + PHAsset *phAsset = (PHAsset *)asset; + if (phAsset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo; + else if (phAsset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio; + else if (phAsset.mediaType == PHAssetMediaTypeImage) { + if (@available(iOS 9.1, *)) { + // if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive) type = TZAssetModelMediaTypeLivePhoto; + } + // Gif + if ([[phAsset valueForKey:@"filename"] hasSuffix:@"GIF"]) { + type = TZAssetModelMediaTypePhotoGif; + } + } + return type; +} + +- (NSString *)getNewTimeFromDurationSecond:(NSInteger)duration { + NSString *newTime; + if (duration < 10) { + newTime = [NSString stringWithFormat:@"0:0%zd",duration]; + } else if (duration < 60) { + newTime = [NSString stringWithFormat:@"0:%zd",duration]; + } else { + NSInteger min = duration / 60; + NSInteger sec = duration - (min * 60); + if (sec < 10) { + newTime = [NSString stringWithFormat:@"%zd:0%zd",min,sec]; + } else { + newTime = [NSString stringWithFormat:@"%zd:%zd",min,sec]; + } + } + return newTime; +} + +/// Get photo bytes 获得一组照片的大小 +- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion { + if (!photos || !photos.count) { + if (completion) completion(@"0B"); + return; + } + + __block NSInteger dataLength = 0; + __block NSInteger assetCount = 0; + + for (NSInteger i = 0; i < photos.count; i++) { + TZAssetModel *model = photos[i]; + + if (model.type == TZAssetModelMediaTypeVideo) { + PHVideoRequestOptions *videoOptions = [[PHVideoRequestOptions alloc] init]; + videoOptions.networkAccessAllowed = YES; + + [[PHImageManager defaultManager] requestAVAssetForVideo:model.asset options:videoOptions resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) { + if ([asset isKindOfClass:[AVURLAsset class]]) { + NSNumber *fileSize = nil; + [[(AVURLAsset *)asset URL] getResourceValue:&fileSize forKey:NSURLFileSizeKey error:nil]; + dataLength += [fileSize longLongValue]; + } + assetCount++; + if (assetCount >= photos.count) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *bytes = [self getBytesFromDataLength:dataLength]; + if (completion) completion(bytes); + }); + } + }]; + } else { + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + options.resizeMode = PHImageRequestOptionsResizeModeFast; + options.networkAccessAllowed = YES; + if (model.type == TZAssetModelMediaTypePhotoGif) { + options.version = PHImageRequestOptionsVersionOriginal; + } + + [[PHImageManager defaultManager] requestImageDataForAsset:model.asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { + dataLength += imageData.length; + assetCount++; + if (assetCount >= photos.count) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *bytes = [self getBytesFromDataLength:dataLength]; + if (completion) completion(bytes); + }); + } + }]; + } + } +} + +- (NSString *)getBytesFromDataLength:(NSInteger)dataLength { + NSString *bytes; + if (dataLength >= 0.1 * (1024 * 1024)) { + bytes = [NSString stringWithFormat:@"%0.1fM",dataLength/1024/1024.0]; + } else if (dataLength >= 1024) { + bytes = [NSString stringWithFormat:@"%0.0fK",dataLength/1024.0]; + } else { + bytes = [NSString stringWithFormat:@"%zdB",dataLength]; + } + return bytes; +} + +#pragma mark - Get Photo + +/// Get photo 获得照片本身 +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion { + return [self getPhotoWithAsset:asset completion:completion progressHandler:nil networkAccessAllowed:YES]; +} + +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion { + return [self getPhotoWithAsset:asset photoWidth:photoWidth completion:completion progressHandler:nil networkAccessAllowed:YES]; +} + +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed { + CGFloat fullScreenWidth = TZScreenWidth; + if (_photoPreviewMaxWidth > 0 && fullScreenWidth > _photoPreviewMaxWidth) { + fullScreenWidth = _photoPreviewMaxWidth; + } + return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:progressHandler networkAccessAllowed:networkAccessAllowed]; +} + +- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler { + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (progressHandler) { + progressHandler(progress, error, stop, info); + } + }); + }; + options.networkAccessAllowed = YES; + options.resizeMode = PHImageRequestOptionsResizeModeFast; + int32_t imageRequestID = [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { + if (completion) completion(imageData,dataUTI,orientation,info); + }]; + return imageRequestID; +} + +- (PHImageRequestID)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed { + CGSize imageSize; + if (photoWidth < TZScreenWidth && photoWidth < _photoPreviewMaxWidth) { + imageSize = AssetGridThumbnailSize; + } else { + PHAsset *phAsset = (PHAsset *)asset; + CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight; + CGFloat pixelWidth = photoWidth * TZScreenScale; + // 超宽图片 + if (aspectRatio > 1.8) { + pixelWidth = pixelWidth * aspectRatio; + } + // 超高图片 + if (aspectRatio < 0.2) { + pixelWidth = pixelWidth * 0.5; + } + CGFloat pixelHeight = pixelWidth / aspectRatio; + imageSize = CGSizeMake(pixelWidth, pixelHeight); + } + + // 修复获取图片时出现的瞬间内存过高问题 + // 下面两行代码,来自hsjcom,他的github是:https://github.com/hsjcom 表示感谢 + PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init]; + option.resizeMode = PHImageRequestOptionsResizeModeFast; + int32_t imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) { + BOOL cancelled = [[info objectForKey:PHImageCancelledKey] boolValue]; + if (!cancelled && result) { + result = [self fixOrientation:result]; + if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]); + } + // Download image from iCloud / 从iCloud下载图片 + if ([info objectForKey:PHImageResultIsInCloudKey] && !result && networkAccessAllowed) { + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (progressHandler) { + progressHandler(progress, error, stop, info); + } + }); + }; + options.networkAccessAllowed = YES; + options.resizeMode = PHImageRequestOptionsResizeModeFast; + [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { + UIImage *resultImage = [UIImage imageWithData:imageData]; + if (![TZImagePickerConfig sharedInstance].notScaleImage) { + resultImage = [self scaleImage:resultImage toSize:imageSize]; + } + if (!resultImage && result) { + resultImage = result; + } + resultImage = [self fixOrientation:resultImage]; + if (completion) completion(resultImage,info,NO); + }]; + } + }]; + return imageRequestID; +} + +/// Get postImage / 获取封面图 +- (PHImageRequestID)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *))completion { + id asset = [model.result lastObject]; + if (!self.sortAscendingByModificationDate) { + asset = [model.result firstObject]; + } + if (!asset) { + return -1; + } + return [[TZImageManager manager] getPhotoWithAsset:asset photoWidth:80 completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + if (completion) completion(photo); + }]; +} + +/// Get Original Photo / 获取原图 +- (PHImageRequestID)getOriginalPhotoWithAsset:(PHAsset *)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion { + return [self getOriginalPhotoWithAsset:asset newCompletion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + if (completion) { + completion(photo,info); + } + }]; +} + +- (PHImageRequestID)getOriginalPhotoWithAsset:(PHAsset *)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion { + return [self getOriginalPhotoWithAsset:asset progressHandler:nil newCompletion:completion]; +} + +- (PHImageRequestID)getOriginalPhotoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion { + PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init]; + option.networkAccessAllowed = YES; + if (progressHandler) { + [option setProgressHandler:progressHandler]; + } + option.resizeMode = PHImageRequestOptionsResizeModeFast; + return [[PHImageManager defaultManager] requestImageDataForAsset:asset options:option resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) { + BOOL cancelled = [[info objectForKey:PHImageCancelledKey] boolValue]; + if (!cancelled && imageData) { + UIImage *result = [self fixOrientation:[UIImage imageWithData:imageData]]; + BOOL isDegraded = [[info objectForKey:PHImageResultIsDegradedKey] boolValue]; + if (completion) completion(result,info,isDegraded); + } + }]; +} + +- (PHImageRequestID)getOriginalPhotoDataWithAsset:(PHAsset *)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion { + return [self getOriginalPhotoDataWithAsset:asset progressHandler:nil completion:completion]; +} + +- (PHImageRequestID)getOriginalPhotoDataWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion { + PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init]; + option.networkAccessAllowed = YES; + if ([[asset valueForKey:@"filename"] hasSuffix:@"GIF"]) { + // if version isn't PHImageRequestOptionsVersionOriginal, the gif may cann't play + option.version = PHImageRequestOptionsVersionOriginal; + } + [option setProgressHandler:progressHandler]; + option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; + return [[PHImageManager defaultManager] requestImageDataForAsset:asset options:option resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { + BOOL cancelled = [[info objectForKey:PHImageCancelledKey] boolValue]; + if (!cancelled && imageData) { + if (completion) completion(imageData,info,NO); + } + }]; +} + +- (UIImage *)getImageWithVideoURL:(NSURL *)videoURL { + AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil]; + if (!asset) { + return nil; + } + AVAssetImageGenerator *generator =[[AVAssetImageGenerator alloc] initWithAsset:asset]; + generator.appliesPreferredTrackTransform = YES; + generator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels; + + CFTimeInterval time = 0.1; + CGImageRef imageRef = [generator copyCGImageAtTime:CMTimeMake(time, 60) actualTime:NULL error:nil]; + UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; + CGImageRelease(imageRef); + return image; +} + +#pragma mark - Save photo + +- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(PHAsset *asset, NSError *error))completion { + [self savePhotoWithImage:image location:nil completion:completion]; +} + +- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion { + __block NSString *localIdentifier = nil; + [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ + PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; + localIdentifier = request.placeholderForCreatedAsset.localIdentifier; + if (location) { + request.location = location; + } + request.creationDate = [NSDate date]; + } completionHandler:^(BOOL success, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (success && completion && localIdentifier) { + [self fetchAssetByIocalIdentifier:localIdentifier retryCount:10 completion:completion]; + } else { + if (error) { + NSLog(@"保存照片出错:%@",error.localizedDescription); + } + if (completion) { + completion(nil, error); + } + } + }); + }]; +} + +- (void)savePhotoWithImage:(UIImage *)image meta:(NSDictionary *)meta location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion { + NSData *imageData = UIImageJPEGRepresentation(image, 1.0f); + CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); + NSDateFormatter *formater = [[NSDateFormatter alloc] init]; + [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"]; + NSString *path = [NSTemporaryDirectory() stringByAppendingFormat:@"image-%@.jpg", [formater stringFromDate:[NSDate date]]]; + NSURL *tmpURL = [NSURL fileURLWithPath:path]; + CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)tmpURL, kUTTypeJPEG, 1, NULL); + CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)meta); + CGImageDestinationFinalize(destination); + CFRelease(source); + CFRelease(destination); + + __block NSString *localIdentifier = nil; + [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ + PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:tmpURL]; + localIdentifier = request.placeholderForCreatedAsset.localIdentifier; + if (location) { + request.location = location; + } + request.creationDate = [NSDate date]; + } completionHandler:^(BOOL success, NSError *error) { + [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (success && completion && localIdentifier) { + [self fetchAssetByIocalIdentifier:localIdentifier retryCount:10 completion:completion]; + } else { + if (error) { + NSLog(@"保存照片出错:%@",error.localizedDescription); + } + if (completion) { + completion(nil, error); + } + } + }); + }]; +} + +- (void)fetchAssetByIocalIdentifier:(NSString *)localIdentifier retryCount:(NSInteger)retryCount completion:(void (^)(PHAsset *asset, NSError *error))completion { + PHAsset *asset = [[PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil] firstObject]; + if (asset || retryCount <= 0) { + if (completion) { + completion(asset, nil); + } + return; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self fetchAssetByIocalIdentifier:localIdentifier retryCount:retryCount - 1 completion:completion]; + }); +} + +#pragma mark - Save video + +- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(PHAsset *asset, NSError *error))completion { + [self saveVideoWithUrl:url location:nil completion:completion]; +} + +- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(PHAsset *asset, NSError *error))completion { + __block NSString *localIdentifier = nil; + [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ + PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url]; + localIdentifier = request.placeholderForCreatedAsset.localIdentifier; + if (location) { + request.location = location; + } + request.creationDate = [NSDate date]; + } completionHandler:^(BOOL success, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (success && completion && localIdentifier) { + [self fetchAssetByIocalIdentifier:localIdentifier retryCount:10 completion:completion]; + } else { + if (error) { + NSLog(@"保存视频出错:%@",error.localizedDescription); + } + if (completion) { + completion(nil, error); + } + } + }); + }]; +} + +#pragma mark - Get Video + +/// Get Video / 获取视频 +- (void)getVideoWithAsset:(PHAsset *)asset completion:(void (^)(AVPlayerItem *, NSDictionary *))completion { + [self getVideoWithAsset:asset progressHandler:nil completion:completion]; +} + +- (void)getVideoWithAsset:(PHAsset *)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion { + PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init]; + option.networkAccessAllowed = YES; + option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (progressHandler) { + progressHandler(progress, error, stop, info); + } + }); + }; + [[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) { + if (completion) completion(playerItem,info); + }]; +} + +#pragma mark - Export video + +/// Export Video / 导出视频 +- (void)getVideoOutputPathWithAsset:(PHAsset *)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + [self getVideoOutputPathWithAsset:asset presetName:AVAssetExportPresetMediumQuality success:success failure:failure]; +} + +- (void)getVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + [self getVideoOutputPathWithAsset:asset presetName:presetName timeRange:kCMTimeRangeZero success:success failure:failure]; +} + +- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + [self startExportVideoWithVideoAsset:videoAsset timeRange:kCMTimeRangeZero presetName:presetName success:success failure:failure]; +} + +- (void)getVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName timeRange:(CMTimeRange)timeRange success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + if (@available(iOS 14.0, *)) { + [self requestVideoOutputPathWithAsset:asset presetName:presetName timeRange:timeRange success:success failure:failure]; + return; + } + [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:[self getVideoRequestOptions] resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){ + // NSLog(@"Info:\n%@",info); + AVURLAsset *videoAsset = (AVURLAsset*)avasset; + // NSLog(@"AVAsset URL: %@",myAsset.URL); + [self startExportVideoWithVideoAsset:videoAsset timeRange:timeRange presetName:presetName success:success failure:failure]; + }]; +} + +- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset timeRange:(CMTimeRange)timeRange presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + if (!presetName) { + presetName = AVAssetExportPresetMediumQuality; + } + // Find compatible presets by video asset. + NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset]; + // Begin to compress video + // Now we just compress to low resolution if it supports + // If you need to upload to the server, but server does't support to upload by streaming, + // You can compress the resolution to lower. Or you can support more higher resolution. + if ([presets containsObject:presetName]) { + AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:presetName]; + NSString *outputPath = [self getVideoOutputPath]; + + // Optimize for network use. + session.shouldOptimizeForNetworkUse = true; + if (!CMTimeRangeEqual(timeRange, kCMTimeRangeZero)) { + session.timeRange = timeRange; + } + + NSArray *supportedTypeArray = session.supportedFileTypes; + if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) { + session.outputFileType = AVFileTypeMPEG4; + } else if (supportedTypeArray.count == 0) { + if (failure) { + failure(@"该视频类型暂不支持导出", nil); + } + NSLog(@"No supported file types 视频类型暂不支持导出"); + return; + } else { + session.outputFileType = [supportedTypeArray objectAtIndex:0]; + if (videoAsset.URL && videoAsset.URL.lastPathComponent) { + outputPath = [outputPath stringByReplacingOccurrencesOfString:@".mp4" withString:[NSString stringWithFormat:@"-%@", videoAsset.URL.lastPathComponent]]; + } + } + // NSLog(@"video outputPath = %@",outputPath); + session.outputURL = [NSURL fileURLWithPath:outputPath]; + + if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) { + [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil]; + } + + if ([TZImagePickerConfig sharedInstance].needFixComposition) { + AVMutableVideoComposition *videoComposition = [self fixedCompositionWithAsset:videoAsset]; + if (videoComposition.renderSize.width) { + // 修正视频转向 + session.videoComposition = videoComposition; + } + } + + // Begin to export video to the output path asynchronously. + [session exportAsynchronouslyWithCompletionHandler:^(void) { + [self handleVideoExportResult:session outputPath:outputPath success:success failure:failure]; + }]; + } else { + if (failure) { + NSString *errorMessage = [NSString stringWithFormat:@"当前设备不支持该预设:%@", presetName]; + failure(errorMessage, nil); + } + } +} + +- (void)requestVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + [self requestVideoOutputPathWithAsset:asset presetName:presetName timeRange:kCMTimeRangeZero success:success failure:failure]; +} + +- (void)requestVideoOutputPathWithAsset:(PHAsset *)asset presetName:(NSString *)presetName timeRange:(CMTimeRange)timeRange success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + if (!presetName) { + presetName = AVAssetExportPresetMediumQuality; + } + [[PHImageManager defaultManager] requestExportSessionForVideo:asset options:[self getVideoRequestOptions] exportPreset:presetName resultHandler:^(AVAssetExportSession *_Nullable exportSession, NSDictionary *_Nullable info) { + NSString *outputPath = [self getVideoOutputPath]; + exportSession.outputURL = [NSURL fileURLWithPath:outputPath]; + exportSession.shouldOptimizeForNetworkUse = NO; + exportSession.outputFileType = AVFileTypeMPEG4; + if (!CMTimeRangeEqual(timeRange, kCMTimeRangeZero)) { + exportSession.timeRange = timeRange; + } + [exportSession exportAsynchronouslyWithCompletionHandler:^{ + [self handleVideoExportResult:exportSession outputPath:outputPath success:success failure:failure]; + }]; + }]; +} + +- (void)requestVideoURLWithAsset:(PHAsset *)asset success:(void (^)(NSURL *videoURL))success failure:(void (^)(NSDictionary* info))failure { + [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:[self getVideoRequestOptions] resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){ + // NSLog(@"AVAsset URL: %@",myAsset.URL); + if ([avasset isKindOfClass:[AVURLAsset class]]) { + NSURL *url = [(AVURLAsset *)avasset URL]; + if (success) { + success(url); + } + } else if (failure) { + failure(info); + } + }]; +} + +- (void)handleVideoExportResult:(AVAssetExportSession *)session outputPath:(NSString *)outputPath success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure { + dispatch_async(dispatch_get_main_queue(), ^{ + switch (session.status) { + case AVAssetExportSessionStatusUnknown: { + NSLog(@"AVAssetExportSessionStatusUnknown"); + } break; + case AVAssetExportSessionStatusWaiting: { + NSLog(@"AVAssetExportSessionStatusWaiting"); + } break; + case AVAssetExportSessionStatusExporting: { + NSLog(@"AVAssetExportSessionStatusExporting"); + } break; + case AVAssetExportSessionStatusCompleted: { + NSLog(@"AVAssetExportSessionStatusCompleted"); + if (success) { + success(outputPath); + } + } break; + case AVAssetExportSessionStatusFailed: { + NSLog(@"AVAssetExportSessionStatusFailed"); + if (failure) { + failure(@"视频导出失败", session.error); + } + } break; + case AVAssetExportSessionStatusCancelled: { + NSLog(@"AVAssetExportSessionStatusCancelled"); + if (failure) { + failure(@"导出任务已被取消", nil); + } + } break; + default: break; + } + }); +} + +- (PHVideoRequestOptions *)getVideoRequestOptions { + PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init]; + options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic; + options.networkAccessAllowed = YES; + return options; +} + +- (NSString *)getVideoOutputPath { + NSDateFormatter *formater = [[NSDateFormatter alloc] init]; + [formater setDateFormat:@"yyyy-MM-dd-HH-mm-ss-SSS"]; + NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/video-%@-%d.mp4", [formater stringFromDate:[NSDate date]], arc4random_uniform(10000000)]; + return outputPath; +} + +- (BOOL)isCameraRollAlbum:(PHAssetCollection *)metadata { + NSString *versionStr = [[UIDevice currentDevice].systemVersion stringByReplacingOccurrencesOfString:@"." withString:@""]; + if (versionStr.length <= 1) { + versionStr = [versionStr stringByAppendingString:@"00"]; + } else if (versionStr.length <= 2) { + versionStr = [versionStr stringByAppendingString:@"0"]; + } + CGFloat version = versionStr.floatValue; + // 目前已知8.0.0 ~ 8.0.2系统,拍照后的图片会保存在最近添加中 + if (version >= 800 && version <= 802) { + return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumRecentlyAdded; + } else { + return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumUserLibrary; + } +} + +/// 检查照片大小是否满足最小要求 +- (BOOL)isPhotoSelectableWithAsset:(PHAsset *)asset { + CGSize photoSize = CGSizeMake(asset.pixelWidth, asset.pixelHeight); + if (self.minPhotoWidthSelectable > photoSize.width || self.minPhotoHeightSelectable > photoSize.height) { + return NO; + } + return YES; +} + +/// 检查照片能否被选中 +- (BOOL)isAssetCannotBeSelected:(PHAsset *)asset { + if ([self.pickerDelegate respondsToSelector:@selector(isAssetCanBeSelected:)]) { + BOOL canSelectAsset = [self.pickerDelegate isAssetCanBeSelected:asset]; + return !canSelectAsset; + } + return NO; +} + +#pragma mark - Private Method + +- (TZAlbumModel *)modelWithResult:(PHFetchResult *)result collection:(PHAssetCollection *)collection isCameraRoll:(BOOL)isCameraRoll needFetchAssets:(BOOL)needFetchAssets options:(PHFetchOptions *)options { + TZAlbumModel *model = [[TZAlbumModel alloc] init]; + [model setResult:result needFetchAssets:needFetchAssets]; + model.name = collection.localizedTitle; + model.collection = collection; + model.options = options; + model.isCameraRoll = isCameraRoll; + model.count = result.count; + return model; +} + +/// 缩放图片至新尺寸 +- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size { + if (image.size.width > size.width && size.width > 0 && size.height > 0) { + UIGraphicsBeginImageContext(size); + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; + + /* 好像不怎么管用:https://mp.weixin.qq.com/s/CiqMlEIp1Ir2EJSDGgMooQ + CGFloat maxPixelSize = MAX(size.width, size.height); + CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)UIImageJPEGRepresentation(image, 0.9), nil); + NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue, + (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize] + }; + CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options); + UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:2 orientation:image.imageOrientation]; + CGImageRelease(imageRef); + CFRelease(sourceRef); + return newImage; + */ + } else { + return image; + } +} + +/// 判断asset是否是视频 +- (BOOL)isVideo:(PHAsset *)asset { + return asset.mediaType == PHAssetMediaTypeVideo; +} + +- (TZAssetModel *)createModelWithAsset:(PHAsset *)asset { + TZAssetModelMediaType type = [[TZImageManager manager] getAssetType:asset]; + NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",asset.duration] : @""; + timeLength = [[TZImageManager manager] getNewTimeFromDurationSecond:timeLength.integerValue]; + TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength]; + return model; +} + +/// 获取优化后的视频转向信息 +- (AVMutableVideoComposition *)fixedCompositionWithAsset:(AVAsset *)videoAsset { + AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; + // 视频转向 + int degrees = [self degressFromVideoFileWithAsset:videoAsset]; + if (degrees != 0) { + CGAffineTransform translateToCenter; + CGAffineTransform mixedTransform; + videoComposition.frameDuration = CMTimeMake(1, 30); + + NSArray *tracks = [videoAsset tracksWithMediaType:AVMediaTypeVideo]; + AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; + + AVMutableVideoCompositionInstruction *roateInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; + roateInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]); + AVMutableVideoCompositionLayerInstruction *roateLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; + + if (degrees == 90) { + // 顺时针旋转90° + translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0); + mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2); + videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width); + [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero]; + } else if(degrees == 180){ + // 顺时针旋转180° + translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.width, videoTrack.naturalSize.height); + mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI); + videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height); + [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero]; + } else if(degrees == 270){ + // 顺时针旋转270° + translateToCenter = CGAffineTransformMakeTranslation(0.0, videoTrack.naturalSize.width); + mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0); + videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width); + [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero]; + } + + roateInstruction.layerInstructions = @[roateLayerInstruction]; + // 加入视频方向信息 + videoComposition.instructions = @[roateInstruction]; + } + return videoComposition; +} + +/// 获取视频角度 +- (int)degressFromVideoFileWithAsset:(AVAsset *)asset { + int degress = 0; + NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; + if([tracks count] > 0) { + AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; + CGAffineTransform t = videoTrack.preferredTransform; + if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){ + // Portrait + degress = 90; + } else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){ + // PortraitUpsideDown + degress = 270; + } else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){ + // LandscapeRight + degress = 0; + } else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){ + // LandscapeLeft + degress = 180; + } + } + return degress; +} + +/// 修正图片转向 +- (UIImage *)fixOrientation:(UIImage *)aImage { + if (!self.shouldFixOrientation) return aImage; + + // No-op if the orientation is already correct + if (aImage.imageOrientation == UIImageOrientationUp) + return aImage; + + // We need to calculate the proper transformation to make the image upright. + // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. + CGAffineTransform transform = CGAffineTransformIdentity; + + switch (aImage.imageOrientation) { + case UIImageOrientationDown: + case UIImageOrientationDownMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height); + transform = CGAffineTransformRotate(transform, M_PI); + break; + + case UIImageOrientationLeft: + case UIImageOrientationLeftMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.width, 0); + transform = CGAffineTransformRotate(transform, M_PI_2); + break; + + case UIImageOrientationRight: + case UIImageOrientationRightMirrored: + transform = CGAffineTransformTranslate(transform, 0, aImage.size.height); + transform = CGAffineTransformRotate(transform, -M_PI_2); + break; + default: + break; + } + + switch (aImage.imageOrientation) { + case UIImageOrientationUpMirrored: + case UIImageOrientationDownMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.width, 0); + transform = CGAffineTransformScale(transform, -1, 1); + break; + + case UIImageOrientationLeftMirrored: + case UIImageOrientationRightMirrored: + transform = CGAffineTransformTranslate(transform, aImage.size.height, 0); + transform = CGAffineTransformScale(transform, -1, 1); + break; + default: + break; + } + + // Now we draw the underlying CGImage into a new context, applying the transform + // calculated above. + CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height, + CGImageGetBitsPerComponent(aImage.CGImage), 0, + CGImageGetColorSpace(aImage.CGImage), + CGImageGetBitmapInfo(aImage.CGImage)); + CGContextConcatCTM(ctx, transform); + switch (aImage.imageOrientation) { + case UIImageOrientationLeft: + case UIImageOrientationLeftMirrored: + case UIImageOrientationRight: + case UIImageOrientationRightMirrored: + // Grr... + CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage); + break; + + default: + CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage); + break; + } + + // And now we just create a new UIImage from the drawing context + CGImageRef cgimg = CGBitmapContextCreateImage(ctx); + UIImage *img = [UIImage imageWithCGImage:cgimg]; + CGContextRelease(ctx); + CGImageRelease(cgimg); + return img; +} + +#pragma clang diagnostic pop + +// 添加加载更多数据的方法 +- (void)getMoreAssetsFromFetchResult:(PHFetchResult *)result currentCount:(NSInteger)currentCount completion:(void (^)(NSArray *))completion { + if (self.isLoadingMore || currentCount >= result.count) { + if (completion) completion(nil); + return; + } + + self.isLoadingMore = YES; + TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance]; + + // 使用同步处理 + NSInteger offset = MAX((NSInteger)(result.count - currentCount - self.pageSize), 0); + NSInteger start = result.count - currentCount - 1; + NSMutableArray *photoArr = [NSMutableArray array]; + + // 从旧到新遍历,这样插入时就是正确的顺序 + for (NSInteger i = offset; i <= start; i++) { + @autoreleasepool { + PHAsset *asset = result[i]; + TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage]; + if (model) { + [photoArr addObject:model]; + } + } + } + + self.isLoadingMore = NO; + if (completion) completion(photoArr); +} + +@end + + +//@implementation TZSortDescriptor +// +//- (id)reversedSortDescriptor { +// return [NSNumber numberWithBool:![TZImageManager manager].sortAscendingByModificationDate]; +//} +// +//@end diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlay@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlay@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7a51372a60e3f90de4ae96fc260bb323e79d4867 GIT binary patch literal 3645 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 P00000NkvXXu0mjf^@Sk% literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlayHL@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlayHL@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ffcadc1b1e504082b5c99d006b99fcf34518c1fe GIT binary patch literal 3645 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 P00000NkvXXu0mjfL*e}E literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/VideoSendIcon@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/VideoSendIcon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..110543a5cf1f0b18c93233202081025d8edf9655 GIT binary patch literal 223 zcmV<503iQ~P)<%$Ym~_E2Ad{3HKJA}E-b zf*_gG`OxJgl6kW%Z?Y-k$TgEluqt7KICjG{Qm`teF(P)yEV51pZBIP18*-+~ZpgVh zyCV1|$b|-c^~Uz=)D!G_*%J4#`?bHFMe>yoFrRsVf$6Ux6BNx$QIO633ak44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TW!dY5_BX4N|yFZki`h*;`K+$B+uf zx3>+m4hM+19<)eFkJ^51(b^dzX7A!YTbwY+O#1Pm-+12&gC~Wt*Zb#tJ=o6m@(=d| zzw!p@a;*u+)=-K3cj=bf8=LdrO^+AuiLXD(%|H1|@}XX9QIF(nxX8Ih_U}H&AD(~T z_N~;N=d*QQ-}{@=e!GC*VfXPJ<+km&^S->1yZ7?-kI#bj^V>hYzRSCRZ8gI!+hcoQ zTi$6Snf0wUK9INm!ruP1)_-dX9{aIgno&Bm$mMtZd+bEgpU(+-21)>)u6{1-oD!M< DP0$)v literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ar.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ar.lproj/Localizable.strings new file mode 100644 index 0000000..0e9b817 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ar.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "阿拉伯语"; +"OK" = "حسنا"; +"Back" = "الى الخلف"; +"Done" = "فعله"; +"Edit" = "تعديل"; +"Sorry" = "آسف"; +"Cancel" = "إلغاء"; +"Setting" = "ضبط"; +"Photos" = "الصور"; +"Videos" = "أشرطة فيديو"; +"Preview" = "معاينة"; +"Full image" = "الصورة كاملة"; +"Processing..." = "معالجة..."; +"No Photos or Videos" = "لا توجد صور أو مقاطع فيديو"; +"Synchronizing photos from iCloud" = "مزامنة الصور من iCloud"; +"iCloud sync failed" = "iCloud فشلت المزامنة"; +"Can not use camera" = "لا يمكن استخدام الكاميرا"; +"Can not choose both video and photo" = "لا يمكن اختيار كل من الفيديو والصور"; +"Can not choose both photo and GIF" = "لا يمكن اختيار كل من الصور و GIF"; +"Select the video when in multi state, we will handle the video as a photo" = "حدد مقطع الفيديو عندما يكون في حالة متعددة، وسنعمل على معالجة مقطع الفيديو كصورة"; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "إذا تعذّر الانتقال إلى صفحة \"إعدادات الخصوصية\"، فيرجى الانتقال إلى صفحة \"الإعدادات\" بنفسك، شكرًا لك"; +"Select a maximum of %zd photos" = "حدد فقط ما يصل إلى %zd صورة"; +"Select a minimum of %zd photos" = "الرجاء تحديد %zd صورة على الأقل"; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "السماح لـ %@ بالوصول إلى الألبوم في \"الإعدادات > الخصوصية > الصور\""; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "الرجاء السماح لـ %@ بالوصول إلى الكاميرا في \"الإعدادات > الخصوصية > الكاميرا\""; +"Selected for %ld seconds" = "محدد لمدة %ld ثانية"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/de.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/de.lproj/Localizable.strings new file mode 100644 index 0000000..3a6cec3 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/de.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "德语"; +"OK" = "OK"; +"Back" = "Zurück"; +"Done" = "Erledigt"; +"Edit" = "Bearbeiten"; +"Sorry" = "Es tut uns leid"; +"Cancel" = "Stornieren"; +"Setting" = "Rahmen"; +"Photos" = "Fotos"; +"Videos" = "Videos"; +"Preview" = "Vorschau"; +"Full image" = "Vollbild"; +"Processing..." = "Wird bearbeitet..."; +"No Photos or Videos" = "Keine Fotos oder Videos"; +"Synchronizing photos from iCloud" = "Fotos aus iCloud synchronisieren"; +"iCloud sync failed" = "iCloud Synchronisierung fehlgeschlagen"; +"Can not use camera" = "Kann die Kamera nicht benutzen"; +"Can not choose both video and photo" = "Video und Foto können nicht ausgewählt werden"; +"Can not choose both photo and GIF" = "Foto und GIF können nicht ausgewählt werden"; +"Select the video when in multi state, we will handle the video as a photo" = "Wenn Sie das Video im Multi-Status auswählen, wird es als Foto behandelt"; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "Sie können nicht zur Seite mit den Datenschutz-Einstellungen springen; bitte navigieren Sie selbst zur Einstellungsseite. Vielen Dank."; +"Select a maximum of %zd photos" = "Wählen Sie maximal %zd Bilder aus"; +"Select a minimum of %zd photos" = "Bitte wählen Sie mindestens %zd Fotos aus"; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "Erlauben Sie %@ den Zugriff auf Ihr Album unter: „Einstellungen > Datenschutz > Fotos“"; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Erlauben Sie %@ den Zugriff auf Ihre Kamera unter: „Einstellungen > Datenschutz > Kamera“"; +"Selected for %ld seconds" = "Ausgewählt für %ld Sekunden"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/en.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/en.lproj/Localizable.strings new file mode 100755 index 0000000000000000000000000000000000000000..a120f28b7e9cc1c3ccd9db32602e71288fbd619d GIT binary patch literal 3760 zcmd5;+lmuG5Uppwq6y?p_Xk8#_aY*=fq)?FOKv7{b0ZgHeDu|C^}!!d&*_ui?oMXH z%!;xMyG(kzPMtbc)z!a$HSDcj+6QZxtNc8}&W8Q`_TziQp4ub4UjwBMf-_;rP8hGO zV?DdAfg_A)C!7nL+sp>FaiX1YF0F54Ti3>kcEV|c&l1nBGLqs-?Sym=g=WxbV3Uei zLdxv|s{vwLBf^;tE1?Bext-8jHbRtZ{H-csh5YAs!g>!*eZ*K7E4K^0mO%Op#DQ%q zF;kQ+O03H zPhIbM1fQ&I^@@Yn8QxRXSwY3V?~7NDUCe)E_uAgrRg(2XRmzy1!V;@Cv}bmEJ}YY| z#;l|YZT;E|tL!s}Y_Xqt2C`1pP;d>K$N07Nwp(8>?Dx@LUE(|JI>zn*fl(Ig{}8zq z=kgOYnWA$UCC`r#>jHH>hMJtwJFK%3Vedl}N6FWTed5N8z6kEUV1^%ll zS%tg@ab|{!;AHDycXzLsdi(~lwXrj=)hG5GyE*04nhvY+E<@{hivBA$MO?IY$V6Gn z^<~U;G)m`GI0@^k#B)1LyIiIJ#jZ@XV`j&-%{u^Z1iBA3p&x& Privacy -> Photos\"" = "Permita que %@ acceda a su galería en \"Ajustes > Privacidad > Fotografías\""; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Permita que %@ acceda a su cámara en \"Ajustes > Privacidad > Cámara\""; +"Selected for %ld seconds" = "Seleccionado para %ld segundos"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/fr.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/fr.lproj/Localizable.strings new file mode 100644 index 0000000..f4e921f --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/fr.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "法语"; +"OK" = "D'accord"; +"Back" = "Retour"; +"Done" = "Terminé"; +"Edit" = "Éditer"; +"Sorry" = "Pardon"; +"Cancel" = "Annuler"; +"Setting" = "Réglage"; +"Photos" = "Photos"; +"Videos" = "Vidéos"; +"Preview" = "Aperçu"; +"Full image" = "Image complète"; +"Processing..." = "En traitement..."; +"No Photos or Videos" = "Aucune photo ou vidéo"; +"Synchronizing photos from iCloud" = "Synchroniser des photos depuis iCloud"; +"iCloud sync failed" = "iCloud échec de la synchronisation"; +"Can not use camera" = "Impossible d'utiliser la caméra"; +"Can not choose both video and photo" = "Impossible de choisir à la fois la vidéo et la photo"; +"Can not choose both photo and GIF" = "Impossible de choisir à la fois photo et GIF"; +"Select the video when in multi state, we will handle the video as a photo" = "Sélectionnez la vidéo lorsqu’elle est en état multiple, nous la traiterons comme une photo"; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "Impossible d'ouvrir la page des paramètres de confidentialité, veuillez accéder vous-même à la page des paramètres, merci"; +"Select a maximum of %zd photos" = "Vous pouvez uniquement sélectionner un maximum de %zd images"; +"Select a minimum of %zd photos" = "Veuillez sélectionner un minimum de %zd photos"; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "Autorisez %@ à accéder à votre album dans « Paramètres > Confidentialité > Photos »"; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Autorisez %@ à accéder à votre appareil photo dans « Paramètres > Confidentialité > Appareil photo »"; +"Selected for %ld seconds" = "Sélectionné pendant %ld secondes"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/iCloudError@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/iCloudError@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..77c6d47711ae91bf5c8cd8561ba82efe313650b1 GIT binary patch literal 4394 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 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ja.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ja.lproj/Localizable.strings new file mode 100644 index 0000000..adf5a06 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ja.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "日语"; +"OK" = "OK"; +"Back" = "バック"; +"Done" = "完了"; +"Edit" = "編集する"; +"Sorry" = "ごめんなさい"; +"Cancel" = "キャンセル"; +"Setting" = "設定"; +"Photos" = "写真"; +"Videos" = "動画"; +"Preview" = "プレビュー"; +"Full image" = "フルイメージ"; +"Processing..." = "処理..."; +"No Photos or Videos" = "写真やビデオはありません"; +"Synchronizing photos from iCloud" = "iCloudから写真を同期する"; +"iCloud sync failed" = "iCloud同期に失敗しました"; +"Can not use camera" = "カメラが使えない"; +"Can not choose both video and photo" = "ビデオと写真の両方を選択することはできません"; +"Can not choose both photo and GIF" = "写真とGIFの両方を選択することはできません"; +"Select the video when in multi state, we will handle the video as a photo" = "多肢選択の状態で、ビデオを選択すると、ビデオをデフォルトに画像として送信します。"; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "プライバシー設定画面にジャンプできません。手動で設定画面を表示してください。"; +"Select a maximum of %zd photos" = "写真は多くとも%zd 枚選択できます。"; +"Select a minimum of %zd photos" = "少なくとも %zd 枚の写真を選択してください。"; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "iPhoneの「設定-プライバシー-写真」のオプションで、r%@の携帯電話のアルバムへのアクセス権限を許可してください。"; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "iPhoneの「設定-プライバシー-カメラ」で、%@のカメラへのアクセス権限を許可してください。"; +"Selected for %ld seconds" = "%ld 秒間選択されました"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ko-KP.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ko-KP.lproj/Localizable.strings new file mode 100644 index 0000000..7cdd747 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ko-KP.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "朝鲜语"; +"OK" = "그래"; +"Back" = "뒤로"; +"Done" = "완료"; +"Edit" = "편집하다"; +"Sorry" = "미안해요"; +"Cancel" = "취소"; +"Setting" = "설정"; +"Photos" = "사진"; +"Videos" = "동영상"; +"Preview" = "미리 보기"; +"Full image" = "전체 이미지"; +"Processing..." = "처리..."; +"No Photos or Videos" = "아무 사진이 나 동영상"; +"Synchronizing photos from iCloud" = "ICloud에서 사진을 동기화"; +"iCloud sync failed" = "iCloud동기화 실패"; +"Can not use camera" = "카메라를 사용할 수 없습니다."; +"Can not choose both video and photo" = "비디오와 사진 둘 다를 선택할 수 없습니다."; +"Can not choose both photo and GIF" = "사진 및 GIF를 선택할 수 없습니다."; +"Select the video when in multi state, we will handle the video as a photo" = "다중 선택 모드에서 비디오를 선택하면 비디오를 사진으로 처리합니다."; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "개인 정보 보호 설정 페이지로 바로 이동할 수 없습니다. 설정 페이지로 직접 이동해 주세요. 감사합니다."; +"Select a maximum of %zd photos" = "최대 %zd장의 이미지만 선택할 수 있습니다."; +"Select a minimum of %zd photos" = "최소 %zd장의 사진을 선택해 주세요."; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "\"설정 > 개인 정보 보호 > 사진\"에서 %@이(가) 앨범에 접근할 수 있도록 허용하세요."; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "\"설정 > 개인 정보 보호 > 카메라\"에서 %@이(가) 카메라에 접근할 수 있도록 허용하세요."; +"Selected for %ld seconds" = "%ld 초 동안 선택됨"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/navi_back@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/navi_back@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..633b9e6de011889e7797b505c67d2df72ada89ff GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^qCl*|!2%@DSnLFGtUX;ELn;{Gp4!TIz(9ay!|gwH zpB8L13U=5ku)SD)f|$NfkCpo(<=n^e|6i=Cn0jE>&-3+S3iD!n(na~7?p>EK^WnWa QKw}s@UHx3vIVCg!0JBypJ^%m! literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_def_photoPickerVc@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_def_photoPickerVc@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1415caedf7f7062c72056f8100b546b1e05d10ed GIT binary patch literal 1155 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 APyhe` literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_original_sel@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_original_sel@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8889b1311fc3a260f566af262376f9cfd7ebab75 GIT binary patch literal 620 zcmV-y0+aoTP)@ffk7lFAc0g!X}mJ5=Gp_ZjsrXBL}d30ym+{Y2X-%(B@aX;-}Gg zoLP2Y3yQDV*=0W7n?G;nQ(2ac<|24b!36X{268Y53t=wLGI=LCm7oGWFa}=&8OygS zmS7i5slz)kk_fed0ZK6PtS|4}(RWkOty55gA$2eVDbN9bPRlnl`kf)r#|j!Sp@KoOk)Q&rG_DMhVizw`NbqQN~Vz$^F#-oQ`rByFxJwZM#0ZbAh$MeYV%Sz>LG z+JVxCyt4rvtB)&iLy^=WfF~8`_&Jsm(_`iZ(8gngfle8T`S&;)++v%n; z+5J$E#@)b@+kmnr3aifnjYs7Z>``hJ$$h8D)xp6^x1v<{-W8-BA|<&Njk!A6SraFv z9mgq{(Ad)?SVWL>rCQTiOk9F}X&jN9rs&0BZ>^Ifap=1QGe>&wK^d8)Bh8shFqg)* zJ#!o0>LdgC~;UcUa;{gZqg(vT$7~n z%S^~Zy>G%o&0F2=8MnGyaY#ang-)dHZtp1;g3GN{&E?h~@U=?0r91`ej~WFZ`~_?E zl7D?#fPswF>j9pTWl2j6^$raF(Eoxo#f5pe9R{ouaz9Nd?&4(=?ON4)yTfob&R zQS9rt45Xgxw-jWq>$kWUm@Tfn~Q4?d&B<*Aj!3d6G(FI;{+<^2CCl;QV$XbGWKwB z?d1}`C=Qn8^z5ffXaa8aPQ^NzN!sUyqAL;B*Mb%#Xa!4uqV&u-(JFb7Zo_9U>>gTKS2W2mP zx+Jk*O!crz)vZd?0}t@;T*{&F?3CBdCfk2U{jSWK zF*oh`MHaKaqI(Y~uw~U(eyxzu{P#=45g5~_JzX3_Dj1(${G6ofDA4+`IQQ7LtsAeE zPFjo?q7V&(PqV@;a7PVBvFGOikHOM3;aOnkSB2&h=v zI?uo9IOA#8l~*~&y;r;oz6p8_6j*()$nKmPym z3HkXiMB6vHw3jPws(YQ!6S?1aewBu*)m_1fyT8BdKGDqkYwCiK7e#LWEUWvZWCMZ( zcg>k@uNSk#O@-CFDQ~*VlTV_rOb%^x>d!9v%eM7Z!s%l#KK^6gnilnN!&F7z!XutTdP+W3$bmrL1DDo^e3AkX?5nTgHo~WA7|_yJ{~)#Vm7F>Xr)2E|-+;TeR(z zz}91K2`1Z3-R5@|vYc9{qEzx?{uxmLuT?=&UC)gtM(m22+n+S~Cu_jfo$f(%x!ZxM Ogu&C*&t;ucLK6VY1;)ex literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_sel_previewVc@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/photo_sel_previewVc@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..827c79427f9e19da022051b70678af9ea8bd30d7 GIT binary patch literal 1183 zcmW+!3s6&65Df?<@4bX#0Ob=EB^v%HAk?;_27@FJDGgyv2MUy0K@^dQ2o@3LBLty@ zkW|oGgldIQEafAbUlSo(!VEzSAjn6f#PSnls00yuUuW*!yLvxm1VTuHg``+miX%QI{_o=uIRZl90}F$!3?e89 zz=0(YKoA82O8|}%EERx*U0Yj26=X25hz!thcqtyOmBSzl%dk0XIluu~-)>((15yac zO0jq;1jO+wJOpH=2-*=nH~<0!@ZELpuoOmQ5DH3h`xX01Y7$WiLUcAr0zqY`Qx(oowk3WpQbq= zdMUg&b^fREYe>N8{{@l%FV-z!|Bh`_~ZPa zUW&&49pw(D25P93hdcD|_3cybDFY{)C!0Mw+zd+wv7vsK+PiJ4Ew(SlTDD&OwsYy@ z5?Qq^QJ2umV*CdFjG4v?i@>aWn6+HIyPr-hcpiL@Q_GR{{ys!J@w&pxU*gEqAqQUe|c@dxhuZ&Wb9llORj26n=f#h_8y z874D>x#`=fHV0pv-Zb2n{JH%{O8=n0Z=12pno?5VI2l)`I6PQ<&658}KX29?p=$aH zl7}-z%dz6KRyqvnZ)sqgND-8_20PQKx zy&cc3cy4y+Vg~mKKH2$I^{w?of0i>E30@U^_74~@vQWUp+WdaKN?96M{!c-buckYp z$&*Q}%navpMMhFO`TKH?S;(rVPwb5jF9KO)Vji*3os~_LL<%@HAvJy7S*fr^5!t^% zRG7k4x(GXJgv9wnSAztcD-026l7Q+Y%qcsM`UHT8yoDcK> literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/preview_number_icon@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/preview_number_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..789335b4f32e24f4e883eb8ad782e5294375d359 GIT binary patch literal 501 zcmVkgr0BpBDd1 zE-Y#;%!Roy7goSF?8goC;p4|YKKi(U{n&^@CGI(9@a%2who_QV)hB^q6(|y4NOAbpdNNu z2`!j}wNMH(>==v^N5cwRhOwfsF_wlAb{|HWdqKliV5Tr^h801=uD~dDMH*Jbd&Obz zQIv#jg;8#+By7J0Vf!UvH!TReDG3``5H^s6c@~6ulCU2Zg#D0&eYGHLED3vVLD*YK zSlfcIo+Rw51z}euVY@8|+bs#(WI@;_Nmv%1;wT?E>9ggG;;=J8-eXG?KQx!f!+<*q z!|sH!^H{8KnX@=}7;sQg*r71@iUl;4EKG}T#XX002`zZuV_h8INM6j3$u)6({8iD3 zA*zFF5?{54F^wQ-g2SPH)e0;QdB1-ji#44?EW>5^f*2o{u}t#;OCCG17q>CQ2;+Z7 r7~(eeVkh$MFlezrBBr5&H*3tx`oPGw{) z2!4DVbx=4~dK4d5a(wFq_$COe_;`?`>jdZo;Se9sax|R)jUb$F1gNjFzEkwWMnABh zA`7){nR=)*sVW`)n^xLR@qmLn1jYg3boc^%XXq+3tON?_KM)5e; mbl_YT4xCGQHMbgx@9Q6=;eb=4TJWd<0000 Privacy -> Photos\"" = "Permita a %@ aceder ao seu álbum em “Definições > Privacidade > Fotos”"; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Permita a %@ aceder à sua câmara em “Definições > Privacidade > Câmara”"; +"Selected for %ld seconds" = "Selecionado por %ld segundos"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/right_arrow@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/right_arrow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..795be72bd296c6fbb664e0906e977ac350d4c91d GIT binary patch literal 1259 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+j!3HGvO?g@mq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1Ffc1-hD4M^`1)8S=jZArg4F0$^BXQ!4Z zB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakYy!KT6rXh3di zNuokUZcbjYRfVk**jy_h8zii+qySb@l5ML5aa4qFfP!;=QL2Keo|$g4p^1@#xuu?= znSrH|iH?GifuXs+fw{h+v95ukm4TU+v84hOC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DR zmzV368|&p4rRy77T3YHG80i}s=>k>g7FXt#Bv$C=6)VF`a7isrF3Kz@$;{7F0GXJW zlwVq6s|0i@#0$9vaAWg|p}_3LT&-jW|!2W%(B!Jx1#)91+b5;GI6`b38#5b zy(zfe;*3+TKF~4xpm;@!XP6K$@qn1{R14(5(|u|lFtHZ_Q?>qt(rpY3j0v7Djv*Dd zrd;vWa7h$7_R%_7nNwA@T65_Voh3RNs=gCjS-UzWsRV6OFf*I9Bx8|?n3$834^VE& zlqs9Sg%nR7JO2O5>1Inw5D&e#DV14vA!GH5FVl2azc^%Ww6UKn|K_Ge);}D@_yXSPMo+uA zn(?NE)6DHTkuLk$o@6+z+@3S@_=0mgr2-!5MyDCB*=*}^T;tm`-OCbx%@>@A-sY1S z^Soxx0t2~+f%8PX8Os(;VZQtCzJFhk9Cz*4YLz`t1$|!pX^^^8dCGa0!Rf_a+vnYu zyAUs`cdz2#bGtJy{;bh0ep`8{%Aj2$E@aOqo7;0E0zQTw^*$ecwQosRepH|Myze_j zy??!t{c7<&XHr`3M3b5o70+%a`bO}J3R`^5JHMoBe#RB)$MP(>FVdQ&MBb@06S&D=>Px# literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ru.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ru.lproj/Localizable.strings new file mode 100644 index 0000000..a2f8c45 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/ru.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "俄语"; +"OK" = "Хорошо"; +"Back" = "назад"; +"Done" = "Готово"; +"Edit" = "редактировать"; +"Sorry" = "сожалею"; +"Cancel" = "отменить"; +"Setting" = "настройка"; +"Photos" = "Фото"; +"Videos" = "Видео"; +"Preview" = "предварительный просмотр"; +"Full image" = "Полное изображение"; +"Processing..." = "Обработка ..."; +"No Photos or Videos" = "Нет фото или видео"; +"Synchronizing photos from iCloud" = "Синхронизация фотографий из iCloud"; +"iCloud sync failed" = "iCloud сбой синхронизации"; +"Can not use camera" = "Не могу использовать камеру"; +"Can not choose both video and photo" = "Не могу выбрать как видео,так и фото"; +"Can not choose both photo and GIF" = "Не могу выбрать фото и GIF"; +"Select the video when in multi state, we will handle the video as a photo" = "В случае выбора видео при нахождении в мультирежиме видео будет обработано как фотография"; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "Не удается перейти на страницу настроек конфиденциальности. Перейдите на эту страницу самостоятельно"; +"Select a maximum of %zd photos" = "Вы можете выбрать до %zd изображений"; +"Select a minimum of %zd photos" = "Вы можете выбрать не менее %zd изображений"; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "Разрешите доступ %@ к вашему альбому,перейдя в Настройки > Конфиденциальность > Фото"; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Разрешите доступ %@ к камере вашего устройства,перейдя в Настройки > Конфиденциальность > Камера"; +"Selected for %ld seconds" = "Выбрано для %ld секунд"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/takePicture80@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/takePicture80@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5d06636504c407862886e212d65557fd4594d104 GIT binary patch literal 1285 zcmV+g1^W7lP)`P&{G5qkO6uU@HA%yGC)rPp60AT z2Ixt^)0`E^06htKnzI6r4WKdReUc=np6zZmFU#^?Yke1@?yfpVQ{Zeid%0Szz5zfG zc(o4BrIhDcmMzBsIT}D?%=Z!CZJ6CErOuxWKx51m0DK;!L$zm|E2VBjKQp)j$#sjO z_+JR|GIVDe^)HlCuR}jGIKTs`Z_Nz=vWtt0n~)HL0z9DlHq3&n&>GFMp05EZ}8M-V0(D*xdsTTkqvn*TK*z^L-^ZZN*F+0E*X4C$VWfq8-X|4Cd-wV(f z^9KNY3)#xp>n_Xk&E@6g{VxU5Bgbx0vP8r?tu=XJ>$O*bd7fjGy&AVsdnY0WXz?v0?t ztyxB+Kt%kcwf?)_@@htDN0*Ltm2IvvhIZqF1EkqkYrVBEJcRphfHvLuDFWPy{fsfo0cXptQwT%HgfS?P z0eX&AOQqDSM!3^>5&i?8E zOSzr2*w7(N+wfEG+t}Hd!IB9=hzF(A)^Xubr@>-zVR~_t7=7KA&Z11QLtIFED3fQG z&Z?w8S4zEWx_FfYppBwG_Y4(}LWoJ*(cPhg=Xx7rQsAatJ87uR4RS-;zAVeKp88rM z;=JpWR5g~;DY78Ph+_muygDJeOjcD^hj!M2z>8`UX@a4wa+;>}O^4NK(5C%#I{jSj z54$jTE*q-?>m8vzjxV+#^E{_xq@*0k$5-loBQ-^y8i1`uuU2WVJx$FEss@7J0kQse{lD|i*;x=E5u`aan1 z1xPKelAWiB82T4Cf`hSn007)eDerBP8&&{q9{OC%FhI{Y&j1;qCjn1$Rv-iPB;aYz v3S@wu1U$`Ifeg@-fTuYtkO6uU@HGDk7!$s4k_cm~00000NkvXXu0mjfC%jPk literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/takePicture@2x.png b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/takePicture@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e115003aac9155e74729b88acbb058189cfcac51 GIT binary patch literal 3054 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 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/vi.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/vi.lproj/Localizable.strings new file mode 100644 index 0000000..f54fce8 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/vi.lproj/Localizable.strings @@ -0,0 +1,26 @@ +"KEY" = "越南语"; +"OK" = "Xác nhận"; +"Back" = "Quay lại"; +"Done" = "Hoàn thành"; +"Edit" = "biên tập"; +"Sorry" = "Xin lỗi"; +"Cancel" = "Hủy"; +"Setting" = "Cài đặt"; +"Photos" = "Hình"; +"Videos" = "Clip"; +"Preview" = "Xem trước"; +"Full image" = "Hình gốc"; +"Processing..." = "Đang xử lý..."; +"No Photos or Videos" = "Không có ảnh hoặc video"; +"Can not use camera" = "Máy chụp hình không khả dụng"; +"Synchronizing photos from iCloud" = "Đang đồng bộ hình ảnh từ ICloud"; +"iCloud sync failed" = "iCloud đồng bộ hóa không thành công"; +"Can not choose both video and photo" = "Trong lúc chọn hình ảnh không cùng lúc chọn video"; +"Can not choose both photo and GIF" = "Trong lúc chọn hình ảnh không cùng lúc chọn hình GIF"; +"Select the video when in multi state, we will handle the video as a photo" = "Chọn hình ảnh cùng video, video sẽ bị mặc nhận thành hình ảnh và gửi đi."; +"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "Không thể chuyển tự động qua trang cài đặt riêng tư, bạn hãy thoát ra cà điều chỉnh lại, cám ơn bạn."; +"Select a maximum of %zd photos" = "Bạn chỉ được chọn nhiều nhất %zd tấm hình"; +"Select a minimum of %zd photos" = "Chọn ít nhất %zd tấm hình"; +"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "Vui lòng tại mục iPhone \" Cài đặt – quyền riêng tư - Ảnh\" mở quyền cho phép %@ truy cập ảnh."; +"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Vui lòng tại mục iPhone \" Cài đặt – quyền riêng tư - Ảnh\" mở quyền cho phép %@ truy cập máy ảnh"; +"Selected for %ld seconds" = "Đã chọn cho %ld giây"; diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/zh-Hans.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/zh-Hans.lproj/Localizable.strings new file mode 100755 index 0000000000000000000000000000000000000000..8c4e46409318a0fc01309d9d34fbe41685657f7d GIT binary patch literal 2892 zcmbVOO=whC82tnZOdX+avdHQ(5Xhn0~nF*hNwZ zs7y*Gi?+dqx^Ur2=%#el;zqhE6jZt@F550Ds2FK!rsupn*LS0tGEXiEdEdMDeBXD@ zx!+5BHzwn9M$!@!)$=-zoiSPa+)2h0*Swf~EFa)G38XM6N;FRC%FPP~xdywDgM7d~_i#u-_VoK!<&^sjDh8Vm<@RInO7qv&3~bc}BD$&KXSpW?qiy!Hv5LW%LQ=#$&9b z?CY`&Ml`cWg{vEq#+c6!O&v`4Rn1;~a}vN(VsoqzsUX&kGmZAtBftHw&5#4X(J_mD zg(cK>wNsyxB}+vmm;4V{%qTE#BYF zq{Qsee&LNKyYoIvRdhy{>`v-_tb{1NslXmR&ly0Ss_3+eGauop?w_sudht#yc32?3 z!mf9*GeBVV`|~uAjyWd3HJI!(TUh31-+H4SuZD4i2mwQztpPWWl&?VL4 zy(}ZUl0n?yy{^UbVj&bJIxng9GRxB-SV6O@0=uc zzwQzI)+$mpe#JN~4TGF-8SHjD-D;;!gIQL)SKGLJg58|Dwg*f!_%`u$aA$X#LsPlV zT;+cR>ovZo8gZdkaUn;HMOuyRcp}<9aqj!(pp3|m&A+~yORm?(-DBC;wT*K|vxz;v zV)bFVwda_*nc@58tTEFtY`>h4JQGjYo!WELb_(Y=r@8(X4Wd^*FN4W>#5gN$CqAEv zw4OM67vp+Xy^kX}hk{9I=a@@ApP_!#h@PiT)aUnBUy52r+kaoY-(+um6CECLBU#1| q4+r%u_+1qJt~ecRZ|2}eJ^A*}|4;Ew>gA<@^fbDE<}gQa%l-pEAsGn( literal 0 HcmV?d00001 diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/zh-Hant.lproj/Localizable.strings b/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle/zh-Hant.lproj/Localizable.strings new file mode 100755 index 0000000000000000000000000000000000000000..33aae5a5534f7625bb43c24fafe63a574c2fda17 GIT binary patch literal 2892 zcmbVOO>Yxd6untAQmBz&!y*#WG*YCfsv%u;g^H5!5k*n$!~=;ULLE=+IF3K#IJSdC zOC{722Nc5sEEcqj{sA^!RO+Iec9B&j60u?pY>h$~Mu0(suNIrrXk z&O4LlUZ0H1Ihm0@u{yrK#?C$&{>}~uLq8?@H(ikHWlX*$| zz)={FHlIvsjI)xLoFsf>+`M$e(HQ3>E-5Mb#&~-51vyt!;97w5a=-LI-j5 z;uquY`l*J-m;j#%DFZ1Xm5w@5vm9ysv92-B%PQE+z{4rYg5M;t{@b?-<7fNWw8mf` zc~_SeFrt_}A-vilDUA8_!1To*yGt4;1Qbh5b}g(FvDS_)g>xs`QB&C+Zp0&Hk8{f%s{VM=xGHw7AA^8sRVkCeZa56B+mEYfz{n|bg3N{ zS;^y4h>lxf5!m#Sa-{|I9DbWzQB75&TK_xF`9~HGhu&S|o$1RDJ8xIbQ^Bh?Dr0iq z;Qr%EmgqeyX?dc_@Vv`X36qf}bCQa?mcuH&X@Na@o*6)`N|>~ScfP<~#eKKpYQ{6M z*kXbB7IuA%9RmWpKbWW9nV$M@#jd$eLp}9p&R^@d8-eEI2fuD~&+@k&-J2RM{$qF5 z+v&7~PP1?;Yx8XA4hm2|g&FyMSi?GX^iqu-74VE_nNt;9e%L9eNVbqny!P)~;=Her zfuD)TF6fRley;&-)zFLXdv$AUb1?Go?w@N+&8~)XFVNhojXT?sZz9*CTnjXhZyevy zQ}0)hTr!EOn2<{GT;@^Pl75`v{f<=mt2{XumSpeDb6fe*+x=D4JgEoOqAUE>+N!t#Nt5<#I(htfeIOI)qiKWPL*f#&e!m$iNwlFw`5i*w=Y z<#8vvv|FxCYSkw8xr+V!nb%A)eJ=e^%%ss-=zn4+q{~CdoYl-t(=E(!Cc63}^YtT8K1H@>`Ft?$@s7uQu*{U28_hrFaTYs`gTUZ#driN2>&yXBjcPwU+gsu^g$ z`L?jZ+4v+dIOM4B +#import "TZAssetModel.h" +#import "NSBundle+TZImagePicker.h" +#import "TZImageManager.h" +#import "TZVideoPlayerController.h" +#import "TZGifPhotoPreviewController.h" +#import "TZPhotoPreviewController.h" +#import "TZPhotoPreviewCell.h" + +#if __has_include("TZLocationManager.h") +#define TZ_HAVE_LOCATION_CODE 1 +#import "TZLocationManager.h" +#else +#undef TZ_HAVE_LOCATION_CODE +#endif + +#define CURRENT_SYSTEM_VERSION [[UIDevice currentDevice] systemVersion] +#define SYSTEM_VERSION_GREATER_THAN_15 ([CURRENT_SYSTEM_VERSION floatValue] >= 15.0) + +@class TZAlbumCell, TZAssetCell; +@protocol TZImagePickerControllerDelegate; +@interface TZImagePickerController : UINavigationController + +#pragma mark - +/// Use this init method / 用这个初始化方法 +- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id)delegate; +- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id)delegate; +- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id)delegate pushPhotoPickerVc:(BOOL)pushPhotoPickerVc; +/// This init method just for previewing photos / 用这个初始化方法以预览图片 +- (instancetype)initWithSelectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index; +/// This init method for crop photo / 用这个初始化方法以裁剪图片 +- (instancetype)initCropTypeWithAsset:(PHAsset *)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,PHAsset *asset))completion; + +#pragma mark - +/// Default is 9 / 默认最大可选9张图片 +@property (nonatomic, assign) NSInteger maxImagesCount; + +/// The minimum count photos user must pick, Default is 0 +/// 最小照片必选张数,默认是0 +@property (nonatomic, assign) NSInteger minImagesCount; + +/// If the user does not select any pictures, the current picture is automatically selected when the Finish button is clicked, Default is YES +/// 如果用户未选择任何图片,在点击完成按钮时自动选中当前图片,默认YES +@property (nonatomic, assign) BOOL autoSelectCurrentWhenDone; + +/// Always enale the done button, not require minimum 1 photo be picked +/// 让完成按钮一直可以点击,无须最少选择一张图片 +@property (nonatomic, assign) BOOL alwaysEnableDoneBtn; + +/// Sort photos ascending by modificationDate,Default is YES +/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个 +@property (nonatomic, assign) BOOL sortAscendingByModificationDate; + +/// The pixel width of output image, Default is 828px,you need to set photoPreviewMaxWidth at the same time +/// 导出图片的宽度,默认828像素宽,你需要同时设置photoPreviewMaxWidth的值 +@property (nonatomic, assign) CGFloat photoWidth; + +/// Default is 600px / 默认600像素宽 +@property (nonatomic, assign) CGFloat photoPreviewMaxWidth; + +/// Default is 30, While fetching photo, HUD will dismiss automatic if timeout; +/// 超时时间,默认为30秒,当取图片时间超过30秒还没有取成功时,会自动dismiss HUD; +@property (nonatomic, assign) NSInteger timeout; + +/// Default is YES, if set NO, the original photo button will hide. user can't picking original photo. +/// 默认为YES,如果设置为NO,原图按钮将隐藏,用户不能选择发送原图 +@property (nonatomic, assign) BOOL allowPickingOriginalPhoto; + +/// Default is YES, if set NO, user can't picking video. +/// 默认为YES,如果设置为NO,用户将不能选择视频 +@property (nonatomic, assign) BOOL allowPickingVideo; + +/// Default is NO, if set YES, user can edit video. +/// 默认为NO,如果设置为YES, 用户能编辑视频 +@property (nonatomic, assign) BOOL allowEditVideo; + +/// Export quality of cropped video, Default is AVAssetExportPresetMediumQuality +/// 裁剪视频的导出质量,默认是 AVAssetExportPresetMediumQuality +@property (nonatomic, copy) NSString *presetName; + +/// Default is 30s. If it exceeds the video duration, it is the video duration.The minimum duration of video crop is 1s. +/// 默认是30s,如果超过视频时长,则为视频时长,小于1s不裁剪 +@property (nonatomic, assign) NSInteger maxCropVideoDuration; + +/// Default is NO, if set YES, The edited video will be automatically saved to the album. +/// 默认为NO,如果设置为YES,编辑后的视频会自动保存到相册 +@property (nonatomic, assign) BOOL saveEditedVideoToAlbum; + +/// Default is NO / 默认为NO,为YES时可以多选视频/gif/图片,和照片共享最大可选张数maxImagesCount的限制 +@property (nonatomic, assign) BOOL allowPickingMultipleVideo; + +/// Default is NO, if set YES, user can picking gif image. When NO, gif will be treated as a regular image. If want not displayed, please refer to isAssetCanBeDisplayed +/// 默认为NO,如果设置为YES,用户可以选择gif图片。为NO时gif会被当成普通图片,若要不显示,请参考isAssetCanBeDisplayed +@property (nonatomic, assign) BOOL allowPickingGif; + +/// Default is YES, if set NO, user can't picking image. +/// 默认为YES,如果设置为NO,用户将不能选择发送图片 +@property (nonatomic, assign) BOOL allowPickingImage; + +/// Default is YES, if set NO, user can't take picture. +/// 默认为YES,如果设置为NO, 用户将不能拍摄照片 +@property (nonatomic, assign) BOOL allowTakePicture; + +#ifdef TZ_HAVE_LOCATION_CODE +@property (nonatomic, assign) BOOL allowCameraLocation; +#endif + +/// Default is YES, if set NO, user can't take video. +/// 默认为YES,如果设置为NO, 用户将不能拍摄视频 +@property(nonatomic, assign) BOOL allowTakeVideo; +/// Default value is 10 minutes / 视频最大拍摄时间,默认是10分钟,单位是秒 +@property (assign, nonatomic) NSTimeInterval videoMaximumDuration; +/// Customizing UIImagePickerController's other properties, such as videoQuality / 定制UIImagePickerController的其它属性,比如视频拍摄质量videoQuality +@property (nonatomic, copy) void(^uiImagePickerControllerSettingBlock)(UIImagePickerController *imagePickerController); + +/// 首选语言,如果设置了就用该语言,不设则取当前系统语言。 +/// 支持zh-Hans、zh-Hant、en、vi等值,详见TZImagePickerController.bundle内的语言资源 +@property (copy, nonatomic) NSString *preferredLanguage; + +/// 语言bundle,preferredLanguage变化时languageBundle会变化 +/// 可通过手动设置bundle,让选择器支持新的的语言(需要在设置preferredLanguage后设置languageBundle)。欢迎提交PR把语言文件提交上来~ +@property (strong, nonatomic) NSBundle *languageBundle; + +/// Default is YES, if set NO, user can't preview photo. +/// 默认为YES,如果设置为NO,预览按钮将隐藏,用户将不能去预览照片 +@property (nonatomic, assign) BOOL allowPreview; + +/// Default is YES, if set NO, the picker don't dismiss itself. +/// 默认为YES,如果设置为NO, 选择器将不会自己dismiss +@property(nonatomic, assign) BOOL autoDismiss; + +/// Default is NO, if set YES, in the delegate method the photos and infos will be nil, only assets hava value. +/// 默认为NO,如果设置为YES,代理方法里photos和infos会是nil,只返回assets +@property (assign, nonatomic) BOOL onlyReturnAsset; + +/// Default is NO, if set YES, will show the image's selected index. +/// 默认为NO,如果设置为YES,会显示照片的选中序号 +@property (assign, nonatomic) BOOL showSelectedIndex; + +/// Default is NO, if set YES, when selected photos's count up to maxImagesCount, other photo will show float layer what's color is cannotSelectLayerColor. +/// 默认是NO,如果设置为YES,当照片选择张数达到maxImagesCount时,其它照片会显示颜色为cannotSelectLayerColor的浮层 +@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer; +/// Default is white color with 0.8 alpha; +@property (strong, nonatomic) UIColor *cannotSelectLayerColor; + +/// Default is YES, if set NO, the result photo will be scaled to photoWidth pixel width. The photoWidth default is 828px +/// 默认是YES,如果设置为NO,内部会缩放图片到photoWidth像素宽 +@property (assign, nonatomic) BOOL notScaleImage; + +/// 默认是NO,如果设置为YES,导出视频时会修正转向(慎重设为YES,可能导致部分安卓下拍的视频导出失败) +@property (assign, nonatomic) BOOL needFixComposition; + +/// The photos user have selected +/// 用户选中过的图片数组 +@property (nonatomic, strong) NSMutableArray *selectedAssets; +@property (nonatomic, strong) NSMutableArray *selectedModels; +@property (nonatomic, strong) NSMutableArray *selectedAssetIds; +- (void)addSelectedModel:(TZAssetModel *)model; +- (void)removeSelectedModel:(TZAssetModel *)model; + +/// Minimum selectable photo width, Default is 0 +/// 最小可选中的图片宽度,默认是0,小于这个宽度的图片不可选中 +@property (nonatomic, assign) NSInteger minPhotoWidthSelectable; +@property (nonatomic, assign) NSInteger minPhotoHeightSelectable; +/// Hide the photo what can not be selected, Default is NO +/// 隐藏不可以选中的图片,默认是NO,不推荐将其设置为YES +@property (nonatomic, assign) BOOL hideWhenCanNotSelect; +/// Deprecated, Use statusBarStyle (顶部statusBar 是否为系统默认的黑色,默认为NO) +@property (nonatomic, assign) BOOL isStatusBarDefault __attribute__((deprecated("Use -statusBarStyle."))); +/// statusBar的样式,默认为UIStatusBarStyleLightContent +@property (assign, nonatomic) UIStatusBarStyle statusBarStyle; + +#pragma mark - +/// Single selection mode, valid when maxImagesCount = 1 +/// 单选模式,maxImagesCount为1时才生效 +@property (nonatomic, assign) BOOL showSelectBtn; ///< 在单选模式下,照片列表页中,显示选择按钮,默认为NO +@property (nonatomic, assign) BOOL allowCrop; ///< 允许裁剪,默认为YES,showSelectBtn为NO才生效 +@property (nonatomic, assign) BOOL scaleAspectFillCrop; ///< 是否图片等比缩放填充cropRect区域,开启后预览页面无法左右滑动切换图片 +@property (nonatomic, assign) CGRect cropRect; ///< 裁剪框的尺寸 +@property (nonatomic, assign) CGRect cropRectPortrait; ///< 裁剪框的尺寸(竖屏) +@property (nonatomic, assign) CGRect cropRectLandscape; ///< 裁剪框的尺寸(横屏) +@property (nonatomic, assign) BOOL needCircleCrop; ///< 需要圆形裁剪框 +@property (nonatomic, assign) NSInteger circleCropRadius; ///< 圆形裁剪框半径大小 +@property (nonatomic, copy) void (^cropViewSettingBlock)(UIView *cropView); ///< 自定义裁剪框的其他属性 +@property (nonatomic, copy) void (^navLeftBarButtonSettingBlock)(UIButton *leftButton); ///< 自定义返回按钮样式及其属性 + +/// 【自定义各页面/组件的样式】在界面初始化/组件setModel完成后调用,允许外界修改样式等 +@property (nonatomic, copy) void (^photoPickerPageUIConfigBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine); +@property (nonatomic, copy) void (^photoPreviewPageUIConfigBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel); +@property (nonatomic, copy) void (^videoPreviewPageUIConfigBlock)(UIButton *playButton, UIView *toolBar, UIButton *editBtn, UIButton *doneButton); +@property (nonatomic, copy) void (^videoEditViewPageUIConfigBlock)(UIButton *playButton,UILabel *cropVideoDurationLabel, UIButton *editButton, UIButton *doneButton); +@property (nonatomic, copy) void (^gifPreviewPageUIConfigBlock)(UIView *toolBar, UIButton *doneButton); +@property (nonatomic, copy) void (^albumPickerPageUIConfigBlock)(UITableView *tableView); +@property (nonatomic, copy) void (^assetCellDidSetModelBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView); +@property (nonatomic, copy) void (^albumCellDidSetModelBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel); +/// 【自定义各页面/组件的frame】在界面viewDidLayoutSubviews/组件layoutSubviews后调用,允许外界修改frame等 +@property (nonatomic, copy) void (^photoPickerPageDidLayoutSubviewsBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine); +@property (nonatomic, copy) void (^photoPreviewPageDidLayoutSubviewsBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel); +@property (nonatomic, copy) void (^videoPreviewPageDidLayoutSubviewsBlock)(UIButton *playButton, UIView *toolBar, UIButton *editButton, UIButton *doneButton); +@property (nonatomic, copy) void (^videoEditViewPageDidLayoutSubviewsBlock)(UIButton *playButton, UILabel *cropVideoDurationLabel, UIButton *cancelButton, UIButton *doneButton); +@property (nonatomic, copy) void (^gifPreviewPageDidLayoutSubviewsBlock)(UIView *toolBar, UIButton *doneButton); +@property (nonatomic, copy) void (^albumPickerPageDidLayoutSubviewsBlock)(UITableView *tableView); +@property (nonatomic, copy) void (^assetCellDidLayoutSubviewsBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView); +@property (nonatomic, copy) void (^albumCellDidLayoutSubviewsBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel); +/// 自定义各页面/组件的frame】刷新底部状态(refreshNaviBarAndBottomBarState)使用的 +@property (nonatomic, copy) void (^photoPickerPageDidRefreshStateBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine); + +@property (nonatomic, copy) void (^photoPreviewPageDidRefreshStateBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel); + +#pragma mark - +- (UIAlertController *)showAlertWithTitle:(NSString *)title; +- (void)showProgressHUD; +- (void)hideProgressHUD; +@property (nonatomic, assign) BOOL isSelectOriginalPhoto; +@property (assign, nonatomic) BOOL needShowStatusBar; + +#pragma mark - +@property (nonatomic, copy) NSString *takePictureImageName __attribute__((deprecated("Use -takePictureImage."))); +@property (nonatomic, copy) NSString *photoSelImageName __attribute__((deprecated("Use -photoSelImage."))); +@property (nonatomic, copy) NSString *photoDefImageName __attribute__((deprecated("Use -photoDefImage."))); +@property (nonatomic, copy) NSString *photoOriginSelImageName __attribute__((deprecated("Use -photoOriginSelImage."))); +@property (nonatomic, copy) NSString *photoOriginDefImageName __attribute__((deprecated("Use -photoOriginDefImage."))); +@property (nonatomic, copy) NSString *photoPreviewOriginDefImageName __attribute__((deprecated("Use -photoPreviewOriginDefImage."))); +@property (nonatomic, copy) NSString *photoNumberIconImageName __attribute__((deprecated("Use -photoNumberIconImage."))); +@property (nonatomic, strong) UIImage *takePictureImage; +@property (nonatomic, strong) UIImage *addMorePhotoImage; +@property (nonatomic, strong) UIImage *photoSelImage; +@property (nonatomic, strong) UIImage *photoDefImage; +@property (nonatomic, strong) UIImage *photoOriginSelImage; +@property (nonatomic, strong) UIImage *photoOriginDefImage; +@property (nonatomic, strong) UIImage *photoPreviewOriginDefImage; +@property (nonatomic, strong) UIImage *photoNumberIconImage; + +#pragma mark - +/// Appearance / 外观颜色 + 按钮文字 +@property (nonatomic, strong) UIColor *oKButtonTitleColorNormal; +@property (nonatomic, strong) UIColor *oKButtonTitleColorDisabled; +@property (nonatomic, strong) UIColor *naviBgColor; +@property (nonatomic, strong) UIColor *naviTitleColor; +@property (nonatomic, strong) UIFont *naviTitleFont; +@property (nonatomic, strong) UIColor *barItemTextColor; +@property (nonatomic, strong) UIFont *barItemTextFont; + +@property (nonatomic, copy) NSString *doneBtnTitleStr; +@property (nonatomic, copy) NSString *cancelBtnTitleStr; +@property (nonatomic, copy) NSString *previewBtnTitleStr; +@property (nonatomic, copy) NSString *fullImageBtnTitleStr; +@property (nonatomic, copy) NSString *settingBtnTitleStr; +@property (nonatomic, copy) NSString *processHintStr; +@property (nonatomic, copy) NSString *editBtnTitleStr; +@property (nonatomic, copy) NSString *editViewCancelBtnTitleStr; + +/// Icon theme color, default is green color like wechat, the value is r:31 g:185 b:34. Currently only support image selection icon when showSelectedIndex is YES. If you need it, please set it as soon as possible +/// icon主题色,默认是微信的绿色,值是r:31 g:185 b:34。目前仅支持showSelectedIndex为YES时的图片选中icon。如需要,请尽早设置它。 +@property (strong, nonatomic) UIColor *iconThemeColor; + +#pragma mark - +- (void)cancelButtonClick; + +// For method annotations, see the corresponding method in TZImagePickerControllerDelegate / 方法注释见TZImagePickerControllerDelegate中对应方法 +@property (nonatomic, copy) void (^didFinishPickingPhotosHandle)(NSArray *photos,NSArray *assets,BOOL isSelectOriginalPhoto); +@property (nonatomic, copy) void (^didFinishPickingPhotosWithInfosHandle)(NSArray *photos,NSArray *assets,BOOL isSelectOriginalPhoto,NSArray *infos); +@property (nonatomic, copy) void (^imagePickerControllerDidCancelHandle)(void); +@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,PHAsset *asset); +@property (nonatomic, copy) void (^didFinishPickingAndEditingVideoHandle)(UIImage *coverImage,NSString *outputPath,NSString *errorMsg); +@property (nonatomic, copy) void (^didFinishPickingGifImageHandle)(UIImage *animatedImage,id sourceAssets); + +@property (nonatomic, weak) id pickerDelegate; + +@end + + +@protocol TZImagePickerControllerDelegate +@optional +// The picker should dismiss itself; when it dismissed these callback will be called. +// You can also set autoDismiss to NO, then the picker don't dismiss itself. +// If isOriginalPhoto is YES, user picked the original photo. +// You can get original photo with asset, by the method [[TZImageManager manager] getOriginalPhotoWithAsset:completion:]. +// The UIImage Object in photos default width is 828px, you can set it by photoWidth property. +// 这个照片选择器会自己dismiss,当选择器dismiss的时候,会执行下面的代理方法 +// 你也可以设置autoDismiss属性为NO,选择器就不会自己dismis了 +// 如果isSelectOriginalPhoto为YES,表明用户选择了原图 +// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:] +// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它 +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto; +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray *)infos; +- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker; + +/// 如果用户选择了某张照片下面的代理方法会被执行 +/// 如果isSelectOriginalPhoto为YES,表明用户选择了原图 +/// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:] +- (void)imagePickerController:(TZImagePickerController *)picker didSelectAsset:(PHAsset *)asset photo:(UIImage *)photo isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto; + +/// 如果用户取消选择了某张照片下面的代理方法会被执行 +/// 如果isSelectOriginalPhoto为YES,表明用户选择了原图 +/// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:] +- (void)imagePickerController:(TZImagePickerController *)picker didDeselectAsset:(PHAsset *)asset photo:(UIImage *)photo isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto; + +// If user picking a video and allowPickingMultipleVideo is NO, this callback will be called. +// If allowPickingMultipleVideo is YES, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +// 如果用户选择了一个视频且allowPickingMultipleVideo是NO,下面的代理方法会被执行 +// 如果allowPickingMultipleVideo是YES,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(PHAsset *)asset; + +// If allowEditVideo is YES and allowPickingMultipleVideo is NO, When user picking a video, this callback will be called. +// If allowPickingMultipleVideo is YES, video editing is not supported, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +// 当allowEditVideo是YES且allowPickingMultipleVideo是NO是,如果用户选择了一个视频,下面的代理方法会被执行 +// 如果allowPickingMultipleVideo是YES,则不支持编辑视频,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingAndEditingVideo:(UIImage *)coverImage outputPath:(NSString *)outputPath error:(NSString *)errorMsg; + +// When saving the edited video to the album fails, this callback will be called. +// 编辑后的视频自动保存到相册失败时,下面的代理方法会被执行 +- (void)imagePickerController:(TZImagePickerController *)picker didFailToSaveEditedVideoWithError:(NSError *)error; + +// If user picking a gif image and allowPickingMultipleVideo is NO, this callback will be called. +// If allowPickingMultipleVideo is YES, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +// 如果用户选择了一个gif图片且allowPickingMultipleVideo是NO,下面的代理方法会被执行 +// 如果allowPickingMultipleVideo是YES,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(PHAsset *)asset; + +// Decide album show or not't +// 决定相册显示与否 albumName:相册名字 result:相册原始数据 +- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(PHFetchResult *)result; + +// Decide asset show or not't +// 决定照片显示与否 +- (BOOL)isAssetCanSelect:(PHAsset *)asset __attribute__((deprecated("Use -isAssetCanBeDisplayed:."))); +- (BOOL)isAssetCanBeDisplayed:(PHAsset *)asset; + +// Decide asset can be selected +// 决定照片能否被选中 +- (BOOL)isAssetCanBeSelected:(PHAsset *)asset; +@end + + +@interface TZAlbumPickerController : UIViewController +@property (nonatomic, assign) NSInteger columnNumber; +@property (assign, nonatomic) BOOL isFirstAppear; +- (void)configTableView; +@end + + +@interface UIImage (MyBundle) ++ (UIImage *)tz_imageNamedFromMyBundle:(NSString *)name; +@end + + +@interface TZCommonTools : NSObject ++ (UIEdgeInsets)tz_safeAreaInsets; ++ (BOOL)tz_isIPhoneX; ++ (BOOL)tz_isLandscape; ++ (CGFloat)tz_statusBarHeight; +// 获得Info.plist数据字典 ++ (NSDictionary *)tz_getInfoDictionary; ++ (NSString *)tz_getAppName; ++ (BOOL)tz_isRightToLeftLayout; ++ (void)configBarButtonItem:(UIBarButtonItem *)item tzImagePickerVc:(TZImagePickerController *)tzImagePickerVc; ++ (BOOL)isICloudSyncError:(NSError *)error; ++ (BOOL)isAssetNotSelectable:(TZAssetModel *)model tzImagePickerVc:(TZImagePickerController *)tzImagePickerVc; +@end + + +@interface TZImagePickerConfig : NSObject ++ (instancetype)sharedInstance; +@property (copy, nonatomic) NSString *preferredLanguage; +@property(nonatomic, assign) BOOL allowPickingImage; +@property (nonatomic, assign) BOOL allowPickingVideo; +@property (strong, nonatomic) NSBundle *languageBundle; +@property (assign, nonatomic) BOOL showSelectedIndex; +@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer; +@property (assign, nonatomic) BOOL notScaleImage; +@property (assign, nonatomic) BOOL needFixComposition; + +/// 默认是50,如果一个GIF过大,里面图片个数可能超过1000,会导致内存飙升而崩溃 +@property (assign, nonatomic) NSInteger gifPreviewMaxImagesCount; +/// 【自定义GIF播放方案】为了避免内存过大,内部默认限制只播放50帧(平均取),可通过gifPreviewMaxImagesCount属性调整,若对GIF预览有更好的效果要求,可实现这个block采用FLAnimatedImage等三方库来播放,但注意FLAnimatedImage有播放速度较慢问题,自行取舍下。 +@property (nonatomic, copy) void (^gifImagePlayBlock)(TZPhotoPreviewView *view, UIImageView *imageView, NSData *gifData, NSDictionary *info); +@end diff --git a/TZImagePickerController/TZImagePickerController/TZImagePickerController.m b/TZImagePickerController/TZImagePickerController/TZImagePickerController.m new file mode 100644 index 0000000..656cb02 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImagePickerController.m @@ -0,0 +1,1131 @@ +// +// TZImagePickerController.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// version 3.8.8 - 2024.10.27 +// 更多信息,请前往项目的github地址:https://github.com/banchichen/TZImagePickerController + +#import "TZImagePickerController.h" +#import "TZPhotoPickerController.h" +#import "TZPhotoPreviewController.h" +#import "TZAssetModel.h" +#import "TZAssetCell.h" +#import "UIView+TZLayout.h" +#import "TZImageManager.h" +#import "TZVideoCropController.h" + +@interface TZImagePickerController () { + NSTimer *_timer; + UILabel *_tipLabel; + UIButton *_settingBtn; + BOOL _pushPhotoPickerVc; + BOOL _didPushPhotoPickerVc; + CGRect _cropRect; + + UIButton *_progressHUD; + UIView *_HUDContainer; + UIActivityIndicatorView *_HUDIndicatorView; + UILabel *_HUDLabel; + + UIStatusBarStyle _originStatusBarStyle; +} +/// Default is 4, Use in photos collectionView in TZPhotoPickerController +/// 默认4列, TZPhotoPickerController中的照片collectionView +@property (nonatomic, assign) NSInteger columnNumber; +@property (nonatomic, assign) NSInteger HUDTimeoutCount; ///< 超时隐藏HUD计数 +@end + +@implementation TZImagePickerController + +- (instancetype)init { + self = [super init]; + if (self) { + self = [self initWithMaxImagesCount:9 delegate:nil]; + } + return self; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (void)viewDidLoad { + [super viewDidLoad]; + self.needShowStatusBar = ![UIApplication sharedApplication].statusBarHidden; + if (@available(iOS 13.0, *)) { + self.view.backgroundColor = UIColor.tertiarySystemBackgroundColor; + } else { + self.view.backgroundColor = [UIColor whiteColor]; + } + self.navigationBar.barStyle = UIBarStyleBlack; + self.navigationBar.translucent = YES; + [TZImageManager manager].shouldFixOrientation = NO; + + // Default appearance, you can reset these after this method + // 默认的外观,你可以在这个方法后重置 + self.oKButtonTitleColorNormal = [UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0]; + self.oKButtonTitleColorDisabled = [UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:0.5]; + + self.navigationBar.barTintColor = [UIColor colorWithRed:(34/255.0) green:(34/255.0) blue:(34/255.0) alpha:1.0]; + self.navigationBar.tintColor = [UIColor whiteColor]; + self.automaticallyAdjustsScrollViewInsets = NO; + if (self.needShowStatusBar) [UIApplication sharedApplication].statusBarHidden = NO; +} + +- (void)setNaviBgColor:(UIColor *)naviBgColor { + _naviBgColor = naviBgColor; + self.navigationBar.barTintColor = naviBgColor; + [self configNavigationBarAppearance]; +} + +- (void)setNaviTitleColor:(UIColor *)naviTitleColor { + _naviTitleColor = naviTitleColor; + [self configNaviTitleAppearance]; +} + +- (void)setNaviTitleFont:(UIFont *)naviTitleFont { + _naviTitleFont = naviTitleFont; + [self configNaviTitleAppearance]; +} + +- (void)configNaviTitleAppearance { + NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; + if (self.naviTitleColor) { + textAttrs[NSForegroundColorAttributeName] = self.naviTitleColor; + } + if (self.naviTitleFont) { + textAttrs[NSFontAttributeName] = self.naviTitleFont; + } + self.navigationBar.titleTextAttributes = textAttrs; + [self configNavigationBarAppearance]; +} + +- (void)configNavigationBarAppearance { + if (@available(iOS 13.0, *)) { + UINavigationBarAppearance *barAppearance = [[UINavigationBarAppearance alloc] init]; + if (self.navigationBar.isTranslucent) { + UIColor *barTintColor = self.navigationBar.barTintColor; + barAppearance.backgroundColor = [barTintColor colorWithAlphaComponent:0.85]; + } else { + barAppearance.backgroundColor = self.navigationBar.barTintColor; + } + barAppearance.titleTextAttributes = self.navigationBar.titleTextAttributes; + self.navigationBar.standardAppearance = barAppearance; + self.navigationBar.scrollEdgeAppearance = barAppearance; + } +} + +- (void)setBarItemTextFont:(UIFont *)barItemTextFont { + _barItemTextFont = barItemTextFont; + [self configBarButtonItemAppearance]; +} + +- (void)setBarItemTextColor:(UIColor *)barItemTextColor { + _barItemTextColor = barItemTextColor; + [self configBarButtonItemAppearance]; +} + +- (void)setIsStatusBarDefault:(BOOL)isStatusBarDefault { + _isStatusBarDefault = isStatusBarDefault; + + if (isStatusBarDefault) { + self.statusBarStyle = UIStatusBarStyleDefault; + } else { + self.statusBarStyle = UIStatusBarStyleLightContent; + } +} + +- (void)configBarButtonItemAppearance { + UIBarButtonItem *barItem; + if (@available(iOS 9, *)) { + barItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]]; + } else { + barItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil]; + } + NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; + textAttrs[NSForegroundColorAttributeName] = self.barItemTextColor; + textAttrs[NSFontAttributeName] = self.barItemTextFont; + [barItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + _originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle; + [UIApplication sharedApplication].statusBarStyle = self.statusBarStyle; + [self configNavigationBarAppearance]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle; + [self hideProgressHUD]; +} + +- (UIStatusBarStyle)preferredStatusBarStyle { + return self.statusBarStyle; +} + +- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id)delegate { + return [self initWithMaxImagesCount:maxImagesCount columnNumber:4 delegate:delegate pushPhotoPickerVc:YES]; +} + +- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id)delegate { + return [self initWithMaxImagesCount:maxImagesCount columnNumber:columnNumber delegate:delegate pushPhotoPickerVc:YES]; +} + +- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id)delegate pushPhotoPickerVc:(BOOL)pushPhotoPickerVc { + _pushPhotoPickerVc = pushPhotoPickerVc; + TZAlbumPickerController *albumPickerVc = [[TZAlbumPickerController alloc] init]; + albumPickerVc.isFirstAppear = YES; + albumPickerVc.columnNumber = columnNumber; + self = [super initWithRootViewController:albumPickerVc]; + if (self) { + self.maxImagesCount = maxImagesCount > 0 ? maxImagesCount : 9; // Default is 9 / 默认最大可选9张图片 + self.pickerDelegate = delegate; + self.selectedAssets = [NSMutableArray array]; + + // Allow user picking original photo and video, you also can set No after this method + // 默认准许用户选择原图和视频, 你也可以在这个方法后置为NO + self.allowPickingOriginalPhoto = YES; + self.allowPickingVideo = YES; + self.allowPickingImage = YES; + self.allowTakePicture = YES; + self.allowTakeVideo = YES; + self.videoMaximumDuration = 10 * 60; + self.sortAscendingByModificationDate = YES; + self.columnNumber = columnNumber; + [self configDefaultSetting]; + + if (![[TZImageManager manager] authorizationStatusAuthorized]) { + _tipLabel = [[UILabel alloc] init]; + _tipLabel.frame = CGRectMake(8, 120, self.view.tz_width - 16, 60); + _tipLabel.textAlignment = NSTextAlignmentCenter; + _tipLabel.numberOfLines = 0; + _tipLabel.font = [UIFont systemFontOfSize:16]; + _tipLabel.textColor = [UIColor blackColor]; + _tipLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + NSString *appName = [TZCommonTools tz_getAppName]; + NSString *tipText = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Allow %@ to access your album in \"Settings -> Privacy -> Photos\""],appName]; + _tipLabel.text = tipText; + [self.view addSubview:_tipLabel]; + + _settingBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [_settingBtn setTitle:self.settingBtnTitleStr forState:UIControlStateNormal]; + _settingBtn.frame = CGRectMake(0, 180, self.view.tz_width, 44); + _settingBtn.titleLabel.font = [UIFont systemFontOfSize:18]; + [_settingBtn addTarget:self action:@selector(settingBtnClick) forControlEvents:UIControlEventTouchUpInside]; + _settingBtn.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + [self.view addSubview:_settingBtn]; + + if ([PHPhotoLibrary authorizationStatus] == 0) { + _timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:NO]; + } + } else { + [self pushPhotoPickerVc]; + } + } + return self; +} + +/// This init method just for previewing photos / 用这个初始化方法以预览图片 +- (instancetype)initWithSelectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index{ + TZPhotoPreviewController *previewVc = [[TZPhotoPreviewController alloc] init]; + self = [super initWithRootViewController:previewVc]; + if (self) { + self.selectedAssets = [NSMutableArray arrayWithArray:selectedAssets]; + self.allowPickingOriginalPhoto = self.allowPickingOriginalPhoto; + [self configDefaultSetting]; + + previewVc.photos = [NSMutableArray arrayWithArray:selectedPhotos]; + previewVc.currentIndex = index; + __weak typeof(self) weakSelf = self; + [previewVc setDoneButtonClickBlockWithPreviewType:^(NSArray *photos, NSArray *assets, BOOL isSelectOriginalPhoto) { + __strong typeof(weakSelf) strongSelf = weakSelf; + if (!strongSelf.autoDismiss) { + if (strongSelf.didFinishPickingPhotosHandle) { + strongSelf.didFinishPickingPhotosHandle(photos,assets,isSelectOriginalPhoto); + } + return; + } + [strongSelf dismissViewControllerAnimated:YES completion:^{ + if (!strongSelf) return; + if (strongSelf.didFinishPickingPhotosHandle) { + strongSelf.didFinishPickingPhotosHandle(photos,assets,isSelectOriginalPhoto); + } + }]; + }]; + } + return self; +} + +/// This init method for crop photo / 用这个初始化方法以裁剪图片 +- (instancetype)initCropTypeWithAsset:(PHAsset *)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,PHAsset *asset))completion { + TZPhotoPreviewController *previewVc = [[TZPhotoPreviewController alloc] init]; + self = [super initWithRootViewController:previewVc]; + if (self) { + self.maxImagesCount = 1; + self.allowPickingImage = YES; + self.allowCrop = YES; + self.selectedAssets = [NSMutableArray arrayWithArray:@[asset]]; + [self configDefaultSetting]; + + previewVc.photos = [NSMutableArray arrayWithArray:@[photo]]; + previewVc.isCropImage = YES; + previewVc.currentIndex = 0; + __weak typeof(self) weakSelf = self; + [previewVc setDoneButtonClickBlockCropMode:^(UIImage *cropImage, id asset) { + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf dismissViewControllerAnimated:YES completion:^{ + if (completion) { + completion(cropImage,asset); + } + }]; + }]; + } + return self; +} + +- (void)configDefaultSetting { + self.autoDismiss = YES; + self.autoSelectCurrentWhenDone = YES; + self.timeout = 30; + self.photoWidth = 828.0; + self.photoPreviewMaxWidth = 600; + self.naviTitleColor = [UIColor whiteColor]; + self.naviTitleFont = [UIFont systemFontOfSize:17]; + self.barItemTextFont = [UIFont systemFontOfSize:15]; + self.barItemTextColor = [UIColor whiteColor]; + self.allowPreview = YES; + // 2.2.26版本,不主动缩放图片,降低内存占用 + self.notScaleImage = YES; + self.needFixComposition = NO; + self.statusBarStyle = UIStatusBarStyleLightContent; + self.cannotSelectLayerColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8]; +#ifdef TZ_HAVE_LOCATION_CODE + self.allowCameraLocation = YES; +#endif + self.presetName = AVAssetExportPresetMediumQuality; + self.maxCropVideoDuration = 30; + + self.iconThemeColor = [UIColor colorWithRed:31 / 255.0 green:185 / 255.0 blue:34 / 255.0 alpha:1.0]; + [self configDefaultBtnTitle]; + + CGFloat cropViewWH = MIN(self.view.tz_width, self.view.tz_height) / 3 * 2; + self.cropRect = CGRectMake((self.view.tz_width - cropViewWH) / 2, (self.view.tz_height - cropViewWH) / 2, cropViewWH, cropViewWH); +} + +- (void)configDefaultImageName { + self.takePictureImageName = @"takePicture80"; + self.photoSelImageName = @"photo_sel_photoPickerVc"; + self.photoDefImageName = @"photo_def_photoPickerVc"; + self.photoNumberIconImage = [self createImageWithColor:nil size:CGSizeMake(24, 24) radius:12]; // @"photo_number_icon"; + self.photoPreviewOriginDefImageName = @"preview_original_def"; + self.photoOriginDefImageName = @"photo_original_def"; + self.photoOriginSelImageName = @"photo_original_sel"; + self.addMorePhotoImage = [UIImage tz_imageNamedFromMyBundle:@"addMore"]; +} + +- (void)setTakePictureImageName:(NSString *)takePictureImageName { + _takePictureImageName = takePictureImageName; + _takePictureImage = [UIImage tz_imageNamedFromMyBundle:takePictureImageName]; +} + +- (void)setPhotoSelImageName:(NSString *)photoSelImageName { + _photoSelImageName = photoSelImageName; + _photoSelImage = [UIImage tz_imageNamedFromMyBundle:photoSelImageName]; +} + +- (void)setPhotoDefImageName:(NSString *)photoDefImageName { + _photoDefImageName = photoDefImageName; + _photoDefImage = [UIImage tz_imageNamedFromMyBundle:photoDefImageName]; +} + +- (void)setPhotoNumberIconImageName:(NSString *)photoNumberIconImageName { + _photoNumberIconImageName = photoNumberIconImageName; + _photoNumberIconImage = [UIImage tz_imageNamedFromMyBundle:photoNumberIconImageName]; +} + +- (void)setPhotoPreviewOriginDefImageName:(NSString *)photoPreviewOriginDefImageName { + _photoPreviewOriginDefImageName = photoPreviewOriginDefImageName; + _photoPreviewOriginDefImage = [UIImage tz_imageNamedFromMyBundle:photoPreviewOriginDefImageName]; +} + +- (void)setPhotoOriginDefImageName:(NSString *)photoOriginDefImageName { + _photoOriginDefImageName = photoOriginDefImageName; + _photoOriginDefImage = [UIImage tz_imageNamedFromMyBundle:photoOriginDefImageName]; +} + +- (void)setPhotoOriginSelImageName:(NSString *)photoOriginSelImageName { + _photoOriginSelImageName = photoOriginSelImageName; + _photoOriginSelImage = [UIImage tz_imageNamedFromMyBundle:photoOriginSelImageName]; +} + +- (void)setTakePictureImage:(UIImage *)takePictureImage { + _takePictureImage = takePictureImage; + _takePictureImageName = @""; +} + +- (void)setIconThemeColor:(UIColor *)iconThemeColor { + _iconThemeColor = iconThemeColor; + [self configDefaultImageName]; +} + +- (void)configDefaultBtnTitle { + self.doneBtnTitleStr = [NSBundle tz_localizedStringForKey:@"Done"]; + self.cancelBtnTitleStr = [NSBundle tz_localizedStringForKey:@"Cancel"]; + self.previewBtnTitleStr = [NSBundle tz_localizedStringForKey:@"Preview"]; + self.fullImageBtnTitleStr = [NSBundle tz_localizedStringForKey:@"Full image"]; + self.settingBtnTitleStr = [NSBundle tz_localizedStringForKey:@"Setting"]; + self.processHintStr = [NSBundle tz_localizedStringForKey:@"Processing..."]; + self.editBtnTitleStr = [NSBundle tz_localizedStringForKey:@"Edit"]; +} + +- (void)setShowSelectedIndex:(BOOL)showSelectedIndex { + _showSelectedIndex = showSelectedIndex; + if (showSelectedIndex) { + self.photoSelImage = [self createImageWithColor:nil size:CGSizeMake(24, 24) radius:12]; + } + [TZImagePickerConfig sharedInstance].showSelectedIndex = showSelectedIndex; +} + +- (void)setShowPhotoCannotSelectLayer:(BOOL)showPhotoCannotSelectLayer { + _showPhotoCannotSelectLayer = showPhotoCannotSelectLayer; + [TZImagePickerConfig sharedInstance].showPhotoCannotSelectLayer = showPhotoCannotSelectLayer; +} + +- (void)setNotScaleImage:(BOOL)notScaleImage { + _notScaleImage = notScaleImage; + [TZImagePickerConfig sharedInstance].notScaleImage = notScaleImage; +} + +- (void)setNeedFixComposition:(BOOL)needFixComposition { + _needFixComposition = needFixComposition; + [TZImagePickerConfig sharedInstance].needFixComposition = needFixComposition; +} + +- (void)observeAuthrizationStatusChange { + [_timer invalidate]; + _timer = nil; + if ([PHPhotoLibrary authorizationStatus] == 0) { + _timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:NO]; + } + + if ([[TZImageManager manager] authorizationStatusAuthorized]) { + [_tipLabel removeFromSuperview]; + [_settingBtn removeFromSuperview]; + + [self pushPhotoPickerVc]; + + TZAlbumPickerController *albumPickerVc = (TZAlbumPickerController *)self.visibleViewController; + if ([albumPickerVc isKindOfClass:[TZAlbumPickerController class]]) { + [albumPickerVc configTableView]; + } + } +} + +- (void)pushPhotoPickerVc { + _didPushPhotoPickerVc = NO; + // 1.6.8 判断是否需要push到照片选择页,如果_pushPhotoPickerVc为NO,则不push + if (!_didPushPhotoPickerVc && _pushPhotoPickerVc) { + TZPhotoPickerController *photoPickerVc = [[TZPhotoPickerController alloc] init]; + photoPickerVc.isFirstAppear = YES; + photoPickerVc.columnNumber = self.columnNumber; + [[TZImageManager manager] getCameraRollAlbumWithFetchAssets:NO completion:^(TZAlbumModel *model) { + photoPickerVc.model = model; + [self pushViewController:photoPickerVc animated:YES]; + self->_didPushPhotoPickerVc = YES; + }]; + } +} + +- (UIAlertController *)showAlertWithTitle:(NSString *)title { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"OK"] style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alertController animated:YES completion:nil]; + return alertController; +} + +- (void)showProgressHUD { + if (!_progressHUD) { + _progressHUD = [UIButton buttonWithType:UIButtonTypeCustom]; + [_progressHUD setBackgroundColor:[UIColor clearColor]]; + + _HUDContainer = [[UIView alloc] init]; + _HUDContainer.layer.cornerRadius = 8; + _HUDContainer.clipsToBounds = YES; + _HUDContainer.backgroundColor = [UIColor darkGrayColor]; + _HUDContainer.alpha = 0.7; + + _HUDIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + + _HUDLabel = [[UILabel alloc] init]; + _HUDLabel.textAlignment = NSTextAlignmentCenter; + _HUDLabel.text = self.processHintStr; + _HUDLabel.font = [UIFont systemFontOfSize:15]; + _HUDLabel.textColor = [UIColor whiteColor]; + + [_HUDContainer addSubview:_HUDLabel]; + [_HUDContainer addSubview:_HUDIndicatorView]; + [_progressHUD addSubview:_HUDContainer]; + } + [_HUDIndicatorView startAnimating]; + UIWindow *applicationWindow; + if ([[[UIApplication sharedApplication] delegate] respondsToSelector:@selector(window)]) { + applicationWindow = [[[UIApplication sharedApplication] delegate] window]; + } else { + applicationWindow = [[UIApplication sharedApplication] keyWindow]; + } + [applicationWindow addSubview:_progressHUD]; + [self.view setNeedsLayout]; + + // if over time, dismiss HUD automatic + self.HUDTimeoutCount++; + __weak typeof(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.timeout * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.HUDTimeoutCount--; + if (strongSelf.HUDTimeoutCount <= 0) { + strongSelf.HUDTimeoutCount = 0; + [strongSelf hideProgressHUD]; + } + }); +} + +- (void)hideProgressHUD { + if (_progressHUD) { + [_HUDIndicatorView stopAnimating]; + [_progressHUD removeFromSuperview]; + } +} + +- (void)setMaxImagesCount:(NSInteger)maxImagesCount { + _maxImagesCount = maxImagesCount; + if (maxImagesCount > 1) { + _showSelectBtn = YES; + _allowCrop = NO; + } +} + +- (void)setShowSelectBtn:(BOOL)showSelectBtn { + _showSelectBtn = showSelectBtn; + // 多选模式下,不允许让showSelectBtn为NO + if (!showSelectBtn && _maxImagesCount > 1) { + _showSelectBtn = YES; + } +} + +- (void)setAllowCrop:(BOOL)allowCrop { + _allowCrop = _maxImagesCount > 1 ? NO : allowCrop; + if (allowCrop) { // 允许裁剪的时候,不能选原图和GIF + self.allowPickingOriginalPhoto = NO; + self.allowPickingGif = NO; + self.photoWidth = 1200; + self.photoPreviewMaxWidth = 1200; + } +} + +- (void)setCircleCropRadius:(NSInteger)circleCropRadius { + _circleCropRadius = circleCropRadius; + self.cropRect = CGRectMake(self.view.tz_width / 2 - circleCropRadius, self.view.tz_height / 2 - _circleCropRadius, _circleCropRadius * 2, _circleCropRadius * 2); +} + +- (void)setCropRect:(CGRect)cropRect { + _cropRect = cropRect; + if ([TZCommonTools tz_isLandscape]) { + _cropRectLandscape = cropRect; + CGFloat widthHeight = cropRect.size.height; + _cropRectPortrait = CGRectMake(cropRect.origin.y, (self.view.tz_width - widthHeight) / 2, widthHeight, widthHeight); + } else { + _cropRectPortrait = cropRect; + CGFloat widthHeight = cropRect.size.width; + _cropRectLandscape = CGRectMake((self.view.tz_height - widthHeight) / 2, cropRect.origin.x, widthHeight, widthHeight); + } +} + +- (CGRect)cropRect { + CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; + BOOL isFullScreen = self.view.tz_height == screenHeight; + if (isFullScreen) { + return _cropRect; + } else { + CGRect newCropRect = _cropRect; + newCropRect.origin.y -= ((screenHeight - self.view.tz_height) / 2); + return newCropRect; + } +} + +- (void)setTimeout:(NSInteger)timeout { + _timeout = timeout; + if (timeout < 5) { + _timeout = 5; + } else if (_timeout > 600) { + _timeout = 600; + } +} + +- (void)setPickerDelegate:(id)pickerDelegate { + _pickerDelegate = pickerDelegate; + [TZImageManager manager].pickerDelegate = pickerDelegate; +} + +- (void)setColumnNumber:(NSInteger)columnNumber { + _columnNumber = columnNumber; + if (columnNumber <= 2) { + _columnNumber = 2; + } else if (columnNumber >= 6) { + _columnNumber = 6; + } + + TZAlbumPickerController *albumPickerVc = [self.childViewControllers firstObject]; + albumPickerVc.columnNumber = _columnNumber; + [TZImageManager manager].columnNumber = _columnNumber; +} + +- (void)setMinPhotoWidthSelectable:(NSInteger)minPhotoWidthSelectable { + _minPhotoWidthSelectable = minPhotoWidthSelectable; + [TZImageManager manager].minPhotoWidthSelectable = minPhotoWidthSelectable; +} + +- (void)setMinPhotoHeightSelectable:(NSInteger)minPhotoHeightSelectable { + _minPhotoHeightSelectable = minPhotoHeightSelectable; + [TZImageManager manager].minPhotoHeightSelectable = minPhotoHeightSelectable; +} + +- (void)setHideWhenCanNotSelect:(BOOL)hideWhenCanNotSelect { + _hideWhenCanNotSelect = hideWhenCanNotSelect; + [TZImageManager manager].hideWhenCanNotSelect = hideWhenCanNotSelect; +} + +- (void)setPhotoPreviewMaxWidth:(CGFloat)photoPreviewMaxWidth { + _photoPreviewMaxWidth = photoPreviewMaxWidth; + if (photoPreviewMaxWidth > 800) { + _photoPreviewMaxWidth = 800; + } else if (photoPreviewMaxWidth < 500) { + _photoPreviewMaxWidth = 500; + } + [TZImageManager manager].photoPreviewMaxWidth = _photoPreviewMaxWidth; +} + +- (void)setPhotoWidth:(CGFloat)photoWidth { + _photoWidth = photoWidth; + [TZImageManager manager].photoWidth = photoWidth; +} + +- (void)setSelectedAssets:(NSMutableArray *)selectedAssets { + _selectedAssets = selectedAssets; + _selectedModels = [NSMutableArray array]; + _selectedAssetIds = [NSMutableArray array]; + for (PHAsset *asset in selectedAssets) { + TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:[[TZImageManager manager] getAssetType:asset]]; + model.isSelected = YES; + [self addSelectedModel:model]; + } +} + +- (void)setAllowPickingImage:(BOOL)allowPickingImage { + _allowPickingImage = allowPickingImage; + [TZImagePickerConfig sharedInstance].allowPickingImage = allowPickingImage; + if (!allowPickingImage) { + _allowTakePicture = NO; + } +} + +- (void)setAllowPickingVideo:(BOOL)allowPickingVideo { + _allowPickingVideo = allowPickingVideo; + [TZImagePickerConfig sharedInstance].allowPickingVideo = allowPickingVideo; + if (!allowPickingVideo) { + _allowTakeVideo = NO; + } +} + +- (void)setPreferredLanguage:(NSString *)preferredLanguage { + _preferredLanguage = preferredLanguage; + [TZImagePickerConfig sharedInstance].preferredLanguage = preferredLanguage; + [self configDefaultBtnTitle]; +} + +- (void)setLanguageBundle:(NSBundle *)languageBundle { + _languageBundle = languageBundle; + [TZImagePickerConfig sharedInstance].languageBundle = languageBundle; + [self configDefaultBtnTitle]; +} + +- (void)setSortAscendingByModificationDate:(BOOL)sortAscendingByModificationDate { + _sortAscendingByModificationDate = sortAscendingByModificationDate; + [TZImageManager manager].sortAscendingByModificationDate = sortAscendingByModificationDate; +} + +- (void)settingBtnClick { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; +} + +- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { + viewController.automaticallyAdjustsScrollViewInsets = NO; + [super pushViewController:viewController animated:animated]; +} + +- (void)dealloc { + // NSLog(@"%@ dealloc",NSStringFromClass(self.class)); +} + +- (void)addSelectedModel:(TZAssetModel *)model { + [_selectedModels addObject:model]; + [_selectedAssetIds addObject:model.asset.localIdentifier]; +} + +- (void)removeSelectedModel:(TZAssetModel *)model { + [_selectedModels removeObject:model]; + [_selectedAssetIds removeObject:model.asset.localIdentifier]; +} + +- (UIImage *)createImageWithColor:(UIColor *)color size:(CGSize)size radius:(CGFloat)radius { + if (!color) { + color = self.iconThemeColor; + } + CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, [color CGColor]); + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; + CGContextAddPath(context, path.CGPath); + CGContextFillPath(context); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + +#pragma mark - UIContentContainer + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (![UIApplication sharedApplication].statusBarHidden) { + if (self.needShowStatusBar) [UIApplication sharedApplication].statusBarHidden = NO; + } + }); + if (size.width > size.height) { + _cropRect = _cropRectLandscape; + } else { + _cropRect = _cropRectPortrait; + } +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + CGFloat progressHUDY = CGRectGetMaxY(self.navigationBar.frame); + _progressHUD.frame = CGRectMake(0, progressHUDY, self.view.tz_width, self.view.tz_height - progressHUDY); + _HUDContainer.frame = CGRectMake((self.view.tz_width - 120) / 2, (_progressHUD.tz_height - 90 - progressHUDY) / 2, 120, 90); + _HUDIndicatorView.frame = CGRectMake(45, 15, 30, 30); + _HUDLabel.frame = CGRectMake(0,40, 120, 50); +} + +#pragma mark - Public +- (void)cancelVc { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)cancelButtonClick { + if (self.autoDismiss) { + [self dismissViewControllerAnimated:YES completion:^{ + [self callDelegateMethod]; + }]; + } else { + [self callDelegateMethod]; + } +} + +- (void)callDelegateMethod { + if ([self.pickerDelegate respondsToSelector:@selector(tz_imagePickerControllerDidCancel:)]) { + [self.pickerDelegate tz_imagePickerControllerDidCancel:self]; + } + if (self.imagePickerControllerDidCancelHandle) { + self.imagePickerControllerDidCancelHandle(); + } +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + if ([self.topViewController isKindOfClass:TZVideoPlayerController.class] && self.topViewController.presentedViewController) { + return UIInterfaceOrientationMaskPortrait; + } + return UIInterfaceOrientationMaskAll; +} + +@end + + +@interface TZAlbumPickerController () { + UITableView *_tableView; +} +@property (nonatomic, strong) NSMutableArray *albumArr; +@end + +@implementation TZAlbumPickerController + +// 添加新的辅助方法 +- (UIBarButtonItem *)createBarButtonItemWithTitle:(NSString *)title target:(id)target { + UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, 44)]; + + UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; + button.frame = containerView.bounds; + [button setTitle:title forState:UIControlStateNormal]; + button.titleLabel.font = [UIFont systemFontOfSize:16]; + [button addTarget:target action:@selector(cancelButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentRight]; + [containerView addSubview:button]; + return [[UIBarButtonItem alloc] initWithCustomView:containerView]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + if ([[TZImageManager manager] authorizationStatusAuthorized] || !SYSTEM_VERSION_GREATER_THAN_15) { + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; + } + self.isFirstAppear = YES; + if (@available(iOS 13.0, *)) { + self.view.backgroundColor = UIColor.tertiarySystemBackgroundColor; + } else { + self.view.backgroundColor = [UIColor whiteColor]; + } + + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + self.navigationItem.rightBarButtonItem = [self createBarButtonItemWithTitle:imagePickerVc.cancelBtnTitleStr + target:imagePickerVc]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + [imagePickerVc hideProgressHUD]; + + if (imagePickerVc.allowPickingImage) { + self.navigationItem.title = [NSBundle tz_localizedStringForKey:@"Photos"]; + } else if (imagePickerVc.allowPickingVideo) { + self.navigationItem.title = [NSBundle tz_localizedStringForKey:@"Videos"]; + } + + if (self.isFirstAppear && !imagePickerVc.navLeftBarButtonSettingBlock) { + self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:[NSBundle tz_localizedStringForKey:@"Back"] + style:UIBarButtonItemStylePlain + target:nil + action:nil]; + } + + BOOL isRootViewController = (self.navigationController.viewControllers.firstObject == self); + NSString *buttonTitle = isRootViewController ? + [NSBundle tz_localizedStringForKey:@"Back"] : + imagePickerVc.cancelBtnTitleStr; + + if (!isRootViewController || imagePickerVc.cancelBtnTitleStr.length > 0) { + self.navigationItem.rightBarButtonItem = [self createBarButtonItemWithTitle:buttonTitle + target:imagePickerVc]; + } + [TZCommonTools configBarButtonItem:self.navigationItem.backBarButtonItem tzImagePickerVc:imagePickerVc]; + [self configTableView]; +} +- (void)configTableView { + if (![[TZImageManager manager] authorizationStatusAuthorized]) { + return; + } + + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + if (self.isFirstAppear) { + [imagePickerVc showProgressHUD]; + } + + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + [[TZImageManager manager] getAllAlbumsWithFetchAssets:!self.isFirstAppear completion:^(NSArray *models) { + dispatch_async(dispatch_get_main_queue(), ^{ + self->_albumArr = [NSMutableArray arrayWithArray:models]; + for (TZAlbumModel *albumModel in self->_albumArr) { + albumModel.selectedModels = imagePickerVc.selectedModels; + } + [imagePickerVc hideProgressHUD]; + + if (self.isFirstAppear) { + self.isFirstAppear = NO; + [self configTableView]; + } + + if (!self->_tableView) { + self->_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + self->_tableView.rowHeight = 70; + if (@available(iOS 13.0, *)) { + self->_tableView.backgroundColor = [UIColor tertiarySystemBackgroundColor]; + } else { + self->_tableView.backgroundColor = [UIColor whiteColor]; + } + self->_tableView.tableFooterView = [[UIView alloc] init]; + self->_tableView.dataSource = self; + self->_tableView.delegate = self; + [self->_tableView registerClass:[TZAlbumCell class] forCellReuseIdentifier:@"TZAlbumCell"]; + [self.view addSubview:self->_tableView]; + if (imagePickerVc.albumPickerPageUIConfigBlock) { + imagePickerVc.albumPickerPageUIConfigBlock(self->_tableView); + } + } else { + [self->_tableView reloadData]; + } + }); + }]; + }); +} + +- (void)dealloc { + [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; + // NSLog(@"%@ dealloc",NSStringFromClass(self.class)); +} + +- (UIStatusBarStyle)preferredStatusBarStyle { + TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController; + if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) { + return tzImagePicker.statusBarStyle; + } + return [super preferredStatusBarStyle]; +} + +#pragma mark - PHPhotoLibraryChangeObserver + +- (void)photoLibraryDidChange:(PHChange *)changeInstance { + dispatch_async(dispatch_get_main_queue(), ^{ + [self configTableView]; + }); +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + CGFloat top = 0; + CGFloat tableViewHeight = 0; + CGFloat naviBarHeight = self.navigationController.navigationBar.tz_height; + BOOL isStatusBarHidden = [UIApplication sharedApplication].isStatusBarHidden; + BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height; + if (self.navigationController.navigationBar.isTranslucent) { + top = naviBarHeight; + if (!isStatusBarHidden && isFullScreen) top += [TZCommonTools tz_statusBarHeight]; + tableViewHeight = self.view.tz_height - top; + } else { + tableViewHeight = self.view.tz_height; + } + _tableView.frame = CGRectMake(0, top, self.view.tz_width, tableViewHeight); + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + if (imagePickerVc.albumPickerPageDidLayoutSubviewsBlock) { + imagePickerVc.albumPickerPageDidLayoutSubviewsBlock(_tableView); + } +} + +#pragma mark - UITableViewDataSource && Delegate + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _albumArr.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + TZAlbumCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TZAlbumCell"]; + if (@available(iOS 13.0, *)) { + cell.backgroundColor = UIColor.tertiarySystemBackgroundColor; + } + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + cell.albumCellDidLayoutSubviewsBlock = imagePickerVc.albumCellDidLayoutSubviewsBlock; + cell.albumCellDidSetModelBlock = imagePickerVc.albumCellDidSetModelBlock; + cell.selectedCountButton.backgroundColor = imagePickerVc.iconThemeColor; + cell.model = _albumArr[indexPath.row]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + TZPhotoPickerController *photoPickerVc = [[TZPhotoPickerController alloc] init]; + photoPickerVc.columnNumber = self.columnNumber; + TZAlbumModel *model = _albumArr[indexPath.row]; + photoPickerVc.model = model; + [self.navigationController pushViewController:photoPickerVc animated:YES]; + [tableView deselectRowAtIndexPath:indexPath animated:NO]; +} + +#pragma clang diagnostic pop + +@end + + +@implementation UIImage (MyBundle) + ++ (UIImage *)tz_imageNamedFromMyBundle:(NSString *)name { + NSBundle *imageBundle = [NSBundle tz_imagePickerBundle]; + name = [name stringByAppendingString:@"@2x"]; + NSString *imagePath = [imageBundle pathForResource:name ofType:@"png"]; + UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; + if (!image) { + // 兼容业务方自己设置图片的方式 + name = [name stringByReplacingOccurrencesOfString:@"@2x" withString:@""]; + image = [UIImage imageNamed:name]; + } + return image; +} + +@end + + +@implementation TZCommonTools + ++ (UIEdgeInsets)tz_safeAreaInsets { + UIWindow *window = [UIApplication sharedApplication].windows.firstObject; + if (![window isKeyWindow]) { + UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; + if (CGRectEqualToRect(keyWindow.bounds, [UIScreen mainScreen].bounds)) { + window = keyWindow; + } + } + if (@available(iOS 11.0, *)) { + UIEdgeInsets insets = [window safeAreaInsets]; + return insets; + } + return UIEdgeInsetsZero; +} + ++ (BOOL)tz_isIPhoneX { + if ([UIWindow instancesRespondToSelector:@selector(safeAreaInsets)]) { + return [self tz_safeAreaInsets].bottom > 0; + } + return (CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(375, 812)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(812, 375)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(414, 896)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(896, 414)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(390, 844)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(844, 390)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(428, 926)) || + CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(926, 428))); +} + ++ (BOOL)tz_isLandscape { + if ([UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeRight || + [UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeLeft) { + return true; + } + return false; +} + ++ (CGFloat)tz_statusBarHeight { + if ([UIWindow instancesRespondToSelector:@selector(safeAreaInsets)]) { + return [self tz_safeAreaInsets].top ?: 20; + } + return 20; +} + +// 获得Info.plist数据字典 ++ (NSDictionary *)tz_getInfoDictionary { + NSDictionary *infoDict = [NSBundle mainBundle].localizedInfoDictionary; + if (!infoDict || !infoDict.count) { + infoDict = [NSBundle mainBundle].infoDictionary; + } + if (!infoDict || !infoDict.count) { + NSString *path = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"]; + infoDict = [NSDictionary dictionaryWithContentsOfFile:path]; + } + return infoDict ? infoDict : @{}; +} + ++ (NSString *)tz_getAppName { + NSDictionary *infoDict = [self tz_getInfoDictionary]; + NSString *appName = [infoDict valueForKey:@"CFBundleDisplayName"]; + if (!appName) appName = [infoDict valueForKey:@"CFBundleName"]; + if (!appName) appName = [infoDict valueForKey:@"CFBundleExecutable"]; + if (!appName) { + infoDict = [NSBundle mainBundle].infoDictionary; + appName = [infoDict valueForKey:@"CFBundleDisplayName"]; + if (!appName) appName = [infoDict valueForKey:@"CFBundleName"]; + if (!appName) appName = [infoDict valueForKey:@"CFBundleExecutable"]; + } + return appName; +} + ++ (BOOL)tz_isRightToLeftLayout { + if (@available(iOS 9.0, *)) { + if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:UIView.appearance.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) { + return YES; + } + } else { + NSString *preferredLanguage = [NSLocale preferredLanguages].firstObject; + if ([preferredLanguage hasPrefix:@"ar-"]) { + return YES; + } + } + return NO; +} + ++ (void)configBarButtonItem:(UIBarButtonItem *)item tzImagePickerVc:(TZImagePickerController *)tzImagePickerVc { + item.tintColor = tzImagePickerVc.barItemTextColor; + NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; + textAttrs[NSForegroundColorAttributeName] = tzImagePickerVc.barItemTextColor; + textAttrs[NSFontAttributeName] = tzImagePickerVc.barItemTextFont; + [item setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; + + NSMutableDictionary *textAttrsHighlighted = [NSMutableDictionary dictionary]; + textAttrsHighlighted[NSFontAttributeName] = tzImagePickerVc.barItemTextFont; + [item setTitleTextAttributes:textAttrsHighlighted forState:UIControlStateHighlighted]; +} + ++ (BOOL)isICloudSyncError:(NSError *)error { + if (!error) return NO; + if ([error.domain isEqualToString:@"CKErrorDomain"] || [error.domain isEqualToString:@"CloudPhotoLibraryErrorDomain"]) { + return YES; + } + return NO; +} + ++ (BOOL)isAssetNotSelectable:(TZAssetModel *)model tzImagePickerVc:(TZImagePickerController *)tzImagePickerVc { + BOOL notSelectable = tzImagePickerVc.selectedModels.count >= tzImagePickerVc.maxImagesCount; + if (tzImagePickerVc.selectedModels && tzImagePickerVc.selectedModels.count > 0 && !tzImagePickerVc.allowPickingMultipleVideo) { + if (model.asset.mediaType == PHAssetMediaTypeVideo) { + notSelectable = true; + } + } + return notSelectable; +} + +@end + + +@interface TZImagePickerConfig () +@property (strong, nonatomic) NSSet *supportedLanguages; +@end + +@implementation TZImagePickerConfig + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static TZImagePickerConfig *config = nil; + dispatch_once(&onceToken, ^{ + if (config == nil) { + config = [[TZImagePickerConfig alloc] init]; + config.supportedLanguages = [NSSet setWithObjects:@"zh-Hans", @"zh-Hant", @"en", @"ar", @"de", @"es", @"fr", @"ja", @"ko-KP", @"pt", @"ru", @"vi", nil]; + config.preferredLanguage = nil; + config.gifPreviewMaxImagesCount = 50; + } + }); + return config; +} + +- (void)setPreferredLanguage:(NSString *)preferredLanguage { + _preferredLanguage = preferredLanguage; + + if (!preferredLanguage || !preferredLanguage.length) { + preferredLanguage = [NSLocale preferredLanguages].firstObject; + } + + NSString *usedLanguage = @"en"; + for (NSString *language in self.supportedLanguages) { + if ([preferredLanguage hasPrefix:language]) { + usedLanguage = language; + break; + } + } + _languageBundle = [NSBundle bundleWithPath:[[NSBundle tz_imagePickerBundle] pathForResource:usedLanguage ofType:@"lproj"]]; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZImageRequestOperation.h b/TZImagePickerController/TZImagePickerController/TZImageRequestOperation.h new file mode 100644 index 0000000..89b9676 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImageRequestOperation.h @@ -0,0 +1,30 @@ +// +// TZImageRequestOperation.h +// TZImagePickerControllerFramework +// +// Created by 谭真 on 2018/12/20. +// Copyright © 2018 谭真. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TZImageRequestOperation : NSOperation + +typedef void(^TZImageRequestCompletedBlock)(UIImage *photo, NSDictionary *info, BOOL isDegraded); +typedef void(^TZImageRequestProgressBlock)(double progress, NSError *error, BOOL *stop, NSDictionary *info); + +@property (nonatomic, copy, nullable) TZImageRequestCompletedBlock completedBlock; +@property (nonatomic, copy, nullable) TZImageRequestProgressBlock progressBlock; +@property (nonatomic, strong, nullable) PHAsset *asset; + +@property (assign, nonatomic, getter = isExecuting) BOOL executing; +@property (assign, nonatomic, getter = isFinished) BOOL finished; + +- (instancetype)initWithAsset:(PHAsset *)asset completion:(TZImageRequestCompletedBlock)completionBlock progressHandler:(TZImageRequestProgressBlock)progressHandler; +- (void)done; +@end + +NS_ASSUME_NONNULL_END diff --git a/TZImagePickerController/TZImagePickerController/TZImageRequestOperation.m b/TZImagePickerController/TZImagePickerController/TZImageRequestOperation.m new file mode 100644 index 0000000..358c5ed --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZImageRequestOperation.m @@ -0,0 +1,77 @@ +// +// TZImageRequestOperation.m +// TZImagePickerControllerFramework +// +// Created by 谭真 on 2018/12/20. +// Copyright © 2018 谭真. All rights reserved. +// + +#import "TZImageRequestOperation.h" +#import "TZImageManager.h" + +@implementation TZImageRequestOperation + +@synthesize executing = _executing; +@synthesize finished = _finished; + +- (instancetype)initWithAsset:(PHAsset *)asset completion:(TZImageRequestCompletedBlock)completionBlock progressHandler:(TZImageRequestProgressBlock)progressHandler { + self = [super init]; + self.asset = asset; + self.completedBlock = completionBlock; + self.progressBlock = progressHandler; + _executing = NO; + _finished = NO; + return self; +} + +- (void)start { + self.executing = YES; + [[TZImageManager manager] getPhotoWithAsset:self.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (!isDegraded) { + if (self.completedBlock) { + self.completedBlock(photo, info, isDegraded); + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self done]; + }); + } + }); + } progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.progressBlock) { + self.progressBlock(progress, error, stop, info); + } + }); + } networkAccessAllowed:YES]; +} + +- (void)done { + self.finished = YES; + self.executing = NO; + [self reset]; +} + +- (void)reset { + self.asset = nil; + self.completedBlock = nil; + self.progressBlock = nil; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _finished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _executing = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isAsynchronous { + return YES; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPickerController.h b/TZImagePickerController/TZImagePickerController/TZPhotoPickerController.h new file mode 100644 index 0000000..8400be2 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPickerController.h @@ -0,0 +1,27 @@ +// +// TZPhotoPickerController.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@class TZAlbumModel; +@interface TZPhotoPickerController : UIViewController + +@property (nonatomic, assign) BOOL isFirstAppear; +@property (nonatomic, assign) NSInteger columnNumber; +@property (nonatomic, strong) TZAlbumModel *model; +/** + * 加载更多资源 + * 当用户下拉时触发加载更多旧照片 + */ +- (void)loadMoreAssets; +@end + + +@interface TZCollectionView : UICollectionView + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPickerController.m b/TZImagePickerController/TZImagePickerController/TZPhotoPickerController.m new file mode 100755 index 0000000..6156376 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPickerController.m @@ -0,0 +1,1377 @@ +// +// TZPhotoPickerController.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "TZPhotoPickerController.h" +#import "TZImagePickerController.h" +#import "TZPhotoPreviewController.h" +#import "TZAssetCell.h" +#import "TZAssetModel.h" +#import "UIView+TZLayout.h" +#import "TZImageManager.h" +#import "TZVideoPlayerController.h" +#import "TZGifPhotoPreviewController.h" +#import +#import "TZImageRequestOperation.h" +#import "TZAuthLimitedFooterTipView.h" +#import +@interface TZPhotoPickerController () { + NSMutableArray *_models; + + UIView *_bottomToolBar; + UIButton *_previewButton; + UIButton *_doneButton; + UIImageView *_numberImageView; + UILabel *_numberLabel; + UIButton *_originalPhotoButton; + UILabel *_originalPhotoLabel; + UIView *_divideLine; + + BOOL _shouldScrollToBottom; + BOOL _showTakePhotoBtn; + BOOL _authorizationLimited; + + CGFloat _offsetItemCount; +} +@property CGRect previousPreheatRect; +@property (nonatomic, assign) BOOL isSelectOriginalPhoto; +@property (nonatomic, strong) TZCollectionView *collectionView; +@property (nonatomic, strong) TZAuthLimitedFooterTipView *authFooterTipView; +@property (nonatomic, strong) UILabel *noDataLabel; +@property (strong, nonatomic) UICollectionViewFlowLayout *layout; +@property (nonatomic, strong) UIImagePickerController *imagePickerVc; +@property (strong, nonatomic) CLLocation *location; +@property (nonatomic, strong) NSOperationQueue *operationQueue; +@property (nonatomic, assign) BOOL isSavingMedia; +@property (nonatomic, assign) BOOL isFetchingMedia; +@property (nonatomic, assign) BOOL isLoadingMore; +@property (nonatomic, strong) UIActivityIndicatorView *loadingIndicator; +@property (nonatomic, assign) BOOL canLoadMore; +@property (nonatomic, strong) NSDate *lastLoadTime; + +@end + +static CGSize AssetGridThumbnailSize; +static CGFloat itemMargin = 5; + +@implementation TZPhotoPickerController + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (UIImagePickerController *)imagePickerVc { + if (_imagePickerVc == nil) { + _imagePickerVc = [[UIImagePickerController alloc] init]; + _imagePickerVc.delegate = self; + // set appearance / 改变相册选择页的导航栏外观 + _imagePickerVc.navigationBar.barTintColor = self.navigationController.navigationBar.barTintColor; + _imagePickerVc.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; + UIBarButtonItem *tzBarItem, *BarItem; + if (@available(iOS 9, *)) { + tzBarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]]; + BarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UIImagePickerController class]]]; + } else { + tzBarItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil]; + BarItem = [UIBarButtonItem appearanceWhenContainedIn:[UIImagePickerController class], nil]; + } + NSDictionary *titleTextAttributes = [tzBarItem titleTextAttributesForState:UIControlStateNormal]; + [BarItem setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal]; + } + return _imagePickerVc; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + if ([[TZImageManager manager] authorizationStatusAuthorized] || !SYSTEM_VERSION_GREATER_THAN_15) { + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; + } + self.isFirstAppear = YES; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + _isSelectOriginalPhoto = tzImagePickerVc.isSelectOriginalPhoto; + _shouldScrollToBottom = YES; + if (@available(iOS 13.0, *)) { + self.view.backgroundColor = UIColor.tertiarySystemBackgroundColor; + } else { + self.view.backgroundColor = [UIColor whiteColor]; + } + self.navigationItem.title = _model.name; + UIBarButtonItem *galleryItem = [[UIBarButtonItem alloc] initWithTitle:tzImagePickerVc.cancelBtnTitleStr style:UIBarButtonItemStylePlain target:self action:@selector(galleryItemClick)]; + [TZCommonTools configBarButtonItem:galleryItem tzImagePickerVc:tzImagePickerVc]; + self.navigationItem.rightBarButtonItem = galleryItem; + if (tzImagePickerVc.navLeftBarButtonSettingBlock) { + UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeCustom]; + leftButton.frame = CGRectMake(0, 0, 44, 44); + [leftButton addTarget:tzImagePickerVc action:@selector(cancelButtonClick) forControlEvents:UIControlEventTouchUpInside]; + tzImagePickerVc.navLeftBarButtonSettingBlock(leftButton); + UIBarButtonItem *leftItem1 = [[UIBarButtonItem alloc] initWithCustomView:leftButton]; + [TZCommonTools configBarButtonItem:leftItem1 tzImagePickerVc:tzImagePickerVc]; + self.navigationItem.leftBarButtonItem = leftItem1; + } else if (tzImagePickerVc.childViewControllers.count) { + UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:[NSBundle tz_localizedStringForKey:@"Back"] style:UIBarButtonItemStylePlain target:tzImagePickerVc action:@selector(cancelButtonClick)]; + [TZCommonTools configBarButtonItem:backItem tzImagePickerVc:tzImagePickerVc]; + self.navigationItem.leftBarButtonItem = backItem; + } + _showTakePhotoBtn = _model.isCameraRoll && ((tzImagePickerVc.allowTakePicture && tzImagePickerVc.allowPickingImage) || (tzImagePickerVc.allowTakeVideo && tzImagePickerVc.allowPickingVideo)); + _authorizationLimited = _model.isCameraRoll && [[TZImageManager manager] isPHAuthorizationStatusLimited]; + // [self resetCachedAssets]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; + + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 3; + + // 初始化加载指示器 + self.loadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + self.loadingIndicator.hidesWhenStopped = YES; + [self.view addSubview:self.loadingIndicator]; + + // 确保初始化时不会触发加载 + self.isLoadingMore = NO; + self.lastLoadTime = [NSDate date]; + + // 初始化时禁用滚动 + self.collectionView.scrollEnabled = NO; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + self.collectionView.scrollEnabled = YES; + }); +} + +- (void)fetchAssetModels { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; +// if (_isFirstAppear && !_model.models.count) { +// [tzImagePickerVc showProgressHUD]; +// } + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + if (!tzImagePickerVc.sortAscendingByModificationDate && self->_isFirstAppear && self->_model.isCameraRoll) { + [[TZImageManager manager] getCameraRollAlbumWithFetchAssets:YES completion:^(TZAlbumModel *model) { + self->_model = model; + self->_models = [NSMutableArray arrayWithArray:self->_model.models]; + [self initSubviews]; + }]; + } else { + [[TZImageManager manager] getAssetsFromFetchResult:self->_model.result completion:^(NSArray *models) { + self->_models = [NSMutableArray arrayWithArray:models]; + [self initSubviews]; + }]; + } + }); +} + +- (void)initSubviews { + dispatch_async(dispatch_get_main_queue(), ^{ +// TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; +// [tzImagePickerVc hideProgressHUD]; + + [self checkSelectedModels]; + [self configCollectionView]; + self->_collectionView.hidden = YES; + [self configBottomToolBar]; + [self prepareScrollCollectionViewToBottom]; + }); +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + tzImagePickerVc.isSelectOriginalPhoto = _isSelectOriginalPhoto; +} + +- (BOOL)prefersStatusBarHidden { + return NO; +} + +- (UIStatusBarStyle)preferredStatusBarStyle { + TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController; + if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) { + return tzImagePicker.statusBarStyle; + } + return [super preferredStatusBarStyle]; +} + +- (void)configCollectionView { + if (!_collectionView) { + _layout = [[UICollectionViewFlowLayout alloc] init]; + _collectionView = [[TZCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout]; + if (@available(iOS 13.0, *)) { + _collectionView.backgroundColor = UIColor.tertiarySystemBackgroundColor; + } else { + _collectionView.backgroundColor = [UIColor whiteColor]; + } + _collectionView.dataSource = self; + _collectionView.delegate = self; + _collectionView.alwaysBounceHorizontal = NO; + _collectionView.contentInset = UIEdgeInsetsMake(itemMargin, itemMargin, itemMargin, itemMargin); + [self.view addSubview:_collectionView]; + [_collectionView registerClass:[TZAssetCell class] forCellWithReuseIdentifier:@"TZAssetCell"]; + [_collectionView registerClass:[TZAssetCameraCell class] forCellWithReuseIdentifier:@"TZAssetCameraCell"]; + [_collectionView registerClass:[TZAssetAddMoreCell class] forCellWithReuseIdentifier:@"TZAssetAddMoreCell"]; + } else { + [_collectionView reloadData]; + } + + if (!_authFooterTipView && _authorizationLimited) { + _authFooterTipView = [[TZAuthLimitedFooterTipView alloc] initWithFrame:CGRectMake(0, 0, self.view.tz_width, 80)]; + UITapGestureRecognizer *footTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openSettingsApplication)]; + [_authFooterTipView addGestureRecognizer:footTap]; + [self.view addSubview:_authFooterTipView]; + } + + _collectionView.contentSize = CGSizeMake(self.view.tz_width, (([self getAllCellCount] + self.columnNumber - 1) / self.columnNumber) * self.view.tz_width); + if (_models.count == 0) { + [_collectionView addSubview:self.noDataLabel]; + } else if (_noDataLabel) { + [_noDataLabel removeFromSuperview]; + _noDataLabel = nil; + } +} + +- (UILabel *)noDataLabel { + if (!_noDataLabel) { + _noDataLabel = [[UILabel alloc] initWithFrame:_collectionView.bounds]; + _noDataLabel.textAlignment = NSTextAlignmentCenter; + _noDataLabel.text = [NSBundle tz_localizedStringForKey:@"No Photos or Videos"]; + CGFloat rgb = 153 / 256.0; + _noDataLabel.textColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; + _noDataLabel.font = [UIFont boldSystemFontOfSize:20]; + } + return _noDataLabel; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + // Determine the size of the thumbnails to request from the PHCachingImageManager + CGFloat scale = 2.0; + if ([UIScreen mainScreen].bounds.size.width > 600) { + scale = 1.0; + } + CGSize cellSize = ((UICollectionViewFlowLayout *)_collectionView.collectionViewLayout).itemSize; + AssetGridThumbnailSize = CGSizeMake(cellSize.width * scale, cellSize.height * scale); + + if (!_models) { + [self fetchAssetModels]; + } +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + self.isFirstAppear = NO; + // [self updateCachedAssets]; +} + +- (void)configBottomToolBar { + if (_bottomToolBar) return; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (!tzImagePickerVc.showSelectBtn) return; + + _bottomToolBar = [[UIView alloc] initWithFrame:CGRectZero]; + CGFloat rgb = 253 / 255.0; + if (@available(iOS 13.0, *)) { + _bottomToolBar.backgroundColor = UIColor.tertiarySystemBackgroundColor; + } else { + _bottomToolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; + } + + _previewButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_previewButton addTarget:self action:@selector(previewButtonClick) forControlEvents:UIControlEventTouchUpInside]; + _previewButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_previewButton setTitle:tzImagePickerVc.previewBtnTitleStr forState:UIControlStateNormal]; + [_previewButton setTitle:tzImagePickerVc.previewBtnTitleStr forState:UIControlStateDisabled]; + if (@available(iOS 13.0, *)) { + [_previewButton setTitleColor:UIColor.labelColor forState:UIControlStateNormal]; + } else { + [_previewButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + } + [_previewButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled]; + _previewButton.enabled = tzImagePickerVc.selectedModels.count; + + if (tzImagePickerVc.allowPickingOriginalPhoto) { + _originalPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, [TZCommonTools tz_isRightToLeftLayout] ? 10 : -10, 0, 0); + [_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside]; + _originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_originalPhotoButton setTitle:tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateNormal]; + [_originalPhotoButton setTitle:tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateSelected]; + [_originalPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + if (@available(iOS 13.0, *)) { + [_originalPhotoButton setTitleColor:[UIColor labelColor] forState:UIControlStateSelected]; + } else { + [_originalPhotoButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected]; + } + [_originalPhotoButton setImage:tzImagePickerVc.photoOriginDefImage forState:UIControlStateNormal]; + [_originalPhotoButton setImage:tzImagePickerVc.photoOriginSelImage forState:UIControlStateSelected]; + _originalPhotoButton.imageView.clipsToBounds = YES; + _originalPhotoButton.imageView.contentMode = UIViewContentModeScaleAspectFit; + _originalPhotoButton.selected = _isSelectOriginalPhoto; + _originalPhotoButton.enabled = tzImagePickerVc.selectedModels.count > 0; + + _originalPhotoLabel = [[UILabel alloc] init]; + _originalPhotoLabel.textAlignment = NSTextAlignmentLeft; + _originalPhotoLabel.font = [UIFont systemFontOfSize:16]; + if (@available(iOS 13.0, *)) { + _originalPhotoLabel.textColor = [UIColor labelColor]; + } else { + _originalPhotoLabel.textColor = [UIColor blackColor]; + } + if (_isSelectOriginalPhoto) [self getSelectedPhotoBytes]; + } + + _doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _doneButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal]; + [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateDisabled]; + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal]; + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled]; + _doneButton.enabled = tzImagePickerVc.selectedModels.count || tzImagePickerVc.alwaysEnableDoneBtn; + + _numberImageView = [[UIImageView alloc] initWithImage:tzImagePickerVc.photoNumberIconImage]; + _numberImageView.hidden = tzImagePickerVc.selectedModels.count <= 0; + _numberImageView.clipsToBounds = YES; + _numberImageView.contentMode = UIViewContentModeScaleAspectFit; + _numberImageView.backgroundColor = [UIColor clearColor]; + + _numberLabel = [[UILabel alloc] init]; + _numberLabel.font = [UIFont systemFontOfSize:15]; + _numberLabel.adjustsFontSizeToFitWidth = YES; + _numberLabel.textColor = [UIColor whiteColor]; + _numberLabel.textAlignment = NSTextAlignmentCenter; + _numberLabel.text = [NSString stringWithFormat:@"%zd",tzImagePickerVc.selectedModels.count]; + _numberLabel.hidden = tzImagePickerVc.selectedModels.count <= 0; + _numberLabel.backgroundColor = [UIColor clearColor]; + _numberLabel.userInteractionEnabled = YES; + + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doneButtonClick)]; + [_numberLabel addGestureRecognizer:tapGesture]; + + _divideLine = [[UIView alloc] init]; + CGFloat rgb2 = 222 / 255.0; + if (@available(iOS 13.0, *)) { + UIColor *divideLineDyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) { + if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) { + return [UIColor colorWithRed:rgb2 green:rgb2 blue:rgb2 alpha:1.0]; + } else { + CGFloat lineDarkRgb = 100 / 255.0; + return [UIColor colorWithRed:lineDarkRgb green:lineDarkRgb blue:lineDarkRgb alpha:1.0]; + } + }]; + _divideLine.backgroundColor = divideLineDyColor; + } else { + _divideLine.backgroundColor = [UIColor colorWithRed:rgb2 green:rgb2 blue:rgb2 alpha:1.0]; + } + + [_bottomToolBar addSubview:_divideLine]; + [_bottomToolBar addSubview:_previewButton]; + [_bottomToolBar addSubview:_doneButton]; + [_bottomToolBar addSubview:_numberImageView]; + [_bottomToolBar addSubview:_numberLabel]; + [_bottomToolBar addSubview:_originalPhotoButton]; + [self.view addSubview:_bottomToolBar]; + [_originalPhotoButton addSubview:_originalPhotoLabel]; + + if (tzImagePickerVc.photoPickerPageUIConfigBlock) { + tzImagePickerVc.photoPickerPageUIConfigBlock(_collectionView, _bottomToolBar, _previewButton, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel, _divideLine); + } +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + + CGFloat top = 0; + CGFloat collectionViewHeight = 0; + CGFloat naviBarHeight = self.navigationController.navigationBar.tz_height; + CGFloat footerTipViewH = _authorizationLimited ? 80 : 0; + BOOL isStatusBarHidden = [UIApplication sharedApplication].isStatusBarHidden; + BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height; + CGFloat toolBarHeight = 50 + [TZCommonTools tz_safeAreaInsets].bottom; + if (self.navigationController.navigationBar.isTranslucent) { + top = naviBarHeight; + if (!isStatusBarHidden && isFullScreen) top += [TZCommonTools tz_statusBarHeight]; + collectionViewHeight = tzImagePickerVc.showSelectBtn ? self.view.tz_height - toolBarHeight - top : self.view.tz_height - top;; + } else { + collectionViewHeight = tzImagePickerVc.showSelectBtn ? self.view.tz_height - toolBarHeight : self.view.tz_height; + } + collectionViewHeight -= footerTipViewH; + + _collectionView.frame = CGRectMake(0, top, self.view.tz_width, collectionViewHeight); + _noDataLabel.frame = _collectionView.bounds; + CGFloat itemWH = (self.view.tz_width - (self.columnNumber + 1) * itemMargin) / self.columnNumber; + _layout.itemSize = CGSizeMake(itemWH, itemWH); + _layout.minimumInteritemSpacing = itemMargin; + _layout.minimumLineSpacing = itemMargin; + [_collectionView setCollectionViewLayout:_layout]; + if (_offsetItemCount > 0) { + CGFloat offsetY = _offsetItemCount * (_layout.itemSize.height + _layout.minimumLineSpacing); + [_collectionView setContentOffset:CGPointMake(0, offsetY)]; + } + + CGFloat toolBarTop = 0; + if (!self.navigationController.navigationBar.isHidden) { + toolBarTop = self.view.tz_height - toolBarHeight; + } else { + CGFloat navigationHeight = naviBarHeight + [TZCommonTools tz_statusBarHeight]; + toolBarTop = self.view.tz_height - toolBarHeight - navigationHeight; + } + _bottomToolBar.frame = CGRectMake(0, toolBarTop, self.view.tz_width, toolBarHeight); + if (_authFooterTipView) { + CGFloat footerTipViewY = _bottomToolBar ? toolBarTop - footerTipViewH : self.view.tz_height - footerTipViewH; + _authFooterTipView.frame = CGRectMake(0, footerTipViewY, self.view.tz_width, footerTipViewH);; + } + CGFloat previewWidth = [tzImagePickerVc.previewBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size.width + 2; + if (!tzImagePickerVc.allowPreview) { + previewWidth = 0.0; + } + _previewButton.frame = CGRectMake(10, 3, previewWidth, 44); + _previewButton.tz_width = !tzImagePickerVc.showSelectBtn ? 0 : previewWidth; + if (tzImagePickerVc.allowPickingOriginalPhoto) { + CGFloat fullImageWidth = [tzImagePickerVc.fullImageBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size.width; + _originalPhotoButton.frame = CGRectMake(CGRectGetMaxX(_previewButton.frame), 0, fullImageWidth + 56, 50); + _originalPhotoLabel.frame = CGRectMake(fullImageWidth + 46, 0, 80, 50); + } + [_doneButton sizeToFit]; + _doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, MAX(44, _doneButton.tz_width), 50); + _numberImageView.frame = CGRectMake(_doneButton.tz_left - 24 - 5, 13, 24, 24); + _numberLabel.frame = _numberImageView.frame; + _divideLine.frame = CGRectMake(0, 0, self.view.tz_width, 1); + + [TZImageManager manager].columnNumber = [TZImageManager manager].columnNumber; + [TZImageManager manager].photoWidth = tzImagePickerVc.photoWidth; + [self.collectionView reloadData]; + + if (tzImagePickerVc.photoPickerPageDidLayoutSubviewsBlock) { + tzImagePickerVc.photoPickerPageDidLayoutSubviewsBlock(_collectionView, _bottomToolBar, _previewButton, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel, _divideLine); + } + + // 设置加载指示器位置 + self.loadingIndicator.center = CGPointMake(self.view.tz_width / 2, 50); +} + +#pragma mark - Notification + +- (void)didChangeStatusBarOrientationNotification:(NSNotification *)noti { + _offsetItemCount = _collectionView.contentOffset.y / (_layout.itemSize.height + _layout.minimumLineSpacing); +} + +#pragma mark - Click Event +- (void)galleryItemClick{ + [self.navigationController popViewControllerAnimated:YES]; +} +- (void)navLeftBarButtonClick{ + [self.navigationController popViewControllerAnimated:YES]; +} +- (void)previewButtonClick { + TZPhotoPreviewController *photoPreviewVc = [[TZPhotoPreviewController alloc] init]; + [self pushPhotoPrevireViewController:photoPreviewVc needCheckSelectedModels:YES]; +} + +- (void)originalPhotoButtonClick { + _originalPhotoButton.selected = !_originalPhotoButton.isSelected; + _isSelectOriginalPhoto = _originalPhotoButton.isSelected; + _originalPhotoLabel.hidden = !_originalPhotoButton.isSelected; + if (_isSelectOriginalPhoto) { + [self getSelectedPhotoBytes]; + } +} + +- (void)doneButtonClick { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + // 1.6.8 判断是否满足最小必选张数的限制 + if (tzImagePickerVc.minImagesCount && tzImagePickerVc.selectedModels.count < tzImagePickerVc.minImagesCount) { + NSString *title = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Select a minimum of %zd photos"], tzImagePickerVc.minImagesCount]; + [tzImagePickerVc showAlertWithTitle:title]; + return; + } + + [tzImagePickerVc showProgressHUD]; + _doneButton.enabled = NO; + self.isFetchingMedia = YES; + NSMutableArray *assets = [NSMutableArray array]; + NSMutableArray *photos; + NSMutableArray *infoArr; + if (tzImagePickerVc.onlyReturnAsset) { // not fetch image + for (NSInteger i = 0; i < tzImagePickerVc.selectedModels.count; i++) { + TZAssetModel *model = tzImagePickerVc.selectedModels[i]; + [assets addObject:model.asset]; + } + } else { // fetch image + photos = [NSMutableArray array]; + infoArr = [NSMutableArray array]; + for (NSInteger i = 0; i < tzImagePickerVc.selectedModels.count; i++) { [photos addObject:@1];[assets addObject:@1];[infoArr addObject:@1]; } + + __block BOOL havenotShowAlert = YES; + [TZImageManager manager].shouldFixOrientation = YES; + __block UIAlertController *alertView; + for (NSInteger i = 0; i < tzImagePickerVc.selectedModels.count; i++) { + TZAssetModel *model = tzImagePickerVc.selectedModels[i]; + TZImageRequestOperation *operation = [[TZImageRequestOperation alloc] initWithAsset:model.asset completion:^(UIImage * _Nonnull photo, NSDictionary * _Nonnull info, BOOL isDegraded) { + if (isDegraded) return; + if (photo) { + if (![TZImagePickerConfig sharedInstance].notScaleImage) { + photo = [[TZImageManager manager] scaleImage:photo toSize:CGSizeMake(tzImagePickerVc.photoWidth, (int)(tzImagePickerVc.photoWidth * photo.size.height / photo.size.width))]; + } + [photos replaceObjectAtIndex:i withObject:photo]; + } + if (info) [infoArr replaceObjectAtIndex:i withObject:info]; + [assets replaceObjectAtIndex:i withObject:model.asset]; + + for (id item in photos) { if ([item isKindOfClass:[NSNumber class]]) return; } + + if (havenotShowAlert && alertView) { + [alertView dismissViewControllerAnimated:YES completion:^{ + alertView = nil; + [self didGetAllPhotos:photos assets:assets infoArr:infoArr]; + }]; + } else { + [self didGetAllPhotos:photos assets:assets infoArr:infoArr]; + } + } progressHandler:^(double progress, NSError * _Nonnull error, BOOL * _Nonnull stop, NSDictionary * _Nonnull info) { + // 如果图片正在从iCloud同步中,提醒用户 + if (progress < 1 && havenotShowAlert && !alertView) { + alertView = [tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Synchronizing photos from iCloud"]]; + havenotShowAlert = NO; + return; + } + if (progress >= 1) { + havenotShowAlert = YES; + } + }]; + [self.operationQueue addOperation:operation]; + } + } + if (tzImagePickerVc.selectedModels.count <= 0 || tzImagePickerVc.onlyReturnAsset) { + [self didGetAllPhotos:photos assets:assets infoArr:infoArr]; + } +} + +- (void)didGetAllPhotos:(NSArray *)photos assets:(NSArray *)assets infoArr:(NSArray *)infoArr { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + [tzImagePickerVc hideProgressHUD]; + _doneButton.enabled = YES; + self.isFetchingMedia = NO; + + if (tzImagePickerVc.autoDismiss) { + [self.navigationController dismissViewControllerAnimated:YES completion:^{ + [self callDelegateMethodWithPhotos:photos assets:assets infoArr:infoArr]; + }]; + } else { + [self callDelegateMethodWithPhotos:photos assets:assets infoArr:infoArr]; + } +} + +- (void)callDelegateMethodWithPhotos:(NSArray *)photos assets:(NSArray *)assets infoArr:(NSArray *)infoArr { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc.allowPickingVideo && tzImagePickerVc.maxImagesCount == 1) { + if ([[TZImageManager manager] isVideo:[assets firstObject]]) { + BOOL triggered = NO; + if ([tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingVideo:sourceAssets:)]) { + [tzImagePickerVc.pickerDelegate imagePickerController:tzImagePickerVc didFinishPickingVideo:[photos firstObject] sourceAssets:[assets firstObject]]; + triggered = YES; + } + if (tzImagePickerVc.didFinishPickingVideoHandle) { + tzImagePickerVc.didFinishPickingVideoHandle([photos firstObject], [assets firstObject]); + triggered = YES; + } + if (triggered) return; + } + } + + if ([tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:)]) { + [tzImagePickerVc.pickerDelegate imagePickerController:tzImagePickerVc didFinishPickingPhotos:photos sourceAssets:assets isSelectOriginalPhoto:_isSelectOriginalPhoto]; + } + if ([tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto:infos:)]) { + [tzImagePickerVc.pickerDelegate imagePickerController:tzImagePickerVc didFinishPickingPhotos:photos sourceAssets:assets isSelectOriginalPhoto:_isSelectOriginalPhoto infos:infoArr]; + } + if (tzImagePickerVc.didFinishPickingPhotosHandle) { + tzImagePickerVc.didFinishPickingPhotosHandle(photos,assets,_isSelectOriginalPhoto); + } + if (tzImagePickerVc.didFinishPickingPhotosWithInfosHandle) { + tzImagePickerVc.didFinishPickingPhotosWithInfosHandle(photos,assets,_isSelectOriginalPhoto,infoArr); + } +} + +#pragma mark - UICollectionViewDataSource && Delegate + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + if (_showTakePhotoBtn) { + return _models.count + 1; + } + return _models.count; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + // the cell lead to add more photo / 去添加更多照片的cell + if (indexPath.item == [self getAddMorePhotoCellIndex]) { + TZAssetAddMoreCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZAssetAddMoreCell" forIndexPath:indexPath]; + cell.imageView.image = tzImagePickerVc.addMorePhotoImage; + cell.tipLabel.text = [NSBundle tz_localizedStringForKey:@"Add more accessible photos"]; + cell.imageView.contentMode = UIViewContentModeScaleAspectFit; + cell.imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500]; + return cell; + } + // the cell lead to take a picture / 去拍照的cell + if (indexPath.item == [self getTakePhotoCellIndex]) { + TZAssetCameraCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZAssetCameraCell" forIndexPath:indexPath]; + cell.imageView.image = tzImagePickerVc.takePictureImage; + if ([tzImagePickerVc.takePictureImageName isEqualToString:@"takePicture80"]) { + cell.imageView.contentMode = UIViewContentModeCenter; + CGFloat rgb = 223 / 255.0; + cell.imageView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; + } else { + cell.imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500]; + } + return cell; + } + // the cell dipaly photo or video / 展示照片或视频的cell + TZAssetCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZAssetCell" forIndexPath:indexPath]; + cell.allowPickingMultipleVideo = tzImagePickerVc.allowPickingMultipleVideo; + cell.photoDefImage = tzImagePickerVc.photoDefImage; + cell.photoSelImage = tzImagePickerVc.photoSelImage; + cell.assetCellDidSetModelBlock = tzImagePickerVc.assetCellDidSetModelBlock; + cell.assetCellDidLayoutSubviewsBlock = tzImagePickerVc.assetCellDidLayoutSubviewsBlock; + TZAssetModel *model; + if (tzImagePickerVc.sortAscendingByModificationDate) { + model = _models[indexPath.item]; + } else { + NSInteger diff = [self getAllCellCount] - _models.count; + model = _models[indexPath.item - diff];; + } + cell.allowPickingGif = tzImagePickerVc.allowPickingGif; + cell.model = model; + if (model.isSelected && tzImagePickerVc.showSelectedIndex) { + cell.index = [tzImagePickerVc.selectedAssetIds indexOfObject:model.asset.localIdentifier] + 1; + } + cell.showSelectBtn = tzImagePickerVc.showSelectBtn; + cell.allowPreview = tzImagePickerVc.allowPreview; + + BOOL notSelectable = [TZCommonTools isAssetNotSelectable:model tzImagePickerVc:tzImagePickerVc]; + if (notSelectable && tzImagePickerVc.showPhotoCannotSelectLayer && !model.isSelected) { + cell.cannotSelectLayerButton.backgroundColor = tzImagePickerVc.cannotSelectLayerColor; + cell.cannotSelectLayerButton.hidden = NO; + } else { + cell.cannotSelectLayerButton.hidden = YES; + } + + __weak typeof(cell) weakCell = cell; + __weak typeof(self) weakSelf = self; + __weak typeof(_numberImageView.layer) weakLayer = _numberImageView.layer; + cell.didSelectPhotoBlock = ^(BOOL isSelected) { + __strong typeof(weakCell) strongCell = weakCell; + __strong typeof(weakSelf) strongSelf = weakSelf; + __strong typeof(weakLayer) strongLayer = weakLayer; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)strongSelf.navigationController; + // 1. cancel select / 取消选择 + if (isSelected) { + strongCell.selectPhotoButton.selected = NO; + model.isSelected = NO; + NSArray *selectedModels = [NSArray arrayWithArray:tzImagePickerVc.selectedModels]; + for (TZAssetModel *model_item in selectedModels) { + if ([model.asset.localIdentifier isEqualToString:model_item.asset.localIdentifier]) { + [tzImagePickerVc removeSelectedModel:model_item]; + [strongSelf setAsset:model_item.asset isSelect:NO]; + break; + } + } + [strongSelf refreshBottomToolBarStatus]; + if (tzImagePickerVc.showSelectedIndex || tzImagePickerVc.showPhotoCannotSelectLayer) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_PHOTO_PICKER_RELOAD_NOTIFICATION" object:strongSelf.navigationController]; + } + [UIView showOscillatoryAnimationWithLayer:strongLayer type:TZOscillatoryAnimationToSmaller]; + if (strongCell.model.iCloudFailed) { + NSString *title = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"]; + [tzImagePickerVc showAlertWithTitle:title]; + } + } else { + // 2. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制 + if (tzImagePickerVc.selectedModels.count < tzImagePickerVc.maxImagesCount) { + if ([[TZImageManager manager] isAssetCannotBeSelected:model.asset]) { + return; + } + if (!tzImagePickerVc.allowPreview) { + BOOL shouldDone = tzImagePickerVc.maxImagesCount == 1; + if (!tzImagePickerVc.allowPickingMultipleVideo && (model.type == TZAssetModelMediaTypeVideo || model.type == TZAssetModelMediaTypePhotoGif)) { + shouldDone = YES; + } + if (shouldDone) { + model.isSelected = YES; + [tzImagePickerVc addSelectedModel:model]; + [strongSelf doneButtonClick]; + return; + } + } + strongCell.selectPhotoButton.selected = YES; + model.isSelected = YES; + [tzImagePickerVc addSelectedModel:model]; + if (tzImagePickerVc.showSelectedIndex || tzImagePickerVc.showPhotoCannotSelectLayer) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_PHOTO_PICKER_RELOAD_NOTIFICATION" object:strongSelf.navigationController]; + } + [strongSelf setAsset:model.asset isSelect:YES]; + [strongSelf refreshBottomToolBarStatus]; + [UIView showOscillatoryAnimationWithLayer:strongLayer type:TZOscillatoryAnimationToSmaller]; + } else { + NSString *title = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Select a maximum of %zd photos"], tzImagePickerVc.maxImagesCount]; + [tzImagePickerVc showAlertWithTitle:title]; + } + } + }; + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + // take a photo / 去拍照 + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (indexPath.item == [self getAddMorePhotoCellIndex]) { + [self addMorePhoto]; return; + } + if (indexPath.item == [self getTakePhotoCellIndex]) { + [self takePhoto]; return; + } + // preview phote or video / 预览照片或视频 + NSInteger index = indexPath.item; + if (!tzImagePickerVc.sortAscendingByModificationDate) { + index -= [self getAllCellCount] - _models.count; + } + TZAssetModel *model = _models[index]; + if (model.type == TZAssetModelMediaTypeVideo && !tzImagePickerVc.allowPickingMultipleVideo) { + if (tzImagePickerVc.selectedModels.count > 0) { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + [imagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Can not choose both video and photo"]]; + } else { + TZVideoPlayerController *videoPlayerVc = [[TZVideoPlayerController alloc] init]; + videoPlayerVc.model = model; + [self.navigationController pushViewController:videoPlayerVc animated:YES]; + } + } else if (model.type == TZAssetModelMediaTypePhotoGif && tzImagePickerVc.allowPickingGif && !tzImagePickerVc.allowPickingMultipleVideo) { + if (tzImagePickerVc.selectedModels.count > 0) { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + [imagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Can not choose both photo and GIF"]]; + } else { + TZGifPhotoPreviewController *gifPreviewVc = [[TZGifPhotoPreviewController alloc] init]; + gifPreviewVc.model = model; + [self.navigationController pushViewController:gifPreviewVc animated:YES]; + } + } else { + TZPhotoPreviewController *photoPreviewVc = [[TZPhotoPreviewController alloc] init]; + photoPreviewVc.currentIndex = index; + photoPreviewVc.models = _models; + [self pushPhotoPrevireViewController:photoPreviewVc]; + } +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + // 只在用户手动滚动时触发 + if (!scrollView.isDragging && !scrollView.isDecelerating) { + return; + } + + // 添加时间间隔和偏移量的双重控制 + NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:self.lastLoadTime ?: [NSDate distantPast]]; + CGFloat offsetY = scrollView.contentOffset.y; + CGFloat contentHeight = scrollView.contentSize.height; + CGFloat frameHeight = scrollView.frame.size.height; + + // 只在滚动到顶部一定距离且满足时间间隔时触发 + if (!self.isLoadingMore && + offsetY < -100 && + interval > 3.0 && + contentHeight > frameHeight) { // 确保有足够内容可滚动 + self.lastLoadTime = [NSDate date]; + [self loadMoreAssets]; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { + // 只在松手且标记为可加载时触发加载 + if (self.canLoadMore) { + self.canLoadMore = NO; // 重置标记 + [self loadMoreAssets]; + } +} + +#pragma mark - Private Method + +- (NSInteger)getAllCellCount { + NSInteger count = _models.count; + if (_showTakePhotoBtn) { + count += 1; + } + if (_authorizationLimited) { + count += 1; + } + return count; +} + +- (NSInteger)getTakePhotoCellIndex { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (!_showTakePhotoBtn) { + return -1; + } + if (tzImagePickerVc.sortAscendingByModificationDate) { + return [self getAllCellCount] - 1; + } else { + return 0; + } +} + +- (NSInteger)getAddMorePhotoCellIndex { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (!_authorizationLimited) { + return -1; + } + if (tzImagePickerVc.sortAscendingByModificationDate) { + if (_showTakePhotoBtn) { + return [self getAllCellCount] - 2; + } + return [self getAllCellCount] - 1; + } else { + return _showTakePhotoBtn ? 1 : 0; + } +} + +/// 拍照按钮点击事件 +- (void)takePhoto { + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; + if ((authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied)) { + + // 无权限 做一个友好的提示 + NSString *appName = [TZCommonTools tz_getAppName]; + + NSString *title = [NSBundle tz_localizedStringForKey:@"Can not use camera"]; + NSString *message = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\""],appName]; + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *cancelAct = [UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:nil]; + [alertController addAction:cancelAct]; + UIAlertAction *settingAct = [UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"Setting"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; + }]; + [alertController addAction:settingAct]; + [self.navigationController presentViewController:alertController animated:YES completion:nil]; + } else if (authStatus == AVAuthorizationStatusNotDetermined) { + // fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏 + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { + if (granted) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self pushImagePickerController]; + }); + } + }]; + } else { + [self pushImagePickerController]; + } +} + +- (void)openSettingsApplication { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; +} + +- (void)addMorePhoto { + if (@available(iOS 14, *)) { + [[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self]; + } +} + +// 调用相机 +- (void)pushImagePickerController { + // 提前定位 + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; +#ifdef TZ_HAVE_LOCATION_CODE + if (tzImagePickerVc.allowCameraLocation) { + __weak typeof(self) weakSelf = self; + [[TZLocationManager manager] startLocationWithSuccessBlock:^(NSArray *locations) { + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.location = [locations firstObject]; + } failureBlock:^(NSError *error) { + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.location = nil; + }]; + } +#endif + + UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; + if ([UIImagePickerController isSourceTypeAvailable: sourceType]) { + self.imagePickerVc.sourceType = sourceType; + NSMutableArray *mediaTypes = [NSMutableArray array]; + if (tzImagePickerVc.allowTakePicture) { + [mediaTypes addObject:(NSString *)kUTTypeImage]; + } + if (tzImagePickerVc.allowTakeVideo) { + [mediaTypes addObject:(NSString *)kUTTypeMovie]; + self.imagePickerVc.videoMaximumDuration = tzImagePickerVc.videoMaximumDuration; + } + self.imagePickerVc.mediaTypes= mediaTypes; + if (tzImagePickerVc.uiImagePickerControllerSettingBlock) { + tzImagePickerVc.uiImagePickerControllerSettingBlock(_imagePickerVc); + } + [self presentViewController:_imagePickerVc animated:YES completion:nil]; + } else { + NSLog(@"模拟器中无法打开照相机,请在真机中使用"); + } +} + +- (void)refreshBottomToolBarStatus { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + + _previewButton.enabled = tzImagePickerVc.selectedModels.count > 0; + _doneButton.enabled = tzImagePickerVc.selectedModels.count > 0 || tzImagePickerVc.alwaysEnableDoneBtn; + + _numberImageView.hidden = tzImagePickerVc.selectedModels.count <= 0; + _numberLabel.hidden = tzImagePickerVc.selectedModels.count <= 0; + _numberLabel.text = [NSString stringWithFormat:@"%zd",tzImagePickerVc.selectedModels.count]; + + _originalPhotoButton.enabled = tzImagePickerVc.selectedModels.count > 0; + _originalPhotoButton.selected = (_isSelectOriginalPhoto && _originalPhotoButton.enabled); + _originalPhotoLabel.hidden = (!_originalPhotoButton.isSelected); + if (_isSelectOriginalPhoto) [self getSelectedPhotoBytes]; + + if (tzImagePickerVc.photoPickerPageDidRefreshStateBlock) { + tzImagePickerVc.photoPickerPageDidRefreshStateBlock(_collectionView, _bottomToolBar, _previewButton, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel, _divideLine);; + } +} + +- (void)pushPhotoPrevireViewController:(TZPhotoPreviewController *)photoPreviewVc { + [self pushPhotoPrevireViewController:photoPreviewVc needCheckSelectedModels:NO]; +} + +- (void)pushPhotoPrevireViewController:(TZPhotoPreviewController *)photoPreviewVc needCheckSelectedModels:(BOOL)needCheckSelectedModels { + __weak typeof(self) weakSelf = self; + photoPreviewVc.isSelectOriginalPhoto = _isSelectOriginalPhoto; + [photoPreviewVc setBackButtonClickBlock:^(BOOL isSelectOriginalPhoto) { + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.isSelectOriginalPhoto = isSelectOriginalPhoto; + if (needCheckSelectedModels) { + [strongSelf checkSelectedModels]; + } + [strongSelf.collectionView reloadData]; + [strongSelf refreshBottomToolBarStatus]; + }]; + [photoPreviewVc setDoneButtonClickBlock:^(BOOL isSelectOriginalPhoto) { + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.isSelectOriginalPhoto = isSelectOriginalPhoto; + [strongSelf doneButtonClick]; + }]; + [photoPreviewVc setDoneButtonClickBlockCropMode:^(UIImage *cropedImage, id asset) { + __strong typeof(weakSelf) strongSelf = weakSelf; + NSArray *assets = @[]; + if (asset) { + assets = @[asset]; + } + NSArray *photos = @[]; + if (cropedImage) { + photos = @[cropedImage]; + } + [strongSelf didGetAllPhotos:photos assets:assets infoArr:nil]; + }]; + [self.navigationController pushViewController:photoPreviewVc animated:YES]; +} + +- (void)getSelectedPhotoBytes { + // 越南语 && 5屏幕时会显示不下,暂时这样处理 + if ([[TZImagePickerConfig sharedInstance].preferredLanguage isEqualToString:@"vi"] && self.view.tz_width <= 320) { + return; + } + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + [[TZImageManager manager] getPhotosBytesWithArray:imagePickerVc.selectedModels completion:^(NSString *totalBytes) { + self->_originalPhotoLabel.text = [NSString stringWithFormat:@"(%@)",totalBytes]; + }]; +} + +- (void)prepareScrollCollectionViewToBottom { + if (_shouldScrollToBottom && _models.count > 0) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self scrollCollectionViewToBottom]; + // try fix #1562:https://github.com/banchichen/TZImagePickerController/issues/1562 + if (@available(iOS 15.0, *)) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self scrollCollectionViewToBottom]; + }); + } + }); + } else { + _collectionView.hidden = NO; + } +} + +- (void)scrollCollectionViewToBottom { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + NSInteger item = 0; + if (tzImagePickerVc.sortAscendingByModificationDate) { + item = [self getAllCellCount] - 1; + } + [self->_collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:item inSection:0] atScrollPosition:UICollectionViewScrollPositionBottom animated:NO]; + self->_shouldScrollToBottom = NO; + self->_collectionView.hidden = NO; +} + +- (void)checkSelectedModels { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + NSArray *selectedModels = tzImagePickerVc.selectedModels; + NSMutableSet *selectedAssets = [NSMutableSet setWithCapacity:selectedModels.count]; + for (TZAssetModel *model in selectedModels) { + [selectedAssets addObject:model.asset]; + } + // 拿到了最新的models,在此刷新照片选中状态 + for (TZAssetModel *model in _models) { + model.isSelected = NO; + if ([selectedAssets containsObject:model.asset]) { + model.isSelected = YES; + } + } +} + +/// 选中/取消选中某张照片 +- (void)setAsset:(PHAsset *)asset isSelect:(BOOL)isSelect { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (isSelect && [tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didSelectAsset:photo:isSelectOriginalPhoto:)]) { + [self callDelegate:asset isSelect:YES]; + } + if (!isSelect && [tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didDeselectAsset:photo:isSelectOriginalPhoto:)]) { + [self callDelegate:asset isSelect:NO]; + } +} + +/// 调用选中/取消选中某张照片的代理方法 +- (void)callDelegate:(PHAsset *)asset isSelect:(BOOL)isSelect { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + __weak typeof(self) weakSelf = self; + __weak typeof(tzImagePickerVc) weakImagePickerVc= tzImagePickerVc; + [[TZImageManager manager] getPhotoWithAsset:asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + if (isDegraded) return; + __strong typeof(weakSelf) strongSelf = weakSelf; + __strong typeof(weakImagePickerVc) strongImagePickerVc = weakImagePickerVc; + if (isSelect) { + [strongImagePickerVc.pickerDelegate imagePickerController:strongImagePickerVc didSelectAsset:asset photo:photo isSelectOriginalPhoto:strongSelf.isSelectOriginalPhoto]; + } else { + [strongImagePickerVc.pickerDelegate imagePickerController:strongImagePickerVc didDeselectAsset:asset photo:photo isSelectOriginalPhoto:strongSelf.isSelectOriginalPhoto]; + } + }]; +} + +#pragma mark - UIImagePickerControllerDelegate + +- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { + [picker dismissViewControllerAnimated:YES completion:nil]; + NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; + if ([type isEqualToString:@"public.image"]) { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + [imagePickerVc showProgressHUD]; + UIImage *photo = [info objectForKey:UIImagePickerControllerOriginalImage]; + NSDictionary *meta = [info objectForKey:UIImagePickerControllerMediaMetadata]; + if (photo) { + self.isSavingMedia = YES; + [[TZImageManager manager] savePhotoWithImage:photo meta:meta location:self.location completion:^(PHAsset *asset, NSError *error){ + self.isSavingMedia = NO; + if (!error && asset) { + [self addPHAsset:asset]; + } else { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + [tzImagePickerVc hideProgressHUD]; + } + }]; + self.location = nil; + } + } else if ([type isEqualToString:@"public.movie"]) { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + [imagePickerVc showProgressHUD]; + NSURL *videoUrl = [info objectForKey:UIImagePickerControllerMediaURL]; + if (videoUrl) { + self.isSavingMedia = YES; + [[TZImageManager manager] saveVideoWithUrl:videoUrl location:self.location completion:^(PHAsset *asset, NSError *error) { + self.isSavingMedia = NO; + if (!error && asset) { + [self addPHAsset:asset]; + } else { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + [tzImagePickerVc hideProgressHUD]; + } + }]; + self.location = nil; + } + } +} + +- (void)addPHAsset:(PHAsset *)asset { + TZAssetModel *assetModel = [[TZImageManager manager] createModelWithAsset:asset]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + [tzImagePickerVc hideProgressHUD]; + if (tzImagePickerVc.sortAscendingByModificationDate) { + [_models addObject:assetModel]; + } else { + [_models insertObject:assetModel atIndex:0]; + } + + if (tzImagePickerVc.maxImagesCount <= 1) { + if (tzImagePickerVc.allowCrop && asset.mediaType == PHAssetMediaTypeImage) { + TZPhotoPreviewController *photoPreviewVc = [[TZPhotoPreviewController alloc] init]; + if (tzImagePickerVc.sortAscendingByModificationDate) { + photoPreviewVc.currentIndex = _models.count - 1; + } else { + photoPreviewVc.currentIndex = 0; + } + photoPreviewVc.models = _models; + [self pushPhotoPrevireViewController:photoPreviewVc]; + } else if (tzImagePickerVc.selectedModels.count < 1) { + [tzImagePickerVc addSelectedModel:assetModel]; + [self doneButtonClick]; + } + return; + } + + if (tzImagePickerVc.selectedModels.count < tzImagePickerVc.maxImagesCount) { + if (assetModel.type == TZAssetModelMediaTypeVideo && !tzImagePickerVc.allowPickingMultipleVideo) { + // 不能多选视频的情况下,不选中拍摄的视频 + } else { + if ([[TZImageManager manager] isAssetCannotBeSelected:assetModel.asset]) { + return; + } + assetModel.isSelected = YES; + [tzImagePickerVc addSelectedModel:assetModel]; + [self refreshBottomToolBarStatus]; + } + } + _collectionView.hidden = YES; + [_collectionView reloadData]; + + _shouldScrollToBottom = YES; + [self prepareScrollCollectionViewToBottom]; +} + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { + [picker dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)dealloc { + [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + // NSLog(@"%@ dealloc",NSStringFromClass(self.class)); +} + +#pragma mark - PHPhotoLibraryChangeObserver + +- (void)photoLibraryDidChange:(PHChange *)changeInstance { + if (self.isSavingMedia || self.isFetchingMedia) { + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + PHFetchResultChangeDetails *changeDetail = [changeInstance changeDetailsForFetchResult:self.model.result]; + if (changeDetail == nil) return; + if ([[TZImageManager manager] isPHAuthorizationStatusLimited]) { + NSArray *changedObjects = [changeDetail changedObjects]; + changeDetail = [PHFetchResultChangeDetails changeDetailsFromFetchResult:self.model.result toFetchResult:changeDetail.fetchResultAfterChanges changedObjects:changedObjects]; + if (changeDetail && changeDetail.removedObjects.count) { + [self handleRemovedAssets:changeDetail.removedObjects]; + } + } + + if (changeDetail.hasIncrementalChanges == NO) { + [self.model refreshFetchResult]; + [self fetchAssetModels]; + } else { + NSInteger insertedCount = changeDetail.insertedObjects.count; + NSInteger removedCount = changeDetail.removedObjects.count; + NSInteger changedCount = changeDetail.changedObjects.count; + if (insertedCount > 0 || removedCount > 0 || changedCount > 0) { + self.model.result = changeDetail.fetchResultAfterChanges; + self.model.count = changeDetail.fetchResultAfterChanges.count; + [self fetchAssetModels]; + } + } + }); +} + +- (void)handleRemovedAssets:(NSArray *)removedObjects { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + for (PHAsset *asset in removedObjects) { + Boolean isSelected = [tzImagePickerVc.selectedAssetIds containsObject:asset.localIdentifier]; + if (!isSelected) continue; + NSArray *selectedModels = [NSArray arrayWithArray:tzImagePickerVc.selectedModels]; + for (TZAssetModel *model_item in selectedModels) { + if ([asset.localIdentifier isEqualToString:model_item.asset.localIdentifier]) { + [tzImagePickerVc removeSelectedModel:model_item]; + } + } + [self refreshBottomToolBarStatus]; + } +} + +#pragma mark - Asset Caching + +- (void)resetCachedAssets { + [[TZImageManager manager].cachingImageManager stopCachingImagesForAllAssets]; + self.previousPreheatRect = CGRectZero; +} + +- (void)updateCachedAssets { + BOOL isViewVisible = [self isViewLoaded] && [[self view] window] != nil; + if (!isViewVisible) { return; } + + // The preheat window is twice the height of the visible rect. + CGRect preheatRect = _collectionView.bounds; + preheatRect = CGRectInset(preheatRect, 0.0f, -0.5f * CGRectGetHeight(preheatRect)); + + /* + Check if the collection view is showing an area that is significantly + different to the last preheated area. + */ + CGFloat delta = ABS(CGRectGetMidY(preheatRect) - CGRectGetMidY(self.previousPreheatRect)); + if (delta > CGRectGetHeight(_collectionView.bounds) / 3.0f) { + + // Compute the assets to start caching and to stop caching. + NSMutableArray *addedIndexPaths = [NSMutableArray array]; + NSMutableArray *removedIndexPaths = [NSMutableArray array]; + + [self computeDifferenceBetweenRect:self.previousPreheatRect andRect:preheatRect removedHandler:^(CGRect removedRect) { + NSArray *indexPaths = [self aapl_indexPathsForElementsInRect:removedRect]; + [removedIndexPaths addObjectsFromArray:indexPaths]; + } addedHandler:^(CGRect addedRect) { + NSArray *indexPaths = [self aapl_indexPathsForElementsInRect:addedRect]; + [addedIndexPaths addObjectsFromArray:indexPaths]; + }]; + + NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths]; + NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths]; + + // Update the assets the PHCachingImageManager is caching. + [[TZImageManager manager].cachingImageManager startCachingImagesForAssets:assetsToStartCaching + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFill + options:nil]; + [[TZImageManager manager].cachingImageManager stopCachingImagesForAssets:assetsToStopCaching + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFill + options:nil]; + + // Store the preheat rect to compare against in the future. + self.previousPreheatRect = preheatRect; + } +} + +- (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect removedHandler:(void (^)(CGRect removedRect))removedHandler addedHandler:(void (^)(CGRect addedRect))addedHandler { + if (CGRectIntersectsRect(newRect, oldRect)) { + CGFloat oldMaxY = CGRectGetMaxY(oldRect); + CGFloat oldMinY = CGRectGetMinY(oldRect); + CGFloat newMaxY = CGRectGetMaxY(newRect); + CGFloat newMinY = CGRectGetMinY(newRect); + + if (newMaxY > oldMaxY) { + CGRect rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY)); + addedHandler(rectToAdd); + } + + if (oldMinY > newMinY) { + CGRect rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY)); + addedHandler(rectToAdd); + } + + if (newMaxY < oldMaxY) { + CGRect rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY)); + removedHandler(rectToRemove); + } + + if (oldMinY < newMinY) { + CGRect rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY)); + removedHandler(rectToRemove); + } + } else { + addedHandler(newRect); + removedHandler(oldRect); + } +} + +- (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths { + if (indexPaths.count == 0) { return nil; } + + NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count]; + for (NSIndexPath *indexPath in indexPaths) { + if (indexPath.item < _models.count) { + TZAssetModel *model = _models[indexPath.item]; + [assets addObject:model.asset]; + } + } + + return assets; +} + +- (NSArray *)aapl_indexPathsForElementsInRect:(CGRect)rect { + NSArray *allLayoutAttributes = [_collectionView.collectionViewLayout layoutAttributesForElementsInRect:rect]; + if (allLayoutAttributes.count == 0) { return nil; } + NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:allLayoutAttributes.count]; + for (UICollectionViewLayoutAttributes *layoutAttributes in allLayoutAttributes) { + NSIndexPath *indexPath = layoutAttributes.indexPath; + [indexPaths addObject:indexPath]; + } + return indexPaths; +} + +- (void)loadMoreAssets { + if (self.isLoadingMore) return; + + // 检查是否还有更多数据可加载 + if (_models.count >= self.model.result.count) { + return; + } + + self.isLoadingMore = YES; + + // 显示加载提示 + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + [tzImagePickerVc showProgressHUD]; + + // 使用主队列同步处理 + dispatch_async(dispatch_get_main_queue(), ^{ + [[TZImageManager manager] getMoreAssetsFromFetchResult:self.model.result currentCount:self->_models.count completion:^(NSArray *models) { + NSLog(@"loadMoreAssets++++,models.count=%lu",(unsigned long)models.count); + if (models.count > 0) { + // 计算每行显示的列数和每个item的高度 + NSInteger columnCount = self.columnNumber; + CGFloat itemWH = (self.view.tz_width - 2 * 4 - 4) / columnCount - 4; + + // 计算新增加的行数 + NSInteger newRowCount = (models.count + columnCount - 1) / columnCount; + CGFloat heightToAdd = newRowCount * (itemWH + 4); + + // 将新加载的照片插入到数组前面,保持时间顺序 + NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, models.count)]; + [self->_models insertObjects:models atIndexes:indexes]; + + // 记录当前滚动位置 + CGPoint oldOffset = self.collectionView.contentOffset; + + // 刷新UI + [self.collectionView reloadData]; + + // 由于新内容插入到顶部,需要向下偏移相应的高度 + CGPoint newOffset = CGPointMake(oldOffset.x, oldOffset.y + heightToAdd); + + // 设置新的滚动位置 + [self.collectionView setContentOffset:newOffset animated:NO]; + } + + // 隐藏加载提示 + [tzImagePickerVc hideProgressHUD]; + self.isLoadingMore = NO; + }]; + }); +} +#pragma clang diagnostic pop + +@end + + + +@implementation TZCollectionView + +- (BOOL)touchesShouldCancelInContentView:(UIView *)view { + if ([view isKindOfClass:[UIControl class]]) { + return YES; + } + return [super touchesShouldCancelInContentView:view]; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.h b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.h new file mode 100644 index 0000000..451d965 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.h @@ -0,0 +1,76 @@ +// +// TZPhotoPreviewCell.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@class TZAssetModel; +@interface TZAssetPreviewCell : UICollectionViewCell +@property (nonatomic, strong) TZAssetModel *model; +@property (nonatomic, copy) void (^singleTapGestureBlock)(void); +- (void)configSubviews; +- (void)photoPreviewCollectionViewDidScroll; +@end + + +@class TZAssetModel,TZProgressView,TZPhotoPreviewView; +@interface TZPhotoPreviewCell : TZAssetPreviewCell + +@property (nonatomic, copy) void (^imageProgressUpdateBlock)(double progress); + +@property (nonatomic, strong) TZPhotoPreviewView *previewView; + +@property (nonatomic, assign) BOOL allowCrop; +@property (nonatomic, assign) CGRect cropRect; +@property (nonatomic, assign) BOOL scaleAspectFillCrop; + +- (void)recoverSubviews; + +@end + + +@interface TZPhotoPreviewView : UIView +@property (nonatomic, strong) UIImageView *imageView; +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, strong) UIView *imageContainerView; +@property (nonatomic, strong) TZProgressView *progressView; +@property (nonatomic, strong) UIImageView *iCloudErrorIcon; +@property (nonatomic, strong) UILabel *iCloudErrorLabel; +@property (nonatomic, copy) void (^iCloudSyncFailedHandle)(id asset, BOOL isSyncFailed); + + +@property (nonatomic, assign) BOOL allowCrop; +@property (nonatomic, assign) CGRect cropRect; +@property (nonatomic, assign) BOOL scaleAspectFillCrop; +@property (nonatomic, strong) TZAssetModel *model; +@property (nonatomic, strong) id asset; +@property (nonatomic, copy) void (^singleTapGestureBlock)(void); +@property (nonatomic, copy) void (^imageProgressUpdateBlock)(double progress); + +@property (nonatomic, assign) int32_t imageRequestID; + +- (void)recoverSubviews; +@end + + +@class AVPlayer, AVPlayerLayer; +@interface TZVideoPreviewCell : TZAssetPreviewCell +@property (strong, nonatomic) AVPlayer *player; +@property (strong, nonatomic) AVPlayerLayer *playerLayer; +@property (strong, nonatomic) UIButton *playButton; +@property (strong, nonatomic) UIImage *cover; +@property (nonatomic, strong) NSURL *videoURL; +@property (nonatomic, strong) UIImageView *iCloudErrorIcon; +@property (nonatomic, strong) UILabel *iCloudErrorLabel; +@property (nonatomic, copy) void (^iCloudSyncFailedHandle)(id asset, BOOL isSyncFailed); +- (void)pausePlayerAndShowNaviBar; +@end + + +@interface TZGifPreviewCell : TZAssetPreviewCell +@property (strong, nonatomic) TZPhotoPreviewView *previewView; +@end diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m new file mode 100644 index 0000000..81d0b5e --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m @@ -0,0 +1,576 @@ +// +// TZPhotoPreviewCell.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "TZPhotoPreviewCell.h" +#import "TZAssetModel.h" +#import "UIView+TZLayout.h" +#import "TZImageManager.h" +#import "TZProgressView.h" +#import "TZImageCropManager.h" +#import +#import "TZImagePickerController.h" + +@implementation TZAssetPreviewCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor blackColor]; + [self configSubviews]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(photoPreviewCollectionViewDidScroll) name:@"photoPreviewCollectionViewDidScroll" object:nil]; + } + return self; +} + +- (void)configSubviews { + +} + +#pragma mark - Notification + +- (void)photoPreviewCollectionViewDidScroll { + +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + + +@implementation TZPhotoPreviewCell + +- (void)configSubviews { + self.previewView = [[TZPhotoPreviewView alloc] initWithFrame:CGRectZero]; + __weak typeof(self) weakSelf = self; + [self.previewView setSingleTapGestureBlock:^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + if (strongSelf.singleTapGestureBlock) { + strongSelf.singleTapGestureBlock(); + } + }]; + [self.previewView setImageProgressUpdateBlock:^(double progress) { + __strong typeof(weakSelf) strongSelf = weakSelf; + if (strongSelf.imageProgressUpdateBlock) { + strongSelf.imageProgressUpdateBlock(progress); + } + }]; + [self.contentView addSubview:self.previewView]; +} + +- (void)setModel:(TZAssetModel *)model { + [super setModel:model]; + _previewView.model = model; +} + +- (void)recoverSubviews { + [_previewView recoverSubviews]; +} + +- (void)setAllowCrop:(BOOL)allowCrop { + _allowCrop = allowCrop; + _previewView.allowCrop = allowCrop; +} + +- (void)setScaleAspectFillCrop:(BOOL)scaleAspectFillCrop { + _scaleAspectFillCrop = scaleAspectFillCrop; + _previewView.scaleAspectFillCrop = scaleAspectFillCrop; +} + +- (void)setCropRect:(CGRect)cropRect { + _cropRect = cropRect; + _previewView.cropRect = cropRect; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + self.previewView.frame = self.bounds; +} + +@end + + +@interface TZPhotoPreviewView () +@property (assign, nonatomic) BOOL isRequestingGIF; +@end + +@implementation TZPhotoPreviewView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _scrollView = [[UIScrollView alloc] init]; + _scrollView.bouncesZoom = YES; + _scrollView.maximumZoomScale = 4; + _scrollView.minimumZoomScale = 1.0; + _scrollView.multipleTouchEnabled = YES; + _scrollView.delegate = self; + _scrollView.scrollsToTop = NO; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.showsVerticalScrollIndicator = YES; + _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _scrollView.delaysContentTouches = NO; + _scrollView.canCancelContentTouches = YES; + _scrollView.alwaysBounceVertical = NO; + if (@available(iOS 11, *)) { + _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [self addSubview:_scrollView]; + + _imageContainerView = [[UIView alloc] init]; + _imageContainerView.clipsToBounds = YES; + _imageContainerView.contentMode = UIViewContentModeScaleAspectFill; + [_scrollView addSubview:_imageContainerView]; + + _imageView = [[UIImageView alloc] init]; + _imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500]; + _imageView.contentMode = UIViewContentModeScaleAspectFill; + _imageView.clipsToBounds = YES; + [_imageContainerView addSubview:_imageView]; + + _iCloudErrorIcon = [[UIImageView alloc] init]; + _iCloudErrorIcon.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"]; + _iCloudErrorIcon.hidden = YES; + [self addSubview:_iCloudErrorIcon]; + _iCloudErrorLabel = [[UILabel alloc] init]; + _iCloudErrorLabel.font = [UIFont systemFontOfSize:10]; + _iCloudErrorLabel.textColor = [UIColor whiteColor]; + _iCloudErrorLabel.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"]; + _iCloudErrorLabel.hidden = YES; + [self addSubview:_iCloudErrorLabel]; + + UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)]; + [self addGestureRecognizer:tap1]; + UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)]; + tap2.numberOfTapsRequired = 2; + [tap1 requireGestureRecognizerToFail:tap2]; + [self addGestureRecognizer:tap2]; + + [self configProgressView]; + } + return self; +} + +- (void)configProgressView { + _progressView = [[TZProgressView alloc] init]; + _progressView.hidden = YES; + [self addSubview:_progressView]; +} + +- (void)setModel:(TZAssetModel *)model { + _model = model; + self.isRequestingGIF = NO; + [_scrollView setZoomScale:1.0 animated:NO]; + if (model.type == TZAssetModelMediaTypePhotoGif) { + // 先显示缩略图 + [[TZImageManager manager] getPhotoWithAsset:model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + if (photo) { + self.imageView.image = photo; + } + [self resizeSubviews]; + if (self.isRequestingGIF) { + return; + } + // 再显示gif动图 + self.isRequestingGIF = YES; + [[TZImageManager manager] getOriginalPhotoDataWithAsset:model.asset progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + progress = progress > 0.02 ? progress : 0.02; + dispatch_async(dispatch_get_main_queue(), ^{ + BOOL iCloudSyncFailed = [TZCommonTools isICloudSyncError:error]; + self.iCloudErrorLabel.hidden = !iCloudSyncFailed; + self.iCloudErrorIcon.hidden = !iCloudSyncFailed; + if (self.iCloudSyncFailedHandle) { + self.iCloudSyncFailedHandle(model.asset, iCloudSyncFailed); + } + + self.progressView.progress = progress; + if (progress >= 1) { + self.progressView.hidden = YES; + } else { + self.progressView.hidden = NO; + } + }); +#ifdef DEBUG + NSLog(@"[TZImagePickerController] getOriginalPhotoDataWithAsset:%f error:%@", progress, error); +#endif + } completion:^(NSData *data, NSDictionary *info, BOOL isDegraded) { + if (!isDegraded) { + self.isRequestingGIF = NO; + self.progressView.hidden = YES; + if ([TZImagePickerConfig sharedInstance].gifImagePlayBlock) { + [TZImagePickerConfig sharedInstance].gifImagePlayBlock(self, self.imageView, data, info); + } else { + self.imageView.image = [UIImage sd_tz_animatedGIFWithData:data]; + } + [self resizeSubviews]; + } + }]; + } progressHandler:nil networkAccessAllowed:NO]; + } else { + self.asset = model.asset; + } +} + +- (void)setAsset:(PHAsset *)asset { + if (_asset && self.imageRequestID) { + [[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID]; + } + + _asset = asset; + self.imageRequestID = [[TZImageManager manager] getPhotoWithAsset:asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + BOOL iCloudSyncFailed = !photo && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.iCloudErrorLabel.hidden = !iCloudSyncFailed; + self.iCloudErrorIcon.hidden = !iCloudSyncFailed; + if (self.iCloudSyncFailedHandle) { + self.iCloudSyncFailedHandle(asset, iCloudSyncFailed); + } + if (![asset isEqual:self->_asset]) return; + if (photo) { + self.imageView.image = photo; + } + [self resizeSubviews]; + if (self.imageView.tz_height && self.allowCrop) { + CGFloat scale = MAX(self.cropRect.size.width / self.imageView.tz_width, self.cropRect.size.height / self.imageView.tz_height); + if (self.scaleAspectFillCrop && scale > 1) { // 如果设置图片缩放裁剪并且图片需要缩放 + CGFloat multiple = self.scrollView.maximumZoomScale / self.scrollView.minimumZoomScale; + self.scrollView.minimumZoomScale = scale; + self.scrollView.maximumZoomScale = scale * MAX(multiple, 2); + [self.scrollView setZoomScale:scale animated:YES]; + } + } + + self->_progressView.hidden = YES; + if (self.imageProgressUpdateBlock) { + self.imageProgressUpdateBlock(1); + } + if (!isDegraded) { + self.imageRequestID = 0; + } + } progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + if (![asset isEqual:self->_asset]) return; + self->_progressView.hidden = NO; + [self bringSubviewToFront:self->_progressView]; + progress = progress > 0.02 ? progress : 0.02; + self->_progressView.progress = progress; + if (self.imageProgressUpdateBlock && progress < 1) { + self.imageProgressUpdateBlock(progress); + } + + if (progress >= 1) { + self->_progressView.hidden = YES; + self.imageRequestID = 0; + } + } networkAccessAllowed:YES]; + + [self configMaximumZoomScale]; +} + +- (void)recoverSubviews { + [_scrollView setZoomScale:_scrollView.minimumZoomScale animated:NO]; + [self resizeSubviews]; +} + +- (void)resizeSubviews { + _imageContainerView.tz_origin = CGPointZero; + _imageContainerView.tz_width = self.scrollView.tz_width; + + UIImage *image = _imageView.image; + if (image.size.height / image.size.width > self.tz_height / self.scrollView.tz_width) { + CGFloat width = image.size.width / image.size.height * self.scrollView.tz_height; + if (width < 1 || isnan(width)) width = self.tz_width; + width = floor(width); + + _imageContainerView.tz_width = width; + _imageContainerView.tz_height = self.tz_height; + _imageContainerView.tz_centerX = self.scrollView.tz_width / 2; + } else { + CGFloat height = image.size.height / image.size.width * self.scrollView.tz_width; + if (height < 1 || isnan(height)) height = self.tz_height; + height = floor(height); + _imageContainerView.tz_height = height; + _imageContainerView.tz_centerY = self.tz_height / 2; + } + if (_imageContainerView.tz_height > self.tz_height && _imageContainerView.tz_height - self.tz_height <= 1) { + _imageContainerView.tz_height = self.tz_height; + } + CGFloat contentSizeH = MAX(_imageContainerView.tz_height, self.tz_height); + _scrollView.contentSize = CGSizeMake(self.scrollView.tz_width, contentSizeH); + [_scrollView scrollRectToVisible:self.bounds animated:NO]; + _scrollView.alwaysBounceVertical = _imageContainerView.tz_height <= self.tz_height ? NO : YES; + _imageView.frame = _imageContainerView.bounds; + + [self refreshScrollViewContentSize]; +} + +- (void)configMaximumZoomScale { + _scrollView.maximumZoomScale = _allowCrop ? 6.0 : 4.0; + + if ([self.asset isKindOfClass:[PHAsset class]]) { + PHAsset *phAsset = (PHAsset *)self.asset; + CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight; + // 优化超宽图片的显示 + if (aspectRatio > 1.5) { + self.scrollView.maximumZoomScale *= aspectRatio / 1.5; + } + } +} + +- (void)refreshScrollViewContentSize { + if (_allowCrop) { + // 1.7.2 如果允许裁剪,需要让图片的任意部分都能在裁剪框内,于是对_scrollView做了如下处理: + // 1.让contentSize增大(裁剪框右下角的图片部分) + CGFloat contentWidthAdd = (MIN(_imageContainerView.tz_width, self.scrollView.tz_width) - _cropRect.size.width) / 2; + CGFloat contentHeightAdd = (MIN(_imageContainerView.tz_height, self.scrollView.tz_height) - _cropRect.size.height) / 2; + CGFloat newSizeW = MAX(self.scrollView.contentSize.width, self.scrollView.tz_width) + contentWidthAdd; + CGFloat newSizeH = MAX(self.scrollView.contentSize.height, self.scrollView.tz_height) + contentHeightAdd; + _scrollView.contentSize = CGSizeMake(newSizeW, newSizeH); + _scrollView.alwaysBounceVertical = YES; + // 2.让scrollView新增滑动区域(裁剪框左上角的图片部分) + if (contentHeightAdd > 0 || contentWidthAdd > 0) { + _scrollView.contentInset = UIEdgeInsetsMake(MAX(contentHeightAdd, 0), MAX(contentWidthAdd, 0), 0, 0); + } else { + _scrollView.contentInset = UIEdgeInsetsZero; + } + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _scrollView.frame = CGRectMake(10, 0, self.tz_width - 20, self.tz_height); + static CGFloat progressWH = 40; + CGFloat progressX = (self.tz_width - progressWH) / 2; + CGFloat progressY = (self.tz_height - progressWH) / 2; + _progressView.frame = CGRectMake(progressX, progressY, progressWH, progressWH); + [self recoverSubviews]; + _iCloudErrorIcon.frame = CGRectMake(20, [TZCommonTools tz_statusBarHeight] + 44 + 10, 28, 28); + _iCloudErrorLabel.frame = CGRectMake(53, [TZCommonTools tz_statusBarHeight] + 44 + 10, self.tz_width - 63, 28); +} + +#pragma mark - UITapGestureRecognizer Event + +- (void)doubleTap:(UITapGestureRecognizer *)tap { + if (_scrollView.zoomScale > _scrollView.minimumZoomScale) { + _scrollView.contentInset = UIEdgeInsetsZero; + [_scrollView setZoomScale:_scrollView.minimumZoomScale animated:YES]; + } else { + CGPoint touchPoint = [tap locationInView:self.imageView]; + CGFloat newZoomScale = MIN(_scrollView.maximumZoomScale, 2.5); + CGFloat xsize = self.frame.size.width / newZoomScale; + CGFloat ysize = self.frame.size.height / newZoomScale; + [_scrollView zoomToRect:CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize) animated:YES]; + } +} + +- (void)singleTap:(UITapGestureRecognizer *)tap { + if (self.singleTapGestureBlock) { + self.singleTapGestureBlock(); + } +} + +#pragma mark - UIScrollViewDelegate + +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { + return _imageContainerView; +} + +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { + scrollView.contentInset = UIEdgeInsetsZero; +} + +- (void)scrollViewDidZoom:(UIScrollView *)scrollView { + [self refreshImageContainerViewCenter]; +} + +- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { + [self refreshScrollViewContentSize]; +} + +#pragma mark - Private + +- (void)refreshImageContainerViewCenter { + CGFloat offsetX = (_scrollView.tz_width > _scrollView.contentSize.width) ? ((_scrollView.tz_width - _scrollView.contentSize.width) * 0.5) : 0.0; + CGFloat offsetY = (_scrollView.tz_height > _scrollView.contentSize.height) ? ((_scrollView.tz_height - _scrollView.contentSize.height) * 0.5) : 0.0; + self.imageContainerView.center = CGPointMake(_scrollView.contentSize.width * 0.5 + offsetX, _scrollView.contentSize.height * 0.5 + offsetY); +} + +@end + + +@implementation TZVideoPreviewCell + +- (void)configSubviews { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActiveNotification) name:UIApplicationWillResignActiveNotification object:nil]; + _iCloudErrorIcon = [[UIImageView alloc] init]; + _iCloudErrorIcon.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"]; + _iCloudErrorIcon.hidden = YES; + _iCloudErrorLabel = [[UILabel alloc] init]; + _iCloudErrorLabel.font = [UIFont systemFontOfSize:10]; + _iCloudErrorLabel.textColor = [UIColor whiteColor]; + _iCloudErrorLabel.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"]; + _iCloudErrorLabel.hidden = YES; +} + +- (void)configPlayButton { + if (_playButton) { + [_playButton removeFromSuperview]; + } + _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted]; + [_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside]; + _playButton.frame = CGRectMake(0, 64, self.tz_width, self.tz_height - 64 - 44); + [self.contentView addSubview:_playButton]; + [self.contentView addSubview:_iCloudErrorIcon]; + [self.contentView addSubview:_iCloudErrorLabel]; +} + +- (void)setModel:(TZAssetModel *)model { + [super setModel:model]; + [self configMoviePlayer]; +} + +- (void)setVideoURL:(NSURL *)videoURL { + _videoURL = videoURL; + [self configMoviePlayer]; +} + +- (void)configMoviePlayer { + if (_player) { + [_playerLayer removeFromSuperlayer]; + _playerLayer = nil; + [_player pause]; + _player = nil; + } + + if (self.model && self.model.asset) { + [[TZImageManager manager] getPhotoWithAsset:self.model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + BOOL iCloudSyncFailed = !photo && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.iCloudErrorLabel.hidden = !iCloudSyncFailed; + self.iCloudErrorIcon.hidden = !iCloudSyncFailed; + if (self.iCloudSyncFailedHandle) { + self.iCloudSyncFailedHandle(self.model.asset, iCloudSyncFailed); + } + if (photo) { + self.cover = photo; + } + }]; + [[TZImageManager manager] getVideoWithAsset:self.model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + BOOL iCloudSyncFailed = !playerItem && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.iCloudErrorLabel.hidden = !iCloudSyncFailed; + self.iCloudErrorIcon.hidden = !iCloudSyncFailed; + if (self.iCloudSyncFailedHandle) { + self.iCloudSyncFailedHandle(self.model.asset, iCloudSyncFailed); + } + [self configPlayerWithItem:playerItem]; + }); + }]; + } else { + AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:self.videoURL]; + [self configPlayerWithItem:playerItem]; + } +} + +- (void)configPlayerWithItem:(AVPlayerItem *)playerItem { + self.player = [AVPlayer playerWithPlayerItem:playerItem]; + self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; + self.playerLayer.backgroundColor = [UIColor blackColor].CGColor; + self.playerLayer.frame = self.bounds; + [self.contentView.layer addSublayer:self.playerLayer]; + [self configPlayButton]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _playerLayer.frame = self.bounds; + _playButton.frame = CGRectMake(0, 64, self.tz_width, self.tz_height - 64 - 44); + _iCloudErrorIcon.frame = CGRectMake(20, [TZCommonTools tz_statusBarHeight] + 44 + 10, 28, 28); + _iCloudErrorLabel.frame = CGRectMake(53, [TZCommonTools tz_statusBarHeight] + 44 + 10, self.tz_width - 63, 28); +} + +- (void)photoPreviewCollectionViewDidScroll { + if (_player && _player.rate != 0.0) { + [self pausePlayerAndShowNaviBar]; + } +} + +#pragma mark - Notification + +- (void)appWillResignActiveNotification { + if (_player && _player.rate != 0.0) { + [self pausePlayerAndShowNaviBar]; + } +} + +#pragma mark - Click Event + +- (void)playButtonClick { + CMTime currentTime = _player.currentItem.currentTime; + CMTime durationTime = _player.currentItem.duration; + if (_player.rate == 0.0f) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_VIDEO_PLAY_NOTIFICATION" object:_player]; + if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)]; + [_player play]; + [_playButton setImage:nil forState:UIControlStateNormal]; + [UIApplication sharedApplication].statusBarHidden = YES; + if (self.singleTapGestureBlock) { + self.singleTapGestureBlock(); + } + } else { + [self pausePlayerAndShowNaviBar]; + } +} + +- (void)pausePlayerAndShowNaviBar { + [_player pause]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; + if (self.singleTapGestureBlock) { + self.singleTapGestureBlock(); + } +} + +@end + + +@implementation TZGifPreviewCell + +- (void)configSubviews { + [self configPreviewView]; +} + +- (void)configPreviewView { + _previewView = [[TZPhotoPreviewView alloc] initWithFrame:CGRectZero]; + __weak typeof(self) weakSelf = self; + [_previewView setSingleTapGestureBlock:^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf signleTapAction]; + }]; + [self.contentView addSubview:_previewView]; +} + +- (void)setModel:(TZAssetModel *)model { + [super setModel:model]; + _previewView.model = self.model; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _previewView.frame = self.bounds; +} + +#pragma mark - Click Event + +- (void)signleTapAction { + if (self.singleTapGestureBlock) { + self.singleTapGestureBlock(); + } +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.h b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.h new file mode 100644 index 0000000..2d5d677 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.h @@ -0,0 +1,25 @@ +// +// TZPhotoPreviewController.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@interface TZPhotoPreviewController : UIViewController + +@property (nonatomic, strong) NSMutableArray *models; ///< All photo models / 所有图片模型数组 +@property (nonatomic, strong) NSMutableArray *photos; ///< All photos / 所有图片数组 +@property (nonatomic, assign) NSInteger currentIndex; ///< Index of the photo user click / 用户点击的图片的索引 +@property (nonatomic, assign) BOOL isSelectOriginalPhoto; ///< If YES,return original photo / 是否返回原图 +@property (nonatomic, assign) BOOL isCropImage; + +/// Return the new selected photos / 返回最新的选中图片数组 +@property (nonatomic, copy) void (^backButtonClickBlock)(BOOL isSelectOriginalPhoto); +@property (nonatomic, copy) void (^doneButtonClickBlock)(BOOL isSelectOriginalPhoto); +@property (nonatomic, copy) void (^doneButtonClickBlockCropMode)(UIImage *cropedImage,id asset); +@property (nonatomic, copy) void (^doneButtonClickBlockWithPreviewType)(NSArray *photos,NSArray *assets,BOOL isSelectOriginalPhoto); + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.m b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.m new file mode 100644 index 0000000..ae3e969 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewController.m @@ -0,0 +1,686 @@ +// +// TZPhotoPreviewController.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "TZPhotoPreviewController.h" +#import "TZPhotoPreviewCell.h" +#import "TZAssetModel.h" +#import "UIView+TZLayout.h" +#import "TZImagePickerController.h" +#import "TZImageManager.h" +#import "TZImageCropManager.h" + +@interface TZPhotoPreviewController () { + UICollectionView *_collectionView; + UICollectionViewFlowLayout *_layout; + NSArray *_photosTemp; + NSArray *_assetsTemp; + + UIView *_naviBar; + UIButton *_backButton; + UIButton *_selectButton; + UILabel *_indexLabel; + + UIView *_toolBar; + UIButton *_doneButton; + UIImageView *_numberImageView; + UILabel *_numberLabel; + UIButton *_originalPhotoButton; + UILabel *_originalPhotoLabel; + + CGFloat _offsetItemCount; + + BOOL _didSetIsSelectOriginalPhoto; +} +@property (nonatomic, assign) BOOL isHideNaviBar; +@property (nonatomic, strong) UIView *cropBgView; +@property (nonatomic, strong) UIView *cropView; + +@property (nonatomic, assign) double progress; +@property (strong, nonatomic) UIAlertController *alertView; +@property (nonatomic, strong) UIView *iCloudErrorView; +@end + +@implementation TZPhotoPreviewController + +- (void)viewDidLoad { + [super viewDidLoad]; + [TZImageManager manager].shouldFixOrientation = YES; + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (!_didSetIsSelectOriginalPhoto) { + _isSelectOriginalPhoto = _tzImagePickerVc.isSelectOriginalPhoto; + } + if (!self.models.count) { + self.models = [NSMutableArray arrayWithArray:_tzImagePickerVc.selectedModels]; + _assetsTemp = [NSMutableArray arrayWithArray:_tzImagePickerVc.selectedAssets]; + } + [self configCollectionView]; + [self configCustomNaviBar]; + [self configBottomToolBar]; + self.view.clipsToBounds = YES; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +} + +- (void)setIsSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto { + _isSelectOriginalPhoto = isSelectOriginalPhoto; + _didSetIsSelectOriginalPhoto = YES; +} + +- (void)setPhotos:(NSMutableArray *)photos { + _photos = photos; + _photosTemp = [NSArray arrayWithArray:photos]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:YES animated:YES]; + [UIApplication sharedApplication].statusBarHidden = YES; + [_collectionView setContentOffset:CGPointMake((self.view.tz_width + 20) * self.currentIndex, 0) animated:NO]; + [self refreshNaviBarAndBottomBarState]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc.needShowStatusBar) { + [UIApplication sharedApplication].statusBarHidden = NO; + } + [self.navigationController setNavigationBarHidden:NO animated:YES]; + [TZImageManager manager].shouldFixOrientation = NO; +} + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (void)configCustomNaviBar { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + + _naviBar = [[UIView alloc] initWithFrame:CGRectZero]; + _naviBar.backgroundColor = [UIColor colorWithRed:(34/255.0) green:(34/255.0) blue:(34/255.0) alpha:0.7]; + + _backButton = [[UIButton alloc] initWithFrame:CGRectZero]; + [_backButton setImage:[UIImage tz_imageNamedFromMyBundle:@"navi_back"] forState:UIControlStateNormal]; + [_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [_backButton addTarget:self action:@selector(backButtonClick) forControlEvents:UIControlEventTouchUpInside]; + + _selectButton = [[UIButton alloc] initWithFrame:CGRectZero]; + [_selectButton setImage:tzImagePickerVc.photoDefImage forState:UIControlStateNormal]; + [_selectButton setImage:tzImagePickerVc.photoSelImage forState:UIControlStateSelected]; + _selectButton.imageView.clipsToBounds = YES; + _selectButton.imageEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0); + _selectButton.imageView.contentMode = UIViewContentModeScaleAspectFit; + [_selectButton addTarget:self action:@selector(select:) forControlEvents:UIControlEventTouchUpInside]; + _selectButton.hidden = !tzImagePickerVc.showSelectBtn; + + _indexLabel = [[UILabel alloc] init]; + _indexLabel.adjustsFontSizeToFitWidth = YES; + _indexLabel.font = [UIFont systemFontOfSize:14]; + _indexLabel.textColor = [UIColor whiteColor]; + _indexLabel.textAlignment = NSTextAlignmentCenter; + + [_naviBar addSubview:_selectButton]; + [_naviBar addSubview:_indexLabel]; + [_naviBar addSubview:_backButton]; + [self.view addSubview:_naviBar]; +} + +- (void)configBottomToolBar { + _toolBar = [[UIView alloc] initWithFrame:CGRectZero]; + static CGFloat rgb = 34 / 255.0; + _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7]; + + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (_tzImagePickerVc.allowPickingOriginalPhoto) { + _originalPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, [TZCommonTools tz_isRightToLeftLayout] ? 10 : -10, 0, 0); + _originalPhotoButton.backgroundColor = [UIColor clearColor]; + [_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside]; + _originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:13]; + [_originalPhotoButton setTitle:_tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateNormal]; + [_originalPhotoButton setTitle:_tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateSelected]; + [_originalPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + [_originalPhotoButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + [_originalPhotoButton setImage:_tzImagePickerVc.photoPreviewOriginDefImage forState:UIControlStateNormal]; + [_originalPhotoButton setImage:_tzImagePickerVc.photoOriginSelImage forState:UIControlStateSelected]; + + _originalPhotoLabel = [[UILabel alloc] init]; + _originalPhotoLabel.textAlignment = NSTextAlignmentLeft; + _originalPhotoLabel.font = [UIFont systemFontOfSize:13]; + _originalPhotoLabel.textColor = [UIColor whiteColor]; + _originalPhotoLabel.backgroundColor = [UIColor clearColor]; + if (_isSelectOriginalPhoto) [self showPhotoBytes]; + } + + _doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _doneButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [_doneButton setTitle:_tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal]; + [_doneButton setTitleColor:_tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal]; + + _numberImageView = [[UIImageView alloc] initWithImage:_tzImagePickerVc.photoNumberIconImage]; + _numberImageView.backgroundColor = [UIColor clearColor]; + _numberImageView.clipsToBounds = YES; + _numberImageView.contentMode = UIViewContentModeScaleAspectFit; + _numberImageView.hidden = _tzImagePickerVc.selectedModels.count <= 0; + + _numberLabel = [[UILabel alloc] init]; + _numberLabel.font = [UIFont systemFontOfSize:15]; + _numberLabel.adjustsFontSizeToFitWidth = YES; + _numberLabel.textColor = [UIColor whiteColor]; + _numberLabel.textAlignment = NSTextAlignmentCenter; + _numberLabel.text = [NSString stringWithFormat:@"%zd",_tzImagePickerVc.selectedModels.count]; + _numberLabel.hidden = _tzImagePickerVc.selectedModels.count <= 0; + _numberLabel.backgroundColor = [UIColor clearColor]; + _numberLabel.userInteractionEnabled = YES; + + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doneButtonClick)]; + [_numberLabel addGestureRecognizer:tapGesture]; + + [_originalPhotoButton addSubview:_originalPhotoLabel]; + [_toolBar addSubview:_doneButton]; + [_toolBar addSubview:_originalPhotoButton]; + [_toolBar addSubview:_numberImageView]; + [_toolBar addSubview:_numberLabel]; + [self.view addSubview:_toolBar]; + + if (_tzImagePickerVc.photoPreviewPageUIConfigBlock) { + _tzImagePickerVc.photoPreviewPageUIConfigBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel); + } +} + +- (void)configCollectionView { + _layout = [[UICollectionViewFlowLayout alloc] init]; + _layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout]; + _collectionView.backgroundColor = [UIColor blackColor]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + _collectionView.pagingEnabled = YES; + _collectionView.scrollsToTop = NO; + _collectionView.showsHorizontalScrollIndicator = NO; + _collectionView.contentOffset = CGPointMake(0, 0); + _collectionView.contentSize = CGSizeMake(self.models.count * (self.view.tz_width + 20), 0); + if (@available(iOS 11, *)) { + _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + [self.view addSubview:_collectionView]; + [_collectionView registerClass:[TZPhotoPreviewCell class] forCellWithReuseIdentifier:@"TZPhotoPreviewCell"]; + [_collectionView registerClass:[TZPhotoPreviewCell class] forCellWithReuseIdentifier:@"TZPhotoPreviewCellGIF"]; + [_collectionView registerClass:[TZVideoPreviewCell class] forCellWithReuseIdentifier:@"TZVideoPreviewCell"]; + [_collectionView registerClass:[TZGifPreviewCell class] forCellWithReuseIdentifier:@"TZGifPreviewCell"]; + + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (_tzImagePickerVc.scaleAspectFillCrop && _tzImagePickerVc.allowCrop) { + _collectionView.scrollEnabled = NO; + } +} + +- (void)configCropView { + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (_tzImagePickerVc.maxImagesCount <= 1 && _tzImagePickerVc.allowCrop && _tzImagePickerVc.allowPickingImage) { + [_cropView removeFromSuperview]; + [_cropBgView removeFromSuperview]; + + _cropBgView = [UIView new]; + _cropBgView.userInteractionEnabled = NO; + _cropBgView.frame = self.view.bounds; + _cropBgView.backgroundColor = [UIColor clearColor]; + [self.view addSubview:_cropBgView]; + [TZImageCropManager overlayClippingWithView:_cropBgView cropRect:_tzImagePickerVc.cropRect containerView:self.view needCircleCrop:_tzImagePickerVc.needCircleCrop]; + + _cropView = [UIView new]; + _cropView.userInteractionEnabled = NO; + _cropView.frame = _tzImagePickerVc.cropRect; + _cropView.backgroundColor = [UIColor clearColor]; + _cropView.layer.borderColor = [UIColor whiteColor].CGColor; + _cropView.layer.borderWidth = 1.0; + if (_tzImagePickerVc.needCircleCrop) { + _cropView.layer.cornerRadius = _tzImagePickerVc.cropRect.size.width / 2; + _cropView.clipsToBounds = YES; + } + [self.view addSubview:_cropView]; + if (_tzImagePickerVc.cropViewSettingBlock) { + _tzImagePickerVc.cropViewSettingBlock(_cropView); + } + + [self.view bringSubviewToFront:_naviBar]; + [self.view bringSubviewToFront:_toolBar]; + } +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + + BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height; + CGFloat statusBarHeight = isFullScreen ? [TZCommonTools tz_statusBarHeight] : 0; + CGFloat statusBarHeightInterval = isFullScreen ? (statusBarHeight - 20) : 0; + CGFloat naviBarHeight = statusBarHeight + _tzImagePickerVc.navigationBar.tz_height; + _naviBar.frame = CGRectMake(0, 0, self.view.tz_width, naviBarHeight); + _backButton.frame = CGRectMake(10, 10 + statusBarHeightInterval, 44, 44); + _selectButton.frame = CGRectMake(self.view.tz_width - 56, 10 + statusBarHeightInterval, 44, 44); + _indexLabel.frame = _selectButton.frame; + + _layout.itemSize = CGSizeMake(self.view.tz_width + 20, self.view.tz_height); + _layout.minimumInteritemSpacing = 0; + _layout.minimumLineSpacing = 0; + _collectionView.frame = CGRectMake(-10, 0, self.view.tz_width + 20, self.view.tz_height); + [_collectionView setCollectionViewLayout:_layout]; + if (_offsetItemCount > 0) { + CGFloat offsetX = _offsetItemCount * _layout.itemSize.width; + [_collectionView setContentOffset:CGPointMake(offsetX, 0)]; + } + if (_tzImagePickerVc.allowCrop) { + [_collectionView reloadData]; + } + + CGFloat toolBarHeight = 44 + [TZCommonTools tz_safeAreaInsets].bottom; + CGFloat toolBarTop = self.view.tz_height - toolBarHeight; + _toolBar.frame = CGRectMake(0, toolBarTop, self.view.tz_width, toolBarHeight); + if (_tzImagePickerVc.allowPickingOriginalPhoto) { + CGFloat fullImageWidth = [_tzImagePickerVc.fullImageBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size.width; + _originalPhotoButton.frame = CGRectMake(0, 0, fullImageWidth + 56, 44); + _originalPhotoLabel.frame = CGRectMake(fullImageWidth + 42, 0, 80, 44); + } + [_doneButton sizeToFit]; + _doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, MAX(44, _doneButton.tz_width), 44); + _numberImageView.frame = CGRectMake(_doneButton.tz_left - 24 - 5, 10, 24, 24); + _numberLabel.frame = _numberImageView.frame; + + [self configCropView]; + + if (_tzImagePickerVc.photoPreviewPageDidLayoutSubviewsBlock) { + _tzImagePickerVc.photoPreviewPageDidLayoutSubviewsBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel); + } +} + +#pragma mark - Notification + +- (void)didChangeStatusBarOrientationNotification:(NSNotification *)noti { + _offsetItemCount = _collectionView.contentOffset.x / _layout.itemSize.width; +} + +#pragma mark - Click Event + +- (void)select:(UIButton *)selectButton { + [self select:selectButton refreshCount:YES]; +} + +- (void)select:(UIButton *)selectButton refreshCount:(BOOL)refreshCount { + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + TZAssetModel *model = _models[self.currentIndex]; + if (!selectButton.isSelected) { + // 1. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制 + if (_tzImagePickerVc.selectedModels.count >= _tzImagePickerVc.maxImagesCount) { + NSString *title = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Select a maximum of %zd photos"], _tzImagePickerVc.maxImagesCount]; + [_tzImagePickerVc showAlertWithTitle:title]; + return; + // 2. if not over the maxImagesCount / 如果没有超过最大个数限制 + } else { + if ([[TZImageManager manager] isAssetCannotBeSelected:model.asset]) { + return; + } + [_tzImagePickerVc addSelectedModel:model]; + [self setAsset:model.asset isSelect:YES]; + if (self.photos) { + [_tzImagePickerVc.selectedAssets addObject:_assetsTemp[self.currentIndex]]; + [self.photos addObject:_photosTemp[self.currentIndex]]; + } + if (model.type == TZAssetModelMediaTypeVideo && !_tzImagePickerVc.allowPickingMultipleVideo) { + [_tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Select the video when in multi state, we will handle the video as a photo"]]; + } + } + } else { + NSArray *selectedModels = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels]; + for (TZAssetModel *model_item in selectedModels) { + if ([model.asset.localIdentifier isEqualToString:model_item.asset.localIdentifier]) { + // 1.6.7版本更新:防止有多个一样的model,一次性被移除了 + NSArray *selectedModelsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels]; + for (NSInteger i = 0; i < selectedModelsTmp.count; i++) { + TZAssetModel *model = selectedModelsTmp[i]; + if ([model isEqual:model_item]) { + [_tzImagePickerVc removeSelectedModel:model]; + // [_tzImagePickerVc.selectedModels removeObjectAtIndex:i]; + break; + } + } + if (self.photos) { + // 1.6.7版本更新:防止有多个一样的asset,一次性被移除了 + NSArray *selectedAssetsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedAssets]; + for (NSInteger i = 0; i < selectedAssetsTmp.count; i++) { + id asset = selectedAssetsTmp[i]; + if ([asset isEqual:_assetsTemp[self.currentIndex]]) { + [_tzImagePickerVc.selectedAssets removeObjectAtIndex:i]; + break; + } + } + // [_tzImagePickerVc.selectedAssets removeObject:_assetsTemp[self.currentIndex]]; + [self.photos removeObject:_photosTemp[self.currentIndex]]; + } + [self setAsset:model.asset isSelect:NO]; + break; + } + } + } + model.isSelected = !selectButton.isSelected; + if (refreshCount) { + [self refreshNaviBarAndBottomBarState]; + } + if (model.isSelected) { + [UIView showOscillatoryAnimationWithLayer:selectButton.imageView.layer type:TZOscillatoryAnimationToBigger]; + } + [UIView showOscillatoryAnimationWithLayer:_numberImageView.layer type:TZOscillatoryAnimationToSmaller]; +} + +- (void)backButtonClick { + if (self.navigationController.childViewControllers.count < 2) { + [self.navigationController dismissViewControllerAnimated:YES completion:nil]; + if ([self.navigationController isKindOfClass: [TZImagePickerController class]]) { + TZImagePickerController *nav = (TZImagePickerController *)self.navigationController; + if (nav.imagePickerControllerDidCancelHandle) { + nav.imagePickerControllerDidCancelHandle(); + } + } + return; + } + [self.navigationController popViewControllerAnimated:YES]; + if (self.backButtonClickBlock) { + self.backButtonClickBlock(_isSelectOriginalPhoto); + } +} + +- (void)doneButtonClick { + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + // 如果图片正在从iCloud同步中,提醒用户 + if (_progress > 0 && _progress < 1 && (_selectButton.isSelected || !_tzImagePickerVc.selectedModels.count )) { + _alertView = [_tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Synchronizing photos from iCloud"]]; + return; + } + + // 如果没有选中过照片 点击确定时选中当前预览的照片 + if (_tzImagePickerVc.selectedModels.count == 0 && _tzImagePickerVc.minImagesCount <= 0 && _tzImagePickerVc.autoSelectCurrentWhenDone) { + TZAssetModel *model = _models[self.currentIndex]; + if ([[TZImageManager manager] isAssetCannotBeSelected:model.asset]) { + return; + } + [self select:_selectButton refreshCount:NO]; + } + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.currentIndex inSection:0]; + TZPhotoPreviewCell *cell = (TZPhotoPreviewCell *)[_collectionView cellForItemAtIndexPath:indexPath]; + if (_tzImagePickerVc.allowCrop && [cell isKindOfClass:[TZPhotoPreviewCell class]]) { // 裁剪状态 + _doneButton.enabled = NO; + [_tzImagePickerVc showProgressHUD]; + UIImage *cropedImage = [TZImageCropManager cropImageView:cell.previewView.imageView toRect:_tzImagePickerVc.cropRect zoomScale:cell.previewView.scrollView.zoomScale containerView:self.view]; + if (_tzImagePickerVc.needCircleCrop) { + cropedImage = [TZImageCropManager circularClipImage:cropedImage]; + } + _doneButton.enabled = YES; + [_tzImagePickerVc hideProgressHUD]; + if (self.doneButtonClickBlockCropMode) { + TZAssetModel *model = _models[self.currentIndex]; + self.doneButtonClickBlockCropMode(cropedImage,model.asset); + } + } else if (self.doneButtonClickBlock) { // 非裁剪状态 + self.doneButtonClickBlock(_isSelectOriginalPhoto); + } + if (self.doneButtonClickBlockWithPreviewType) { + self.doneButtonClickBlockWithPreviewType(self.photos,_tzImagePickerVc.selectedAssets,self.isSelectOriginalPhoto); + } +} + +- (void)originalPhotoButtonClick { + TZAssetModel *model = _models[self.currentIndex]; + if ([[TZImageManager manager] isAssetCannotBeSelected:model.asset]) { + return; + } + _originalPhotoButton.selected = !_originalPhotoButton.isSelected; + _isSelectOriginalPhoto = _originalPhotoButton.isSelected; + _originalPhotoLabel.hidden = !_originalPhotoButton.isSelected; + if (_isSelectOriginalPhoto) { + [self showPhotoBytes]; + if (!_selectButton.isSelected) { + // 如果当前已选择照片张数 < 最大可选张数 && 最大可选张数大于1,就选中该张图 + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (_tzImagePickerVc.selectedModels.count < _tzImagePickerVc.maxImagesCount && _tzImagePickerVc.showSelectBtn) { + [self select:_selectButton]; + } + } + } +} + +- (void)didTapPreviewCell { + self.isHideNaviBar = !self.isHideNaviBar; + _naviBar.hidden = self.isHideNaviBar; + _toolBar.hidden = self.isHideNaviBar; +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + CGFloat offSetWidth = scrollView.contentOffset.x; + offSetWidth = offSetWidth + ((self.view.tz_width + 20) * 0.5); + + NSInteger currentIndex = offSetWidth / (self.view.tz_width + 20); + if (currentIndex < _models.count && _currentIndex != currentIndex) { + _currentIndex = currentIndex; + [self refreshNaviBarAndBottomBarState]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:@"photoPreviewCollectionViewDidScroll" object:nil]; +} + +#pragma mark - UICollectionViewDataSource && Delegate + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return _models.count; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + TZAssetModel *model = _models[indexPath.item]; + + TZAssetPreviewCell *cell; + __weak typeof(self) weakSelf = self; + if (_tzImagePickerVc.allowPickingMultipleVideo && model.type == TZAssetModelMediaTypeVideo) { + cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZVideoPreviewCell" forIndexPath:indexPath]; + TZVideoPreviewCell *currentCell = (TZVideoPreviewCell *)cell; + currentCell.iCloudSyncFailedHandle = ^(id asset, BOOL isSyncFailed) { + model.iCloudFailed = isSyncFailed; + [weakSelf didICloudSyncStatusChanged:model]; + }; + } else if (_tzImagePickerVc.allowPickingMultipleVideo && model.type == TZAssetModelMediaTypePhotoGif && _tzImagePickerVc.allowPickingGif) { + cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZGifPreviewCell" forIndexPath:indexPath]; + TZGifPreviewCell *currentCell = (TZGifPreviewCell *)cell; + currentCell.previewView.iCloudSyncFailedHandle = ^(id asset, BOOL isSyncFailed) { + model.iCloudFailed = isSyncFailed; + [weakSelf didICloudSyncStatusChanged:model]; + }; + } else { + NSString *reuseId = model.type == TZAssetModelMediaTypePhotoGif ? @"TZPhotoPreviewCellGIF" : @"TZPhotoPreviewCell"; + cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseId forIndexPath:indexPath]; + TZPhotoPreviewCell *photoPreviewCell = (TZPhotoPreviewCell *)cell; + photoPreviewCell.cropRect = _tzImagePickerVc.cropRect; + photoPreviewCell.allowCrop = _tzImagePickerVc.allowCrop; + photoPreviewCell.scaleAspectFillCrop = _tzImagePickerVc.scaleAspectFillCrop; + __weak typeof(_collectionView) weakCollectionView = _collectionView; + __weak typeof(photoPreviewCell) weakCell = photoPreviewCell; + [photoPreviewCell setImageProgressUpdateBlock:^(double progress) { + __strong typeof(weakSelf) strongSelf = weakSelf; + __strong typeof(weakCollectionView) strongCollectionView = weakCollectionView; + __strong typeof(weakCell) strongCell = weakCell; + strongSelf.progress = progress; + if (progress >= 1) { + if (strongSelf.isSelectOriginalPhoto) [strongSelf showPhotoBytes]; + if (strongSelf.alertView && [strongCollectionView.visibleCells containsObject:strongCell]) { + [strongSelf.alertView dismissViewControllerAnimated:YES completion:^{ + strongSelf.alertView = nil; + [strongSelf doneButtonClick]; + }]; + } + } + }]; + photoPreviewCell.previewView.iCloudSyncFailedHandle = ^(id asset, BOOL isSyncFailed) { + model.iCloudFailed = isSyncFailed; + [weakSelf didICloudSyncStatusChanged:model]; + }; + } + + cell.model = model; + [cell setSingleTapGestureBlock:^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf didTapPreviewCell]; + }]; + + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if ([cell isKindOfClass:[TZPhotoPreviewCell class]]) { + [(TZPhotoPreviewCell *)cell recoverSubviews]; + } +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if ([cell isKindOfClass:[TZPhotoPreviewCell class]]) { + [(TZPhotoPreviewCell *)cell recoverSubviews]; + } else if ([cell isKindOfClass:[TZVideoPreviewCell class]]) { + TZVideoPreviewCell *videoCell = (TZVideoPreviewCell *)cell; + if (videoCell.player && videoCell.player.rate != 0.0) { + [videoCell pausePlayerAndShowNaviBar]; + } + } +} + +#pragma mark - Private Method + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + // NSLog(@"%@ dealloc",NSStringFromClass(self.class)); +} + +- (void)refreshNaviBarAndBottomBarState { + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + TZAssetModel *model = _models[self.currentIndex]; + _selectButton.selected = model.isSelected; + [self refreshSelectButtonImageViewContentMode]; + if (_selectButton.isSelected && _tzImagePickerVc.showSelectedIndex && _tzImagePickerVc.showSelectBtn) { + NSString *index = [NSString stringWithFormat:@"%d", (int)([_tzImagePickerVc.selectedAssetIds indexOfObject:model.asset.localIdentifier] + 1)]; + _indexLabel.text = index; + _indexLabel.hidden = NO; + } else { + _indexLabel.hidden = YES; + } + _numberLabel.text = [NSString stringWithFormat:@"%zd",_tzImagePickerVc.selectedModels.count]; + _numberImageView.hidden = (_tzImagePickerVc.selectedModels.count <= 0 || _isHideNaviBar || _isCropImage); + _numberLabel.hidden = (_tzImagePickerVc.selectedModels.count <= 0 || _isHideNaviBar || _isCropImage); + + _originalPhotoButton.selected = _isSelectOriginalPhoto; + _originalPhotoLabel.hidden = !_originalPhotoButton.isSelected; + if (_isSelectOriginalPhoto) [self showPhotoBytes]; + + // If is previewing video, hide original photo button + // 如果正在预览的是视频,隐藏原图按钮 + if (!_isHideNaviBar) { + if (model.type == TZAssetModelMediaTypeVideo) { + _originalPhotoButton.hidden = YES; + _originalPhotoLabel.hidden = YES; + } else { + _originalPhotoButton.hidden = NO; + if (_isSelectOriginalPhoto) _originalPhotoLabel.hidden = NO; + } + } + + _doneButton.hidden = NO; + _selectButton.hidden = !_tzImagePickerVc.showSelectBtn; + // 让宽度/高度小于 最小可选照片尺寸 的图片不能选中 + if (![[TZImageManager manager] isPhotoSelectableWithAsset:model.asset]) { + _numberLabel.hidden = YES; + _numberImageView.hidden = YES; + _selectButton.hidden = YES; + _originalPhotoButton.hidden = YES; + _originalPhotoLabel.hidden = YES; + _doneButton.hidden = YES; + } + // iCloud同步失败的UI刷新 + [self didICloudSyncStatusChanged:model]; + if (_tzImagePickerVc.photoPreviewPageDidRefreshStateBlock) { + _tzImagePickerVc.photoPreviewPageDidRefreshStateBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel); + } +} + +- (void)refreshSelectButtonImageViewContentMode { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (self->_selectButton.imageView.image.size.width <= 27) { + self->_selectButton.imageView.contentMode = UIViewContentModeCenter; + } else { + self->_selectButton.imageView.contentMode = UIViewContentModeScaleAspectFit; + } + }); +} + +- (void)didICloudSyncStatusChanged:(TZAssetModel *)model{ + dispatch_async(dispatch_get_main_queue(), ^{ + TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; + // onlyReturnAsset为NO时,依赖TZ返回大图,所以需要有iCloud同步失败的提示,并且不能选择, + if (_tzImagePickerVc.onlyReturnAsset) { + return; + } + TZAssetModel *currentModel = self.models[self.currentIndex]; + if (_tzImagePickerVc.selectedModels.count <= 0) { + self->_doneButton.enabled = !currentModel.iCloudFailed; + } else { + self->_doneButton.enabled = YES; + } + self->_selectButton.hidden = currentModel.iCloudFailed || !_tzImagePickerVc.showSelectBtn; + if (currentModel.iCloudFailed) { + self->_originalPhotoButton.hidden = YES; + self->_originalPhotoLabel.hidden = YES; + } + }); +} + +- (void)showPhotoBytes { + [[TZImageManager manager] getPhotosBytesWithArray:@[_models[self.currentIndex]] completion:^(NSString *totalBytes) { + self->_originalPhotoLabel.text = [NSString stringWithFormat:@"(%@)",totalBytes]; + }]; +} + +- (NSInteger)currentIndex { + return [TZCommonTools tz_isRightToLeftLayout] ? self.models.count - _currentIndex - 1 : _currentIndex; +} + +/// 选中/取消选中某张照片 +- (void)setAsset:(PHAsset *)asset isSelect:(BOOL)isSelect { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (isSelect && [tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didSelectAsset:photo:isSelectOriginalPhoto:)]) { + [self callDelegate:asset isSelect:YES]; + } + if (!isSelect && [tzImagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didDeselectAsset:photo:isSelectOriginalPhoto:)]) { + [self callDelegate:asset isSelect:NO]; + } +} + +/// 调用选中/取消选中某张照片的代理方法 +- (void)callDelegate:(PHAsset *)asset isSelect:(BOOL)isSelect { + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + __weak typeof(self) weakSelf = self; + __weak typeof(tzImagePickerVc) weakImagePickerVc= tzImagePickerVc; + [[TZImageManager manager] getPhotoWithAsset:asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + if (isDegraded) return; + __strong typeof(weakSelf) strongSelf = weakSelf; + __strong typeof(weakImagePickerVc) strongImagePickerVc = weakImagePickerVc; + if (isSelect) { + [strongImagePickerVc.pickerDelegate imagePickerController:strongImagePickerVc didSelectAsset:asset photo:photo isSelectOriginalPhoto:strongSelf.isSelectOriginalPhoto]; + } else { + [strongImagePickerVc.pickerDelegate imagePickerController:strongImagePickerVc didDeselectAsset:asset photo:photo isSelectOriginalPhoto:strongSelf.isSelectOriginalPhoto]; + } + }]; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZProgressView.h b/TZImagePickerController/TZImagePickerController/TZProgressView.h new file mode 100644 index 0000000..65d4459 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZProgressView.h @@ -0,0 +1,15 @@ +// +// TZProgressView.h +// TZImagePickerController +// +// Created by ttouch on 2016/12/6. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import + +@interface TZProgressView : UIView + +@property (nonatomic, assign) double progress; + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZProgressView.m b/TZImagePickerController/TZImagePickerController/TZProgressView.m new file mode 100644 index 0000000..31a6182 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZProgressView.m @@ -0,0 +1,55 @@ +// +// TZProgressView.m +// TZImagePickerController +// +// Created by ttouch on 2016/12/6. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "TZProgressView.h" + +@interface TZProgressView () +@property (nonatomic, strong) CAShapeLayer *progressLayer; +@end + +@implementation TZProgressView + +- (instancetype)init { + self = [super init]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + + _progressLayer = [CAShapeLayer layer]; + _progressLayer.fillColor = [[UIColor clearColor] CGColor]; + _progressLayer.strokeColor = [[UIColor whiteColor] CGColor]; + _progressLayer.opacity = 1; + _progressLayer.lineCap = kCALineCapRound; + _progressLayer.lineWidth = 5; + + [_progressLayer setShadowColor:[UIColor blackColor].CGColor]; + [_progressLayer setShadowOffset:CGSizeMake(1, 1)]; + [_progressLayer setShadowOpacity:0.5]; + [_progressLayer setShadowRadius:2]; + } + return self; +} + +- (void)drawRect:(CGRect)rect { + CGPoint center = CGPointMake(rect.size.width / 2, rect.size.height / 2); + CGFloat radius = rect.size.width / 2; + CGFloat startA = - M_PI_2; + CGFloat endA = - M_PI_2 + M_PI * 2 * _progress; + _progressLayer.frame = self.bounds; + UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES]; + _progressLayer.path =[path CGPath]; + + [_progressLayer removeFromSuperlayer]; + [self.layer addSublayer:_progressLayer]; +} + +- (void)setProgress:(double)progress { + _progress = progress; + [self setNeedsDisplay]; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZVideoCropController.h b/TZImagePickerController/TZImagePickerController/TZVideoCropController.h new file mode 100644 index 0000000..75ad258 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZVideoCropController.h @@ -0,0 +1,47 @@ +// +// TZVideoCropController.h +// TZImagePickerController +// +// Created by 肖兰月 on 2021/5/27. +// Copyright © 2021 谭真. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class TZAssetModel,TZImagePickerController; + +@interface TZVideoCropController : UIViewController +@property (nonatomic, strong) TZAssetModel *model; +@property (nonatomic, weak) TZImagePickerController *imagePickerVc; +@end + +@protocol TZVideoEditViewDelegate +- (void)editViewCropRectBeginChange; +- (void)editViewCropRectEndChange; +@end + +@interface TZVideoEditView : UIView +@property (strong, nonatomic) UIImageView *beginImgView; +@property (strong, nonatomic) UIImageView *endImgView; +@property (strong, nonatomic) UIView *indicatorLine; +@property (assign, nonatomic) CGFloat videoDuration; +@property (assign, nonatomic) NSInteger maxCropVideoDuration; +@property (assign, nonatomic) CGRect cropRect; +@property (assign, nonatomic) CGFloat allImgWidth; +@property (assign, nonatomic) CGFloat minCropRectWidth; + +@property (nonatomic, weak) id delegate; + +- (void)resetIndicatorLine; +- (void)indicatorLineAnimateWithDuration:(NSTimeInterval)duration cropRect:(CGRect)cropRect; +@end + + + +@interface TZVideoPictureCell : UICollectionViewCell +@property (strong, nonatomic) UIImageView *imgView; +@end + +NS_ASSUME_NONNULL_END diff --git a/TZImagePickerController/TZImagePickerController/TZVideoCropController.m b/TZImagePickerController/TZImagePickerController/TZVideoCropController.m new file mode 100644 index 0000000..a631a60 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZVideoCropController.m @@ -0,0 +1,673 @@ +// +// TZVideoCropController.m +// TZImagePickerController +// +// Created by 肖兰月 on 2021/5/27. +// Copyright © 2021 谭真. All rights reserved. +// + +#import "TZVideoCropController.h" +#import +#import "UIView+TZLayout.h" +#import "TZImageManager.h" +#import "TZAssetModel.h" +#import "TZImagePickerController.h" + +@interface TZVideoCropController () { + AVPlayer *_player; + AVPlayerLayer *_playerLayer; + UIButton *_playButton; + UIImage *_cover; + NSString *_outputPath; + NSString *_errorMsg; + + UIButton *_cancelButton; + UIButton *_doneButton; + UIProgressView *_progress; + UILabel *_cropVideoDurationLabel; + + AVAssetImageGenerator *_imageGenerator; + AVAsset *_asset; + + CGFloat _collectionViewBeginOffsetX; + BOOL _isPlayed; + CGFloat _itemW; + BOOL _isDraging; + + UIStatusBarStyle _originStatusBarStyle; +} + +// iCloud无法同步提示UI +@property (nonatomic, strong) UIView *iCloudErrorView; +@property (strong, nonatomic) UICollectionView *collectionView; +@property (strong, nonatomic) TZVideoEditView *videoEditView; +@property (strong, nonatomic) NSMutableArray *videoImgArray; +@property (strong, nonatomic) NSArray *imageTimes; +@property (strong, nonatomic) NSTimer *timer; + +@end + +@implementation TZVideoCropController + +#define VideoEditLeftMargin 40 +#define PanImageWidth 10 +#define MinCropVideoDuration 1 + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + [self configMoviePlayer]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayer) name:UIApplicationWillResignActiveNotification object:nil]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [self stopTimer]; +} + +- (void)configMoviePlayer { + [[TZImageManager manager] getPhotoWithAsset:_model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + BOOL iCloudSyncFailed = !photo && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.iCloudErrorView.hidden = !iCloudSyncFailed; + self->_doneButton.enabled = !iCloudSyncFailed; + }]; + [[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + self->_asset = playerItem.asset; + self->_player = [AVPlayer playerWithPlayerItem:playerItem]; + self->_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self->_player]; + self->_playerLayer.frame = self.view.bounds; + [self.view.layer addSublayer:self->_playerLayer]; + [self configPlayButton]; + [self configBottomToolBar]; + if (self.imagePickerVc.allowEditVideo) { + [self configVideoImageCollectionView]; + [self configVideoEditView]; + [self generateVideoImage]; + } + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayer) name:AVPlayerItemDidPlayToEndTimeNotification object:self->_player.currentItem]; + }); + }]; +} + +- (void)configPlayButton { + _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted]; + [_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_playButton]; +} + +- (void)configBottomToolBar { + _cropVideoDurationLabel = UILabel.new; + _cropVideoDurationLabel.textAlignment = NSTextAlignmentCenter; + _cropVideoDurationLabel.textColor = UIColor.whiteColor; + _cropVideoDurationLabel.font = [UIFont systemFontOfSize:12]; + [self.view addSubview:_cropVideoDurationLabel]; + + _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _cancelButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_cancelButton setTitle:[NSBundle tz_localizedStringForKey:@"Cancel"] forState:0]; + [_cancelButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + [_cancelButton addTarget:self action:@selector(cancelButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_cancelButton]; + + _doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _doneButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [_doneButton setTitle:self.imagePickerVc.doneBtnTitleStr forState:UIControlStateNormal]; + [_doneButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + [_doneButton setTitleColor:self.imagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled]; + [self.view addSubview:_doneButton]; + + if (self.imagePickerVc.videoEditViewPageUIConfigBlock) { + self.imagePickerVc.videoEditViewPageUIConfigBlock(_playButton, _cropVideoDurationLabel, _cancelButton, _doneButton); + } +} + +- (void)configVideoImageCollectionView { + _itemW = (self.view.tz_width - VideoEditLeftMargin * 2 - 2 * PanImageWidth) / 10.0; + UICollectionViewFlowLayout *layout = UICollectionViewFlowLayout.new; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + layout.itemSize = CGSizeMake(_itemW, _itemW * 2); + layout.minimumLineSpacing = 0; + layout.minimumInteritemSpacing = 0; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionView.dataSource = self; + _collectionView.delegate = self; + _collectionView.contentInset = UIEdgeInsetsMake(0, VideoEditLeftMargin + PanImageWidth, 0, VideoEditLeftMargin + PanImageWidth); + _collectionView.clipsToBounds = NO; + _collectionView.showsHorizontalScrollIndicator = NO; + _collectionView.alwaysBounceHorizontal = YES; + [_collectionView registerClass:TZVideoPictureCell.class forCellWithReuseIdentifier:@"TZVideoPictureCell"]; + [self.view addSubview:_collectionView]; +} + +- (void)configVideoEditView { + _videoEditView = TZVideoEditView.new; + _videoEditView.backgroundColor = UIColor.clearColor; + _videoEditView.delegate = self; + _videoEditView.maxCropVideoDuration = self.imagePickerVc.maxCropVideoDuration; + [self.view addSubview:_videoEditView]; +} + +- (UIStatusBarStyle)preferredStatusBarStyle { + if (self.imagePickerVc && [self.imagePickerVc isKindOfClass:[TZImagePickerController class]]) { + return self.imagePickerVc.statusBarStyle; + } + return [super preferredStatusBarStyle]; +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height; + CGFloat statusBarHeight = isFullScreen ? [TZCommonTools tz_statusBarHeight] : 0; + CGFloat statusBarAndNaviBarHeight = statusBarHeight + self.navigationController.navigationBar.tz_height; + + CGFloat toolBarHeight = 44 + [TZCommonTools tz_safeAreaInsets].bottom; + CGFloat doneButtonWidth = [_doneButton.currentTitle boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size.width; + doneButtonWidth = MAX(44, doneButtonWidth); + _cancelButton.frame = CGRectMake(12, self.view.tz_height - toolBarHeight, 44, 44); + [_cancelButton sizeToFit]; + _cancelButton.tz_height = 44; + _doneButton.frame = CGRectMake(self.view.tz_width - doneButtonWidth - 12, self.view.tz_height - toolBarHeight, doneButtonWidth, 44); + _playButton.frame = CGRectMake(0, statusBarAndNaviBarHeight, self.view.tz_width, self.view.tz_height - statusBarAndNaviBarHeight - toolBarHeight); + + CGFloat collectionViewH = (self.view.tz_width - VideoEditLeftMargin * 2 - 2 * PanImageWidth) / 10.0 * 2; + _collectionView.frame = CGRectMake(0, self.view.tz_height - collectionViewH - toolBarHeight - statusBarHeight, self.view.tz_width, collectionViewH); + _videoEditView.frame = _collectionView.frame; + _cropVideoDurationLabel.frame = CGRectMake(0, _videoEditView.tz_bottom, self.view.tz_width, 20); + + CGFloat playerLayerHeight = CGRectGetMinY(_collectionView.frame) - statusBarHeight * 2; + CGFloat playerLayerWidth = self.view.tz_width/self.view.tz_height * playerLayerHeight; + CGFloat playerLayerLeft = (self.view.tz_width - playerLayerWidth) / 2.0; + CGRect playerLayerFrame = CGRectMake(playerLayerLeft, statusBarHeight, playerLayerWidth, playerLayerHeight); + _playerLayer.frame = playerLayerFrame; + _playButton.frame = CGRectMake(0, statusBarAndNaviBarHeight, self.view.tz_width, playerLayerHeight - statusBarAndNaviBarHeight); + + if (self.imagePickerVc.videoEditViewPageDidLayoutSubviewsBlock) { + self.imagePickerVc.videoEditViewPageDidLayoutSubviewsBlock(_playButton, _cropVideoDurationLabel, _cancelButton, _doneButton); + } +} + +- (void)generateVideoImage { + _imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:_asset]; + _imageGenerator.appliesPreferredTrackTransform = YES; + _imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; + _imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; + _imageGenerator.maximumSize = CGSizeMake(100, 100); + + NSTimeInterval durationSeconds = self.model.asset.duration; + self.videoEditView.videoDuration = durationSeconds; + + NSUInteger imageCount = 10; + CGFloat maxCropWidth = self.view.tz_width - (VideoEditLeftMargin + PanImageWidth) * 2; + if (durationSeconds <= MinCropVideoDuration) return; + if (durationSeconds <= self.imagePickerVc.maxCropVideoDuration) { + imageCount = 10; + self.videoEditView.allImgWidth = maxCropWidth; + _cropVideoDurationLabel.text = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Selected for %ld seconds"], (NSInteger)durationSeconds]; + } else { + CGFloat singleWidthSecond = maxCropWidth / self.imagePickerVc.maxCropVideoDuration; + CGFloat allImgWidth = singleWidthSecond * durationSeconds; + self.videoEditView.allImgWidth = allImgWidth; + imageCount = allImgWidth / _itemW; + _cropVideoDurationLabel.text = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Selected for %ld seconds"],(long)self.imagePickerVc.maxCropVideoDuration]; + } + NSArray *assetTracks = [_asset tracksWithMediaType:AVMediaTypeVideo]; + if (!assetTracks.count) { + self.iCloudErrorView.hidden = NO; + _doneButton.enabled = NO; + _cropVideoDurationLabel.hidden = YES; + return; + }; + Float64 frameRate = [[_asset tracksWithMediaType:AVMediaTypeVideo][0] nominalFrameRate];; + NSMutableArray *times = NSMutableArray.array; + NSTimeInterval intervalSecond = durationSeconds/imageCount; + CMTime timeFrame; + for (NSInteger i = 0; i < imageCount; i++) { + timeFrame = CMTimeMake(intervalSecond * i *frameRate, frameRate); + NSValue *timeValue = [NSValue valueWithCMTime:timeFrame]; + [times addObject:timeValue]; + } + self.videoImgArray = NSMutableArray.new; + self.imageTimes = times; + typeof(self) weakSelf = self; + [_imageGenerator generateCGImagesAsynchronouslyForTimes:times completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) { + if (image) { + UIImage *img = [[UIImage alloc] initWithCGImage:image]; + [weakSelf.videoImgArray addObject:img]; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf.collectionView reloadData]; + }); + } + }]; +} + +#pragma mark - UICollectiobViewDataSource & UIcollectionViewDelegate + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.videoImgArray.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + TZVideoPictureCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZVideoPictureCell" forIndexPath:indexPath]; + cell.imgView.image = self.videoImgArray[indexPath.item]; + return cell; +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (!_isDraging) return; + CGFloat offsetX = scrollView.contentOffset.x; + if (offsetX - _collectionViewBeginOffsetX >= self.view.tz_width) { + [self.collectionView setContentOffset:CGPointMake(self.view.tz_width + _collectionViewBeginOffsetX, 0) animated:NO]; + } else if (_collectionViewBeginOffsetX - offsetX >= self.view.tz_width) { + [self.collectionView setContentOffset:CGPointMake(_collectionViewBeginOffsetX - self.view.tz_width, 0) animated:NO]; + } + + [self editViewCropRectBeginChange]; +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + _isDraging = YES; + _collectionViewBeginOffsetX = scrollView.contentOffset.x; +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + _isDraging = NO; + [self editViewCropRectEndChange]; +} + +#pragma mark - TZVideoEditViewDelegate + +- (void)editViewCropRectBeginChange { + [self stopTimer]; + [_playerLayer.player seekToTime:[self getCropStartTime] toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; + + NSTimeInterval second = [self getCropVideoDuration]; + _cropVideoDurationLabel.text = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Selected for %ld seconds"], (NSInteger)second]; +} + +- (void)editViewCropRectEndChange { + if (_isPlayed) { + [self starTimer]; + } +} + +#pragma mark - Click Event + +- (void)playButtonClick { + CMTime currentTime = _player.currentItem.currentTime; + CMTime durationTime = _player.currentItem.duration; + if (_player.rate == 0.0f) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_VIDEO_PLAY_NOTIFICATION" object:_player]; + if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)]; + _isPlayed = YES; + [self starTimer]; + [_playButton setImage:nil forState:UIControlStateNormal]; + } else { + _isPlayed = NO; + [self stopTimer]; + [self pausePlayer]; + } +} + +- (void)cancelButtonClick { + [self dismissViewControllerAnimated:YES completion:nil]; +} + + +- (void)doneButtonClick { + if ([[TZImageManager manager] isAssetCannotBeSelected:_model.asset]) { + return; + } + [self stopTimer]; + + TZImagePickerController *imagePickerVc = self.imagePickerVc; + [imagePickerVc showProgressHUD]; + [[TZImageManager manager] getVideoOutputPathWithAsset:_model.asset presetName:imagePickerVc.presetName timeRange:[self getCropVideoTimeRange] success:^(NSString *outputPath) { + [imagePickerVc hideProgressHUD]; + self->_outputPath = outputPath; + [self dismissAndCallDelegateMethod]; + } failure:^(NSString *errorMessage, NSError *error) { + [imagePickerVc hideProgressHUD]; + self->_errorMsg = errorMessage; + [self dismissAndCallDelegateMethod]; + }]; +} + +- (void)dismissAndCallDelegateMethod { + [self dismissViewControllerAnimated:NO completion:^{ + [self callDelegateMethod]; + }]; + [self.imagePickerVc dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)callDelegateMethod { + if (_outputPath) { + NSURL *videoURL = [NSURL fileURLWithPath:_outputPath]; + if (self.imagePickerVc.saveEditedVideoToAlbum) { + [[TZImageManager manager] saveVideoWithUrl:videoURL completion:^(PHAsset *asset, NSError *error) { + if (error) { // 视频保存失败 + if ([self.imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFailToSaveEditedVideoWithError:)]) { + [self.imagePickerVc.pickerDelegate imagePickerController:self.imagePickerVc didFailToSaveEditedVideoWithError:error]; + } + } + }]; + } + UIImage *coverImage = [[TZImageManager manager] getImageWithVideoURL:videoURL]; + if ([self.imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingAndEditingVideo:outputPath:error:)]) { + [self.imagePickerVc.pickerDelegate imagePickerController:self.imagePickerVc didFinishPickingAndEditingVideo:coverImage outputPath:_outputPath error:nil]; + } + if (self.imagePickerVc.didFinishPickingAndEditingVideoHandle) { + self.imagePickerVc.didFinishPickingAndEditingVideoHandle(coverImage, _outputPath, nil); + } + } else { + if ([self.imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingAndEditingVideo:outputPath:error:)]) { + [self.imagePickerVc.pickerDelegate imagePickerController:self.imagePickerVc didFinishPickingAndEditingVideo:nil outputPath:nil error:_errorMsg]; + } + if (self.imagePickerVc.didFinishPickingAndEditingVideoHandle) { + self.imagePickerVc.didFinishPickingAndEditingVideoHandle(nil, nil, _errorMsg); + } + } +} + +#pragma mark - private method + +- (CMTime)getCropStartTime { + NSTimeInterval second = [self getCropVideoStartSecond]; + if (second > self.model.asset.duration) { + second = roundf(self.model.asset.duration); + } + return CMTimeMakeWithSeconds(second, _playerLayer.player.currentTime.timescale); +} + +- (CMTimeRange)getCropVideoTimeRange { + NSTimeInterval startSecond = [self getCropVideoStartSecond]; + CMTime start = CMTimeMakeWithSeconds(startSecond, _playerLayer.player.currentTime.timescale); + NSTimeInterval second = [self getCropVideoDuration]; + CMTime duration = CMTimeMakeWithSeconds(second, _playerLayer.player.currentTime.timescale); + return CMTimeRangeMake(start, duration); +} + +- (NSTimeInterval)getCropVideoDuration { + CGFloat rectW = self.videoEditView.cropRect.size.width; + CGFloat contentW = self.videoEditView.allImgWidth; + CGFloat second = rectW / contentW * roundf(self.model.asset.duration); + return roundf(second); +} + +- (NSTimeInterval)getCropVideoStartSecond { + CGFloat offsetX = self.collectionView.contentOffset.x; + CGFloat contentW = self.videoEditView.allImgWidth; + CGFloat cropRectX = self.videoEditView.cropRect.origin.x - VideoEditLeftMargin - PanImageWidth; + NSTimeInterval second = (offsetX + cropRectX) / contentW * roundf(self.model.asset.duration); + if (second < 0) second = 0; + return roundf(second); +} + +- (CMTime)getTimeOfSeek { + NSTimeInterval second = [self getCropVideoStartSecond]; + if (second > self.model.asset.duration) { + second = roundf(self.model.asset.duration); + } + return CMTimeMakeWithSeconds(second, _playerLayer.player.currentTime.timescale); +} + +- (void)starTimer { + [self stopTimer]; + NSTimeInterval timeInterval = [self getCropVideoDuration]; + self.timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(playCropVideo) userInfo:nil repeats:YES]; + [self.timer fire]; +} + +- (void)stopTimer { + if (self.timer) { + [self.videoEditView resetIndicatorLine]; + [_player pause]; + [self.timer invalidate]; + self.timer = nil; + } +} + +- (void)playCropVideo { + [_player seekToTime:[self getCropStartTime] toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; + [_player play]; + [self.videoEditView indicatorLineAnimateWithDuration:[self getCropVideoDuration] cropRect:self.videoEditView.cropRect]; +} + +#pragma mark - Notification Method + +- (void)pausePlayer { + [_player pause]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; +} + +#pragma mark - lazy +- (UIView *)iCloudErrorView{ + if (!_iCloudErrorView) { + _iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_statusBarHeight] + 44 + 10, self.view.tz_width, 28)]; + UIImageView *icloud = [[UIImageView alloc] init]; + icloud.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"]; + icloud.frame = CGRectMake(20, 0, 28, 28); + [_iCloudErrorView addSubview:icloud]; + UILabel *label = [[UILabel alloc] init]; + label.frame = CGRectMake(53, 0, self.view.tz_width - 63, 28); + label.font = [UIFont systemFontOfSize:10]; + label.textColor = [UIColor whiteColor]; + label.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"]; + [_iCloudErrorView addSubview:label]; + [self.view addSubview:_iCloudErrorView]; + _iCloudErrorView.hidden = YES; + } + return _iCloudErrorView; +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + return UIInterfaceOrientationMaskPortrait; +} + +- (void)dealloc { + NSLog(@"%s",__func__); + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma clang diagnostic pop + +@end + + +@implementation TZVideoEditView { + UILabel *_dragingLabel; + CGFloat _itemWidth; + CGFloat _beginOffsetX; + CGFloat _endOffsetX; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + } + return self; +} + +- (void)initSubViews { + _indicatorLine = UIView.new; + _indicatorLine.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7]; + [self addSubview:_indicatorLine]; + + _beginImgView = UIImageView.new; + _beginImgView.image = [UIImage imageNamed:@"leftVideoEdit"]; + _beginImgView.userInteractionEnabled = YES; + _beginImgView.tag = 0; + UIPanGestureRecognizer *beginPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)]; + [_beginImgView addGestureRecognizer:beginPanGesture]; + [self addSubview:_beginImgView]; + + _endImgView = UIImageView.new; + _endImgView.image = [UIImage imageNamed:@"rightVideoEdit"]; + _endImgView.userInteractionEnabled = YES; + _endImgView.tag = 1; + UIPanGestureRecognizer *endPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)]; + [_endImgView addGestureRecognizer:endPanGesture]; + [self addSubview:_endImgView]; +} + +- (void)layoutSubviews { + _beginImgView.frame = CGRectMake(VideoEditLeftMargin, 0, PanImageWidth, self.tz_height); + _indicatorLine.frame = CGRectMake(_beginImgView.tz_right - 2, 2, 2, self.tz_height - 4); + _endImgView.frame = CGRectMake(self.tz_width - PanImageWidth - VideoEditLeftMargin, 0, PanImageWidth, self.tz_height); + + self.cropRect = CGRectMake(VideoEditLeftMargin + PanImageWidth, 0, self.tz_width - VideoEditLeftMargin * 2 - PanImageWidth * 2, self.tz_height); +} + +- (void)setAllImgWidth:(CGFloat)allImgWidth { + _allImgWidth = allImgWidth; + if ((NSInteger)roundf(self.videoDuration) <= 0) { + self.minCropRectWidth = allImgWidth; + return; + } + + CGFloat scale = MinCropVideoDuration / self.videoDuration; + self.minCropRectWidth = scale * allImgWidth; +} + +- (void)setCropRect:(CGRect)cropRect { + _cropRect = cropRect; + self.beginImgView.tz_left = cropRect.origin.x - PanImageWidth; + self.indicatorLine.tz_left = cropRect.origin.x - self.indicatorLine.tz_width; + self.endImgView.tz_left = CGRectGetMaxX(cropRect); + + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextClearRect(context, rect); + + CGPoint topPoints[] = { + CGPointMake(self.cropRect.origin.x, 0), + CGPointMake(CGRectGetMaxX(self.cropRect), 0) + }; + CGPoint bottomPoints[] = { + CGPointMake(self.cropRect.origin.x, self.tz_height), + CGPointMake(CGRectGetMaxX(self.cropRect), self.tz_height) + }; + + CGContextAddLines(context, topPoints, 2); + CGContextAddLines(context, bottomPoints, 2); + CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); + CGContextSetLineWidth(context, 4.0); + CGContextDrawPath(context, kCGPathStroke); +} + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + CGRect beginImgViewFrame = self.beginImgView.frame; + beginImgViewFrame.origin.x -= PanImageWidth; + beginImgViewFrame.size.width += PanImageWidth * 2; + if (CGRectContainsPoint(beginImgViewFrame, point)) return self.beginImgView; + + CGRect endImgViewFrame = self.endImgView.frame; + endImgViewFrame.origin.x -= PanImageWidth; + endImgViewFrame.size.width += PanImageWidth * 2; + if (CGRectContainsPoint(endImgViewFrame, point)) return self.endImgView; + + return nil; +} + +#pragma mark - private + +- (void)indicatorLineAnimateWithDuration:(NSTimeInterval)duration cropRect:(CGRect)cropRect { + [self resetIndicatorLine]; + [UIView animateWithDuration:duration delay:.0 options:UIViewAnimationOptionCurveLinear animations:^{ + self.indicatorLine.tz_left = CGRectGetMaxX(cropRect); + } completion:nil]; +} + +- (void)resetIndicatorLine { + [self.indicatorLine.layer removeAllAnimations]; + self.indicatorLine.tz_left = CGRectGetMinX(self.cropRect) - self.indicatorLine.tz_width; +} + +- (void)panGestureAction:(UIGestureRecognizer *)gesture { + CGPoint point = [gesture locationInView:self]; + CGRect rect = self.cropRect; + CGFloat minCropRectLeft = VideoEditLeftMargin + PanImageWidth; + + switch (gesture.view.tag) { + case 0: { // 左边拖拽 + CGFloat maxX = self.endImgView.tz_left - self.minCropRectWidth; + point.x = MAX(minCropRectLeft, MIN(point.x, maxX)); + point.y = 0; + + rect.size.width = CGRectGetMaxX(rect) - point.x; + rect.origin.x = point.x; + } break; + case 1: { // 右边拖拽 + minCropRectLeft = CGRectGetMaxX(self.beginImgView.frame) + self.minCropRectWidth; + CGFloat maxX = self.tz_width - VideoEditLeftMargin - PanImageWidth; + + point.x = MAX(minCropRectLeft, MIN(point.x, maxX)); + point.y = 0; + + rect.size.width = (point.x - rect.origin.x); + } break; + default:break; + } + + self.cropRect = rect; + + switch (gesture.state) { + case UIGestureRecognizerStateBegan: + case UIGestureRecognizerStateChanged: { + if (self.delegate && [self.delegate respondsToSelector:@selector(editViewCropRectBeginChange)]) { + [self.delegate editViewCropRectBeginChange]; + } + } break; + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: { + if (self.delegate && [self.delegate respondsToSelector:@selector(editViewCropRectEndChange)]) { + [self.delegate editViewCropRectEndChange]; + } + } break; + default: break; + } +} + +@end + + + +@implementation TZVideoPictureCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + } + return self; +} + +- (void)initSubViews { + _imgView = [[UIImageView alloc] initWithFrame:self.bounds]; + _imgView.contentMode = UIViewContentModeScaleAspectFill; + _imgView.clipsToBounds = YES; + [self.contentView addSubview:_imgView]; +} + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.h b/TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.h new file mode 100644 index 0000000..5965907 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.h @@ -0,0 +1,17 @@ +// +// TZVideoEditedPreviewController.h +// TZImagePickerController +// +// Created by 肖兰月 on 2021/5/29. +// Copyright © 2021 谭真. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TZVideoEditedPreviewController : UIViewController +@property (nonatomic, copy) NSURL *videoURL; +@end + +NS_ASSUME_NONNULL_END diff --git a/TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.m b/TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.m new file mode 100644 index 0000000..b9755c1 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZVideoEditedPreviewController.m @@ -0,0 +1,129 @@ +// +// TZVideoEditedPreviewController.m +// TZImagePickerController +// +// Created by 肖兰月 on 2021/5/29. +// Copyright © 2021 谭真. All rights reserved. +// + +#import "TZVideoEditedPreviewController.h" +#import +#import "TZImageManager.h" +#import "TZImagePickerController.h" +#import "UIView+TZLayout.h" + +@interface TZVideoEditedPreviewController () { + AVPlayer *_player; + AVPlayerLayer *_playerLayer; + UIButton *_playButton; + UIImage *_cover; + + UIView *_toolBar; + UIButton *_doneButton; + UIProgressView *_progress; + + UIStatusBarStyle _originStatusBarStyle; +} + +@end + +@implementation TZVideoEditedPreviewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + [self configMoviePlayer]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:UIApplicationWillResignActiveNotification object:nil]; +} + +- (void)configMoviePlayer { + _player = [AVPlayer playerWithURL:self.videoURL]; + _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player]; + [self.view.layer addSublayer:_playerLayer]; + + [self configPlayButton]; + [self configBottomToolBar]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:AVPlayerItemDidPlayToEndTimeNotification object:self->_player.currentItem]; +} + +- (void)configPlayButton { + _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted]; + [_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_playButton]; +} + +- (void)configBottomToolBar { + _toolBar = [[UIView alloc] initWithFrame:CGRectZero]; + CGFloat rgb = 34 / 255.0; + _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7]; + + _doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _doneButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc) { + [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal]; + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal]; + } else { + [_doneButton setTitle:[NSBundle tz_localizedStringForKey:@"Done"] forState:UIControlStateNormal]; + [_doneButton setTitleColor:[UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0] forState:UIControlStateNormal]; + } + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled]; + [_toolBar addSubview:_doneButton]; + [self.view addSubview:_toolBar]; +} + + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height; + CGFloat statusBarHeight = isFullScreen ? [TZCommonTools tz_statusBarHeight] : 0; + CGFloat statusBarAndNaviBarHeight = statusBarHeight + self.navigationController.navigationBar.tz_height; + + CGFloat toolBarHeight = 44 + [TZCommonTools tz_safeAreaInsets].bottom; + _toolBar.frame = CGRectMake(0, self.view.tz_height - toolBarHeight, self.view.tz_width, toolBarHeight); + [_doneButton sizeToFit]; + _doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, MAX(44, _doneButton.tz_width), 44); + _playButton.frame = CGRectMake(0, statusBarAndNaviBarHeight, self.view.tz_width, self.view.tz_height - statusBarAndNaviBarHeight - toolBarHeight); + _playerLayer.frame = self.view.bounds; +} + +#pragma mark - Click Event + +- (void)playButtonClick { + CMTime currentTime = _player.currentItem.currentTime; + CMTime durationTime = _player.currentItem.duration; + if (_player.rate == 0.0f) { + if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)]; + [_player play]; + _toolBar.hidden = YES; + [_playButton setImage:nil forState:UIControlStateNormal]; + } else { + [self pausePlayerAndShowNaviBar]; + } +} + +- (void)doneButtonClick { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - Notification Method + +- (void)pausePlayerAndShowNaviBar { + [_player pause]; + _toolBar.hidden = NO; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma clang diagnostic pop + +@end diff --git a/TZImagePickerController/TZImagePickerController/TZVideoPlayerController.h b/TZImagePickerController/TZImagePickerController/TZVideoPlayerController.h new file mode 100644 index 0000000..50d68bb --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZVideoPlayerController.h @@ -0,0 +1,17 @@ +// +// TZVideoPlayerController.h +// TZImagePickerController +// +// Created by 谭真 on 16/1/5. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import + +@class TZAssetModel; +@interface TZVideoPlayerController : UIViewController + +@property (nonatomic, strong) TZAssetModel *model; + +@end + diff --git a/TZImagePickerController/TZImagePickerController/TZVideoPlayerController.m b/TZImagePickerController/TZImagePickerController/TZVideoPlayerController.m new file mode 100644 index 0000000..7175b4d --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/TZVideoPlayerController.m @@ -0,0 +1,325 @@ +// +// TZVideoPlayerController.m +// TZImagePickerController +// +// Created by 谭真 on 16/1/5. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "TZVideoPlayerController.h" +#import +#import "UIView+TZLayout.h" +#import "TZImageManager.h" +#import "TZAssetModel.h" +#import "TZImagePickerController.h" +#import "TZPhotoPreviewController.h" +#import "TZVideoCropController.h" + +@interface TZVideoPlayerController () { + AVPlayer *_player; + AVPlayerLayer *_playerLayer; + UIButton *_playButton; + UIImage *_playButtonNormalImage; + UIImage *_cover; + NSString *_outputPath; + NSString *_errorMsg; + + UIView *_toolBar; + UIButton *_doneButton; + UIButton *_editButton; + UIProgressView *_progress; + + UIStatusBarStyle _originStatusBarStyle; +} +@property (assign, nonatomic) BOOL needShowStatusBar; + +// iCloud无法同步提示UI +@property (nonatomic, strong) UIView *iCloudErrorView; + +@end + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +@implementation TZVideoPlayerController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.needShowStatusBar = ![UIApplication sharedApplication].statusBarHidden; + self.view.backgroundColor = [UIColor blackColor]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc) { + self.navigationItem.title = tzImagePickerVc.previewBtnTitleStr; + } + [self configMoviePlayer]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:UIApplicationWillResignActiveNotification object:nil]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + _originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle; + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + if (self.needShowStatusBar) { + [UIApplication sharedApplication].statusBarHidden = NO; + } + [UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle; +} + +- (void)configMoviePlayer { + [[TZImageManager manager] getPhotoWithAsset:_model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + BOOL iCloudSyncFailed = !photo && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]]; + self.iCloudErrorView.hidden = !iCloudSyncFailed; + if (!isDegraded && photo) { + self->_cover = photo; + self->_doneButton.enabled = YES; + self->_editButton.enabled = YES; + } + }]; + [[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + self->_player = [AVPlayer playerWithPlayerItem:playerItem]; + self->_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self->_player]; + self->_playerLayer.frame = self.view.bounds; + [self.view.layer addSublayer:self->_playerLayer]; + [self addProgressObserver]; + [self configPlayButton]; + [self configBottomToolBar]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:AVPlayerItemDidPlayToEndTimeNotification object:self->_player.currentItem]; + }); + }]; +} + +/// Show progress,do it next time / 给播放器添加进度更新,下次加上 +- (void)addProgressObserver{ + AVPlayerItem *playerItem = _player.currentItem; + UIProgressView *progress = _progress; + [_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { + float current = CMTimeGetSeconds(time); + float total = CMTimeGetSeconds([playerItem duration]); + if (current) { + [progress setProgress:(current/total) animated:YES]; + } + }]; +} + +- (void)configPlayButton { + _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal]; + [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted]; + [_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_playButton]; +} + +- (void)configBottomToolBar { + _toolBar = [[UIView alloc] initWithFrame:CGRectZero]; + CGFloat rgb = 34 / 255.0; + _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7]; + + _doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _doneButton.titleLabel.font = [UIFont systemFontOfSize:16]; + if (!_cover) { + _doneButton.enabled = NO; + } + [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + if (tzImagePickerVc) { + [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal]; + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal]; + } else { + [_doneButton setTitle:[NSBundle tz_localizedStringForKey:@"Done"] forState:UIControlStateNormal]; + [_doneButton setTitleColor:[UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0] forState:UIControlStateNormal]; + } + [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled]; + [_toolBar addSubview:_doneButton]; + [self.view addSubview:_toolBar]; + + if (tzImagePickerVc && tzImagePickerVc.allowEditVideo && roundf(self.model.asset.duration) > 1) { + _editButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _editButton.titleLabel.font = [UIFont systemFontOfSize:16]; + if (!_cover) { + _editButton.enabled = NO; + } + [_editButton addTarget:self action:@selector(editButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [_editButton setTitle:tzImagePickerVc.editBtnTitleStr forState:UIControlStateNormal]; + [_editButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal]; + [_editButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled]; + [_toolBar addSubview:_editButton]; + } + + if (tzImagePickerVc.videoPreviewPageUIConfigBlock) { + tzImagePickerVc.videoPreviewPageUIConfigBlock(_playButton, _toolBar, _editButton, _doneButton); + } +} + +- (UIStatusBarStyle)preferredStatusBarStyle { + TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController; + if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) { + return tzImagePicker.statusBarStyle; + } + return [super preferredStatusBarStyle]; +} + +#pragma mark - Layout + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController; + + BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height; + CGFloat statusBarHeight = isFullScreen ? [TZCommonTools tz_statusBarHeight] : 0; + CGFloat statusBarAndNaviBarHeight = statusBarHeight + self.navigationController.navigationBar.tz_height; + _playerLayer.frame = self.view.bounds; + CGFloat toolBarHeight = 44 + [TZCommonTools tz_safeAreaInsets].bottom; + _toolBar.frame = CGRectMake(0, self.view.tz_height - toolBarHeight, self.view.tz_width, toolBarHeight); + [_doneButton sizeToFit]; + _doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, MAX(44, _doneButton.tz_width), 44); + _playButton.frame = CGRectMake(0, statusBarAndNaviBarHeight, self.view.tz_width, self.view.tz_height - statusBarAndNaviBarHeight - toolBarHeight); + if (tzImagePickerVc.allowEditVideo) { + _editButton.frame = CGRectMake(12, 0, 44, 44); + [_editButton sizeToFit]; + _editButton.tz_height = 44; + } + if (tzImagePickerVc.videoPreviewPageDidLayoutSubviewsBlock) { + tzImagePickerVc.videoPreviewPageDidLayoutSubviewsBlock(_playButton, _toolBar, _editButton, _doneButton); + } +} + +#pragma mark - Click Event + +- (void)playButtonClick { + CMTime currentTime = _player.currentItem.currentTime; + CMTime durationTime = _player.currentItem.duration; + if (_player.rate == 0.0f) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_VIDEO_PLAY_NOTIFICATION" object:_player]; + if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)]; + [_player play]; + [self.navigationController setNavigationBarHidden:YES]; + _toolBar.hidden = YES; + _playButtonNormalImage = [_playButton imageForState:UIControlStateNormal]; + [_playButton setImage:nil forState:UIControlStateNormal]; + [UIApplication sharedApplication].statusBarHidden = YES; + } else { + [self pausePlayerAndShowNaviBar]; + } +} + +- (void)editButtonClick { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + TZVideoCropController *videoCropVc = [[TZVideoCropController alloc] init]; + videoCropVc.model = self.model; + videoCropVc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + videoCropVc.modalPresentationStyle = UIModalPresentationFullScreen; + videoCropVc.modalPresentationCapturesStatusBarAppearance = YES; + videoCropVc.imagePickerVc = imagePickerVc; + [self presentViewController:videoCropVc animated:YES completion:nil]; +} + +- (void)doneButtonClick { + if ([[TZImageManager manager] isAssetCannotBeSelected:_model.asset]) { + return; + } + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + if (imagePickerVc.allowEditVideo) { + [imagePickerVc showProgressHUD]; + [[TZImageManager manager] getVideoOutputPathWithAsset:_model.asset presetName:imagePickerVc.presetName success:^(NSString *outputPath) { + [imagePickerVc hideProgressHUD]; + self->_outputPath = outputPath; + [self dismissAndCallDelegateMethod]; + } failure:^(NSString *errorMessage, NSError *error) { + [imagePickerVc hideProgressHUD]; + self->_errorMsg = errorMessage; + [self dismissAndCallDelegateMethod]; + }]; + } else { + [self dismissAndCallDelegateMethod]; + } +} + +- (void)dismissAndCallDelegateMethod { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + if (!imagePickerVc) { + [self dismissViewControllerAnimated:YES completion:nil]; + return; + } + if (imagePickerVc.autoDismiss) { + [imagePickerVc dismissViewControllerAnimated:YES completion:^{ + [self callDelegateMethod]; + }]; + } else { + [self callDelegateMethod]; + } +} + +- (void)callDelegateMethod { + TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController; + if (imagePickerVc.allowEditVideo) { + if (_outputPath) { + if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingAndEditingVideo:outputPath:error:)]) { + [imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingAndEditingVideo:self->_cover outputPath:self->_outputPath error:nil]; + } + if (imagePickerVc.didFinishPickingAndEditingVideoHandle) { + imagePickerVc.didFinishPickingAndEditingVideoHandle(self->_cover, self->_outputPath, nil); + } + } else { + if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingAndEditingVideo:outputPath:error:)]) { + [imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingAndEditingVideo:nil outputPath:nil error:self->_errorMsg]; + } + if (imagePickerVc.didFinishPickingAndEditingVideoHandle) { + imagePickerVc.didFinishPickingAndEditingVideoHandle(nil, nil, self->_errorMsg); + } + } + } else { + if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingVideo:sourceAssets:)]) { + [imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingVideo:_cover sourceAssets:_model.asset]; + } + if (imagePickerVc.didFinishPickingVideoHandle) { + imagePickerVc.didFinishPickingVideoHandle(_cover,_model.asset); + } + } +} + +#pragma mark - Notification Method + +- (void)pausePlayerAndShowNaviBar { + [_player pause]; + _toolBar.hidden = NO; + [self.navigationController setNavigationBarHidden:NO]; + UIImage *normalImage = _playButtonNormalImage ?: [UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"]; + [_playButton setImage:normalImage forState:UIControlStateNormal]; + + if (self.needShowStatusBar) { + [UIApplication sharedApplication].statusBarHidden = NO; + } +} + +#pragma mark - lazy +- (UIView *)iCloudErrorView{ + if (!_iCloudErrorView) { + _iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_statusBarHeight] + 44 + 10, self.view.tz_width, 28)]; + UIImageView *icloud = [[UIImageView alloc] init]; + icloud.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"]; + icloud.frame = CGRectMake(20, 0, 28, 28); + [_iCloudErrorView addSubview:icloud]; + UILabel *label = [[UILabel alloc] init]; + label.frame = CGRectMake(53, 0, self.view.tz_width - 63, 28); + label.font = [UIFont systemFontOfSize:10]; + label.textColor = [UIColor whiteColor]; + label.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"]; + [_iCloudErrorView addSubview:label]; + [self.view addSubview:_iCloudErrorView]; + _iCloudErrorView.hidden = YES; + } + return _iCloudErrorView; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma clang diagnostic pop + +@end diff --git a/TZImagePickerController/TZImagePickerController/UIView+TZLayout.h b/TZImagePickerController/TZImagePickerController/UIView+TZLayout.h new file mode 100644 index 0000000..56ade20 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/UIView+TZLayout.h @@ -0,0 +1,31 @@ +// +// UIView+TZLayout.h +// TZImagePickerController +// +// Created by 谭真 on 15/2/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +typedef enum : NSUInteger { + TZOscillatoryAnimationToBigger, + TZOscillatoryAnimationToSmaller, +} TZOscillatoryAnimationType; + +@interface UIView (TZLayout) + +@property (nonatomic) CGFloat tz_left; ///< Shortcut for frame.origin.x. +@property (nonatomic) CGFloat tz_top; ///< Shortcut for frame.origin.y +@property (nonatomic) CGFloat tz_right; ///< Shortcut for frame.origin.x + frame.size.width +@property (nonatomic) CGFloat tz_bottom; ///< Shortcut for frame.origin.y + frame.size.height +@property (nonatomic) CGFloat tz_width; ///< Shortcut for frame.size.width. +@property (nonatomic) CGFloat tz_height; ///< Shortcut for frame.size.height. +@property (nonatomic) CGFloat tz_centerX; ///< Shortcut for center.x +@property (nonatomic) CGFloat tz_centerY; ///< Shortcut for center.y +@property (nonatomic) CGPoint tz_origin; ///< Shortcut for frame.origin. +@property (nonatomic) CGSize tz_size; ///< Shortcut for frame.size. + ++ (void)showOscillatoryAnimationWithLayer:(CALayer *)layer type:(TZOscillatoryAnimationType)type; + +@end diff --git a/TZImagePickerController/TZImagePickerController/UIView+TZLayout.m b/TZImagePickerController/TZImagePickerController/UIView+TZLayout.m new file mode 100644 index 0000000..3e36263 --- /dev/null +++ b/TZImagePickerController/TZImagePickerController/UIView+TZLayout.m @@ -0,0 +1,126 @@ +// +// UIView+TZLayout.m +// TZImagePickerController +// +// Created by 谭真 on 15/2/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "UIView+TZLayout.h" + +@implementation UIView (TZLayout) + +- (CGFloat)tz_left { + return self.frame.origin.x; +} + +- (void)setTz_left:(CGFloat)x { + CGRect frame = self.frame; + frame.origin.x = x; + self.frame = frame; +} + +- (CGFloat)tz_top { + return self.frame.origin.y; +} + +- (void)setTz_top:(CGFloat)y { + CGRect frame = self.frame; + frame.origin.y = y; + self.frame = frame; +} + +- (CGFloat)tz_right { + return self.frame.origin.x + self.frame.size.width; +} + +- (void)setTz_right:(CGFloat)right { + CGRect frame = self.frame; + frame.origin.x = right - frame.size.width; + self.frame = frame; +} + +- (CGFloat)tz_bottom { + return self.frame.origin.y + self.frame.size.height; +} + +- (void)setTz_bottom:(CGFloat)bottom { + CGRect frame = self.frame; + frame.origin.y = bottom - frame.size.height; + self.frame = frame; +} + +- (CGFloat)tz_width { + return self.frame.size.width; +} + +- (void)setTz_width:(CGFloat)width { + CGRect frame = self.frame; + frame.size.width = width; + self.frame = frame; +} + +- (CGFloat)tz_height { + return self.frame.size.height; +} + +- (void)setTz_height:(CGFloat)height { + CGRect frame = self.frame; + frame.size.height = height; + self.frame = frame; +} + +- (CGFloat)tz_centerX { + return self.center.x; +} + +- (void)setTz_centerX:(CGFloat)centerX { + self.center = CGPointMake(centerX, self.center.y); +} + +- (CGFloat)tz_centerY { + return self.center.y; +} + +- (void)setTz_centerY:(CGFloat)centerY { + self.center = CGPointMake(self.center.x, centerY); +} + +- (CGPoint)tz_origin { + return self.frame.origin; +} + +- (void)setTz_origin:(CGPoint)origin { + CGRect frame = self.frame; + frame.origin = origin; + self.frame = frame; +} + +- (CGSize)tz_size { + return self.frame.size; +} + +- (void)setTz_size:(CGSize)size { + CGRect frame = self.frame; + frame.size = size; + self.frame = frame; +} + ++ (void)showOscillatoryAnimationWithLayer:(CALayer *)layer type:(TZOscillatoryAnimationType)type{ + NSNumber *animationScale1 = type == TZOscillatoryAnimationToBigger ? @(1.15) : @(0.5); + NSNumber *animationScale2 = type == TZOscillatoryAnimationToBigger ? @(0.92) : @(1.15); + + [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut animations:^{ + [layer setValue:animationScale1 forKeyPath:@"transform.scale"]; + } completion:^(BOOL finished) { + [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut animations:^{ + [layer setValue:animationScale2 forKeyPath:@"transform.scale"]; + } completion:^(BOOL finished) { + [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut animations:^{ + [layer setValue:@(1.0) forKeyPath:@"transform.scale"]; + } completion:nil]; + }]; + }]; +} + +@end diff --git a/TZImagePickerController/TZImageUploadOperation.h b/TZImagePickerController/TZImageUploadOperation.h new file mode 100644 index 0000000..bd535b4 --- /dev/null +++ b/TZImagePickerController/TZImageUploadOperation.h @@ -0,0 +1,17 @@ +// +// TZImageUploadOperation.h +// TZImagePickerController +// +// Created by 谭真 on 2019/1/14. +// Copyright © 2019 谭真. All rights reserved. +// + +#import "TZImageRequestOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TZImageUploadOperation : TZImageRequestOperation + +@end + +NS_ASSUME_NONNULL_END diff --git a/TZImagePickerController/TZImageUploadOperation.m b/TZImagePickerController/TZImageUploadOperation.m new file mode 100644 index 0000000..b0f7827 --- /dev/null +++ b/TZImagePickerController/TZImageUploadOperation.m @@ -0,0 +1,69 @@ +// +// TZImageUploadOperation.m +// TZImagePickerController +// +// Created by 谭真 on 2019/1/14. +// Copyright © 2019 谭真. All rights reserved. +// + +#import "TZImageUploadOperation.h" +#import "TZImageManager.h" + +@implementation TZImageUploadOperation + +- (void)start { + NSLog(@"TZImageUploadOperation start"); + self.executing = YES; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ +#pragma mark - 获取&上传大图 + /* + [[TZImageManager manager] getPhotoWithAsset:self.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (!isDegraded) { + if (self.completedBlock) { + self.completedBlock(photo, info, isDegraded); + } + // 在这里上传图片(代码略),图片上传完毕后调用[self done] + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self done]; + }); + } + }); + } progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.progressBlock) { + self.progressBlock(progress, error, stop, info); + } + }); + } networkAccessAllowed:YES]; + */ + +#pragma mark - 获取&上传原图 + [[TZImageManager manager] getOriginalPhotoWithAsset:self.asset progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.progressBlock) { + self.progressBlock(progress, error, stop, info); + } + }); + } newCompletion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (!isDegraded) { + if (self.completedBlock) { + self.completedBlock(photo, info, isDegraded); + } + // 在这里上传图片(代码略),图片上传完毕后调用[self done] + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self done]; + }); + } + }); + }]; + }); +} + +- (void)done { + [super done]; + // NSLog(@"TZImageUploadOperation done"); +} + +@end diff --git a/TZImagePickerController/TZTestCell.h b/TZImagePickerController/TZTestCell.h new file mode 100644 index 0000000..294bb1a --- /dev/null +++ b/TZImagePickerController/TZTestCell.h @@ -0,0 +1,23 @@ +// +// TZTestCell.h +// TZImagePickerController +// +// Created by 谭真 on 16/1/3. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import + +@interface TZTestCell : UICollectionViewCell + +@property (nonatomic, strong) UIImageView *imageView; +@property (nonatomic, strong) UIImageView *videoImageView; +@property (nonatomic, strong) UIButton *deleteBtn; +@property (nonatomic, strong) UILabel *gifLable; +@property (nonatomic, assign) NSInteger row; +@property (nonatomic, strong) id asset; + +- (UIView *)snapshotView; + +@end + diff --git a/TZImagePickerController/TZTestCell.m b/TZImagePickerController/TZTestCell.m new file mode 100644 index 0000000..f5ed1b9 --- /dev/null +++ b/TZImagePickerController/TZTestCell.m @@ -0,0 +1,92 @@ +// +// TZTestCell.m +// TZImagePickerController +// +// Created by 谭真 on 16/1/3. +// Copyright © 2016年 谭真. All rights reserved. +// + +#import "TZTestCell.h" +#import "UIView+TZLayout.h" +#import +#import "TZImagePickerController/TZImagePickerController.h" + +@implementation TZTestCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor whiteColor]; + _imageView = [[UIImageView alloc] init]; + _imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + [self addSubview:_imageView]; + self.clipsToBounds = YES; + + _videoImageView = [[UIImageView alloc] init]; + _videoImageView.image = [UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"]; + _videoImageView.contentMode = UIViewContentModeScaleAspectFill; + _videoImageView.hidden = YES; + [self addSubview:_videoImageView]; + + _deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_deleteBtn setImage:[UIImage imageNamed:@"photo_delete"] forState:UIControlStateNormal]; + _deleteBtn.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 0, -10); + _deleteBtn.alpha = 0.6; + [self addSubview:_deleteBtn]; + + _gifLable = [[UILabel alloc] init]; + _gifLable.text = @"GIF"; + _gifLable.textColor = [UIColor whiteColor]; + _gifLable.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8]; + _gifLable.textAlignment = NSTextAlignmentCenter; + _gifLable.font = [UIFont systemFontOfSize:10]; + [self addSubview:_gifLable]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _imageView.frame = self.bounds; + _gifLable.frame = CGRectMake(self.tz_width - 25, self.tz_height - 14, 25, 14); + _deleteBtn.frame = CGRectMake(self.tz_width - 36, 0, 36, 36); + CGFloat width = self.tz_width / 3.0; + _videoImageView.frame = CGRectMake(width, width, width, width); +} + +- (void)setAsset:(PHAsset *)asset { + _asset = asset; + _videoImageView.hidden = asset.mediaType != PHAssetMediaTypeVideo; + _gifLable.hidden = ![[asset valueForKey:@"filename"] containsString:@"GIF"]; +} + +- (void)setRow:(NSInteger)row { + _row = row; + _deleteBtn.tag = row; +} + +- (UIView *)snapshotView { + UIView *snapshotView = [[UIView alloc]init]; + + UIView *cellSnapshotView = nil; + + if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) { + cellSnapshotView = [self snapshotViewAfterScreenUpdates:NO]; + } else { + CGSize size = CGSizeMake(self.bounds.size.width + 20, self.bounds.size.height + 20); + UIGraphicsBeginImageContextWithOptions(size, self.opaque, 0); + [self.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage * cellSnapshotImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + cellSnapshotView = [[UIImageView alloc]initWithImage:cellSnapshotImage]; + } + + snapshotView.frame = CGRectMake(0, 0, cellSnapshotView.frame.size.width, cellSnapshotView.frame.size.height); + cellSnapshotView.frame = CGRectMake(0, 0, cellSnapshotView.frame.size.width, cellSnapshotView.frame.size.height); + + [snapshotView addSubview:cellSnapshotView]; + return snapshotView; +} + +@end diff --git a/TZImagePickerController/ViewController.h b/TZImagePickerController/ViewController.h new file mode 100644 index 0000000..80445ec --- /dev/null +++ b/TZImagePickerController/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/TZImagePickerController/ViewController.m b/TZImagePickerController/ViewController.m new file mode 100644 index 0000000..0badd58 --- /dev/null +++ b/TZImagePickerController/ViewController.m @@ -0,0 +1,889 @@ +// +// ViewController.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import "ViewController.h" +#import "TZImagePickerController.h" +#import "UIView+TZLayout.h" +#import "TZTestCell.h" +#import +#import "LxGridViewFlowLayout.h" +#import "TZImageManager.h" +#import "TZVideoPlayerController.h" +#import "TZPhotoPreviewController.h" +#import "TZGifPhotoPreviewController.h" +#import "TZAssetCell.h" +#import +#import "FLAnimatedImage.h" +#import "TZImageUploadOperation.h" +#import "TZVideoEditedPreviewController.h" + +@interface ViewController () { + NSMutableArray *_selectedPhotos; + NSMutableArray *_selectedAssets; + BOOL _isSelectOriginalPhoto; + BOOL _isAllowEditVideo; + + CGFloat _itemWH; + CGFloat _margin; +} +@property (nonatomic, strong) UIImagePickerController *imagePickerVc; +@property (nonatomic, strong) UICollectionView *collectionView; +@property (strong, nonatomic) LxGridViewFlowLayout *layout; +@property (strong, nonatomic) CLLocation *location; + +@property (nonatomic, strong) NSOperationQueue *operationQueue; + +@property (weak, nonatomic) IBOutlet UIScrollView *scrollView; +// 设置开关 +@property (weak, nonatomic) IBOutlet UISwitch *showTakePhotoBtnSwitch; ///< 允许拍照 +@property (weak, nonatomic) IBOutlet UISwitch *showTakeVideoBtnSwitch; ///< 允许拍视频 +@property (weak, nonatomic) IBOutlet UISwitch *sortAscendingSwitch; ///< 照片排列按修改时间升序 +@property (weak, nonatomic) IBOutlet UISwitch *allowPickingVideoSwitch; ///< 允许选择视频 +@property (weak, nonatomic) IBOutlet UISwitch *allowPickingImageSwitch; ///< 允许选择图片 +@property (weak, nonatomic) IBOutlet UISwitch *allowPickingGifSwitch; +@property (weak, nonatomic) IBOutlet UISwitch *allowPickingOriginalPhotoSwitch; ///< 允许选择原图 +@property (weak, nonatomic) IBOutlet UISwitch *showSheetSwitch; ///< 显示一个sheet,把拍照/拍视频按钮放在外面 +@property (weak, nonatomic) IBOutlet UITextField *maxCountTF; ///< 照片最大可选张数,设置为1即为单选模式 +@property (weak, nonatomic) IBOutlet UITextField *columnNumberTF; +@property (weak, nonatomic) IBOutlet UISwitch *allowCropSwitch; +@property (weak, nonatomic) IBOutlet UISwitch *needCircleCropSwitch; +@property (weak, nonatomic) IBOutlet UISwitch *allowPickingMuitlpleVideoSwitch; +@property (weak, nonatomic) IBOutlet UISwitch *showSelectedIndexSwitch; +@end + +@implementation ViewController + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (UIImagePickerController *)imagePickerVc { + if (_imagePickerVc == nil) { + _imagePickerVc = [[UIImagePickerController alloc] init]; + _imagePickerVc.delegate = self; + // set appearance / 改变相册选择页的导航栏外观 + _imagePickerVc.navigationBar.barTintColor = self.navigationController.navigationBar.barTintColor; + _imagePickerVc.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; + UIBarButtonItem *tzBarItem, *BarItem; + if (@available(iOS 9, *)) { + tzBarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]]; + BarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UIImagePickerController class]]]; + } else { + tzBarItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil]; + BarItem = [UIBarButtonItem appearanceWhenContainedIn:[UIImagePickerController class], nil]; + } + NSDictionary *titleTextAttributes = [tzBarItem titleTextAttributesForState:UIControlStateNormal]; + [BarItem setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal]; + + } + return _imagePickerVc; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + _selectedPhotos = [NSMutableArray array]; + _selectedAssets = [NSMutableArray array]; + [self configCollectionView]; +} + +- (BOOL)prefersStatusBarHidden { + return NO; +} + +- (void)configCollectionView { + // 如不需要长按排序效果,将LxGridViewFlowLayout类改成UICollectionViewFlowLayout即可 + _layout = [[LxGridViewFlowLayout alloc] init]; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout]; + CGFloat rgb = 244 / 255.0; + _collectionView.alwaysBounceVertical = YES; + _collectionView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; + _collectionView.contentInset = UIEdgeInsetsMake(4, 4, 4, 4); + _collectionView.dataSource = self; + _collectionView.delegate = self; + _collectionView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; + [self.view addSubview:_collectionView]; + [_collectionView registerClass:[TZTestCell class] forCellWithReuseIdentifier:@"TZTestCell"]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + NSInteger contentSizeH = 14 * 35 + 20; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + self.scrollView.contentSize = CGSizeMake(0, contentSizeH + 5); + }); + if (self.scrollView.tz_height + 80 > self.view.tz_height) { + self.scrollView.tz_height = self.view.tz_height - 80; + } + + _margin = 4; + _itemWH = (self.view.tz_width - 2 * _margin - 4) / 3 - _margin; + _layout.itemSize = CGSizeMake(_itemWH, _itemWH); + _layout.minimumInteritemSpacing = _margin; + _layout.minimumLineSpacing = _margin; + [self.collectionView setCollectionViewLayout:_layout]; + CGFloat collectionViewY = CGRectGetMaxY(self.scrollView.frame); + self.collectionView.frame = CGRectMake(0, collectionViewY, self.view.tz_width, self.view.tz_height - collectionViewY); +} + +#pragma mark UICollectionView + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + if (_selectedPhotos.count >= self.maxCountTF.text.integerValue) { + return _selectedPhotos.count; + } + if (!self.allowPickingMuitlpleVideoSwitch.isOn) { + if (_isAllowEditVideo) { + return 1; + } else { + for (PHAsset *asset in _selectedAssets) { + if (asset.mediaType == PHAssetMediaTypeVideo) { + return _selectedPhotos.count; + } + } + } + } + return _selectedPhotos.count + 1; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + TZTestCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZTestCell" forIndexPath:indexPath]; + cell.videoImageView.hidden = YES; + if (indexPath.item == _selectedPhotos.count) { + cell.imageView.image = [UIImage imageNamed:@"AlbumAddBtn.png"]; + cell.deleteBtn.hidden = YES; + cell.gifLable.hidden = YES; + } else { + cell.imageView.image = _selectedPhotos[indexPath.item]; + if (!_isAllowEditVideo) { + cell.asset = _selectedAssets[indexPath.item]; + } + cell.deleteBtn.hidden = NO; + } + if (!self.allowPickingGifSwitch.isOn) { + cell.gifLable.hidden = YES; + } + cell.deleteBtn.tag = indexPath.item; + [cell.deleteBtn addTarget:self action:@selector(deleteBtnClik:) forControlEvents:UIControlEventTouchUpInside]; + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.item == _selectedPhotos.count) { + BOOL showSheet = self.showSheetSwitch.isOn; + if (showSheet) { + NSString *takePhotoTitle = @"拍照"; + if (self.showTakeVideoBtnSwitch.isOn && self.showTakePhotoBtnSwitch.isOn) { + takePhotoTitle = @"相机"; + } else if (self.showTakeVideoBtnSwitch.isOn) { + takePhotoTitle = @"拍摄"; + } + UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; + UIAlertAction *takePhotoAction = [UIAlertAction actionWithTitle:takePhotoTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [self takePhoto]; + }]; + [alertVc addAction:takePhotoAction]; + UIAlertAction *imagePickerAction = [UIAlertAction actionWithTitle:@"去相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [self pushTZImagePickerController]; + }]; + [alertVc addAction:imagePickerAction]; + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; + [alertVc addAction:cancelAction]; + UIPopoverPresentationController *popover = alertVc.popoverPresentationController; + UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath]; + if (popover) { + popover.sourceView = cell; + popover.sourceRect = cell.bounds; + popover.permittedArrowDirections = UIPopoverArrowDirectionAny; + } + [self presentViewController:alertVc animated:YES completion:nil]; + } else { + [self pushTZImagePickerController]; + } + } else if (_isAllowEditVideo && [_selectedAssets[indexPath.item] isKindOfClass:[NSURL class]]) { // preview edited video / 预览编辑后的视频 + TZVideoEditedPreviewController *vc = [[TZVideoEditedPreviewController alloc] init]; + vc.videoURL = _selectedAssets[indexPath.item]; + vc.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:vc animated:YES completion:nil]; + } else { // preview photos or video / 预览照片或者视频 + PHAsset *asset = _selectedAssets[indexPath.item]; + BOOL isVideo = NO; + isVideo = asset.mediaType == PHAssetMediaTypeVideo; + if ([[asset valueForKey:@"filename"] containsString:@"GIF"] && self.allowPickingGifSwitch.isOn && !self.allowPickingMuitlpleVideoSwitch.isOn) { + TZGifPhotoPreviewController *vc = [[TZGifPhotoPreviewController alloc] init]; + TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:TZAssetModelMediaTypePhotoGif timeLength:@""]; + vc.model = model; + vc.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:vc animated:YES completion:nil]; + } else if (isVideo && !self.allowPickingMuitlpleVideoSwitch.isOn) { // perview video / 预览视频 + TZVideoPlayerController *vc = [[TZVideoPlayerController alloc] init]; + TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:TZAssetModelMediaTypeVideo timeLength:@""]; + vc.model = model; + vc.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:vc animated:YES completion:nil]; + } else { // preview photos / 预览照片 + TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithSelectedAssets:_selectedAssets selectedPhotos:_selectedPhotos index:indexPath.item]; + imagePickerVc.maxImagesCount = self.maxCountTF.text.integerValue; + imagePickerVc.allowPickingGif = self.allowPickingGifSwitch.isOn; + imagePickerVc.autoSelectCurrentWhenDone = NO; + imagePickerVc.allowPickingOriginalPhoto = self.allowPickingOriginalPhotoSwitch.isOn; + imagePickerVc.allowPickingMultipleVideo = self.allowPickingMuitlpleVideoSwitch.isOn; + imagePickerVc.showSelectedIndex = self.showSelectedIndexSwitch.isOn; + imagePickerVc.isSelectOriginalPhoto = _isSelectOriginalPhoto; + imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; + [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray *photos, NSArray *assets, BOOL isSelectOriginalPhoto) { + self->_selectedPhotos = [NSMutableArray arrayWithArray:photos]; + self->_selectedAssets = [NSMutableArray arrayWithArray:assets]; + self->_isSelectOriginalPhoto = isSelectOriginalPhoto; + [self->_collectionView reloadData]; + self->_collectionView.contentSize = CGSizeMake(0, ((self->_selectedPhotos.count + 2) / 3 ) * (self->_margin + self->_itemWH)); + }]; + [self presentViewController:imagePickerVc animated:YES completion:nil]; + } + } +} + +#pragma mark - LxGridViewDataSource + +/// 以下三个方法为长按排序相关代码 +- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath { + return indexPath.item < _selectedPhotos.count; +} + +- (BOOL)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)sourceIndexPath canMoveToIndexPath:(NSIndexPath *)destinationIndexPath { + return (sourceIndexPath.item < _selectedPhotos.count && destinationIndexPath.item < _selectedPhotos.count); +} + +- (void)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)sourceIndexPath didMoveToIndexPath:(NSIndexPath *)destinationIndexPath { + UIImage *image = _selectedPhotos[sourceIndexPath.item]; + [_selectedPhotos removeObjectAtIndex:sourceIndexPath.item]; + [_selectedPhotos insertObject:image atIndex:destinationIndexPath.item]; + + id asset = _selectedAssets[sourceIndexPath.item]; + [_selectedAssets removeObjectAtIndex:sourceIndexPath.item]; + [_selectedAssets insertObject:asset atIndex:destinationIndexPath.item]; + + [_collectionView reloadData]; +} + +#pragma mark - TZImagePickerController + +- (void)pushTZImagePickerController { + if (self.maxCountTF.text.integerValue <= 0) { + return; + } + // 设置languageBundle以使用其它语言,必须在TZImagePickerController初始化前设置 / Set languageBundle to use other language + // [TZImagePickerConfig sharedInstance].languageBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"tz-ru" ofType:@"lproj"]]; + + TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:self.maxCountTF.text.integerValue columnNumber:self.columnNumberTF.text.integerValue delegate:self pushPhotoPickerVc:YES]; + +#pragma mark - 五类个性化设置,这些参数都可以不传,此时会走默认设置 + imagePickerVc.isSelectOriginalPhoto = _isSelectOriginalPhoto; + + if (self.maxCountTF.text.integerValue > 1) { + // 1.设置目前已经选中的图片数组 + imagePickerVc.selectedAssets = _selectedAssets; // 目前已经选中的图片数组 + } + imagePickerVc.allowTakePicture = self.showTakePhotoBtnSwitch.isOn; // 在内部显示拍照按钮 + imagePickerVc.allowTakeVideo = self.showTakeVideoBtnSwitch.isOn; // 在内部显示拍视频按 + imagePickerVc.videoMaximumDuration = 10; // 视频最大拍摄时间 + imagePickerVc.allowEditVideo = YES; // 允许编辑视频 + // imagePickerVc.saveEditedVideoToCollection = YES; // 编辑后的视频是否自动保存到相册 + // imagePickerVc.maxCropVideoDuration = 30; // 裁剪视频的最大时长 + // imagePickerVc.presetName = AVAssetExportPresetMediumQuality // 编辑后的视频的导出质量 + [imagePickerVc setUiImagePickerControllerSettingBlock:^(UIImagePickerController *imagePickerController) { + imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; + }]; + // imagePickerVc.autoSelectCurrentWhenDone = NO; + + // imagePickerVc.photoWidth = 1600; + // imagePickerVc.photoPreviewMaxWidth = 1600; + + // 2. Set the appearance + // 2. 在这里设置imagePickerVc的外观 + // imagePickerVc.navigationBar.barTintColor = [UIColor greenColor]; + // imagePickerVc.oKButtonTitleColorDisabled = [UIColor lightGrayColor]; + // imagePickerVc.oKButtonTitleColorNormal = [UIColor greenColor]; + // imagePickerVc.barItemTextColor = [UIColor blackColor]; + // imagePickerVc.navigationBar.translucent = NO; + // [imagePickerVc.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blackColor]}]; + // imagePickerVc.navigationBar.tintColor = [UIColor blackColor]; + // if (@available(iOS 13.0, *)) { + // UINavigationBarAppearance *barAppearance = [[UINavigationBarAppearance alloc] init]; + // barAppearance.backgroundColor = imagePickerVc.navigationBar.barTintColor; + // barAppearance.titleTextAttributes = imagePickerVc.navigationBar.titleTextAttributes; + // imagePickerVc.navigationBar.standardAppearance = barAppearance; + // imagePickerVc.navigationBar.scrollEdgeAppearance = barAppearance; + // } + + imagePickerVc.iconThemeColor = [UIColor colorWithRed:31 / 255.0 green:185 / 255.0 blue:34 / 255.0 alpha:1.0]; + imagePickerVc.showPhotoCannotSelectLayer = YES; + imagePickerVc.cannotSelectLayerColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8]; + /* + [imagePickerVc setPhotoPickerPageUIConfigBlock:^(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine) { + [doneButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; + }]; + */ + /* + [imagePickerVc setAssetCellDidSetModelBlock:^(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView) { + cell.contentView.clipsToBounds = YES; + cell.contentView.layer.cornerRadius = cell.contentView.tz_width * 0.5; + }]; + */ + + // 3. Set allow picking video & photo & originalPhoto or not + // 3. 设置是否可以选择视频/图片/原图 + imagePickerVc.allowPickingVideo = self.allowPickingVideoSwitch.isOn; + imagePickerVc.allowPickingImage = self.allowPickingImageSwitch.isOn; + imagePickerVc.allowPickingOriginalPhoto = self.allowPickingOriginalPhotoSwitch.isOn; + imagePickerVc.allowPickingGif = self.allowPickingGifSwitch.isOn; + imagePickerVc.allowPickingMultipleVideo = self.allowPickingMuitlpleVideoSwitch.isOn; // 是否可以多选视频 + + // 4. 照片排列按修改时间升序 + imagePickerVc.sortAscendingByModificationDate = self.sortAscendingSwitch.isOn; + + // imagePickerVc.minImagesCount = 3; + // imagePickerVc.alwaysEnableDoneBtn = YES; + + // imagePickerVc.minPhotoWidthSelectable = 3000; + // imagePickerVc.minPhotoHeightSelectable = 2000; + + /// 5. Single selection mode, valid when maxImagesCount = 1 + /// 5. 单选模式,maxImagesCount为1时才生效 + imagePickerVc.showSelectBtn = NO; + imagePickerVc.allowCrop = self.allowCropSwitch.isOn; + imagePickerVc.needCircleCrop = self.needCircleCropSwitch.isOn; + // 设置竖屏下的裁剪尺寸 + NSInteger left = 30; + NSInteger widthHeight = self.view.tz_width - 2 * left; + NSInteger top = (self.view.tz_height - widthHeight) / 2; + if ([TZCommonTools tz_isLandscape]) { + top = 30; + widthHeight = self.view.tz_height - 2 * left; + left = (self.view.tz_width - widthHeight) / 2; + } + imagePickerVc.cropRect = CGRectMake(left, top, widthHeight, widthHeight); + imagePickerVc.scaleAspectFillCrop = YES; + // 设置横屏下的裁剪尺寸 + // imagePickerVc.cropRectLandscape = CGRectMake((self.view.tz_height - widthHeight) / 2, left, widthHeight, widthHeight); + /* + [imagePickerVc setCropViewSettingBlock:^(UIView *cropView) { + cropView.layer.borderColor = [UIColor redColor].CGColor; + cropView.layer.borderWidth = 2.0; + }];*/ + + // imagePickerVc.allowPreview = NO; + // 自定义导航栏上的返回按钮 + /* + [imagePickerVc setNavLeftBarButtonSettingBlock:^(UIButton *leftButton){ + [leftButton setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal]; + [leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, -10, 0, 20)]; + }]; + imagePickerVc.delegate = self; + */ + + // Deprecated, Use statusBarStyle + // imagePickerVc.isStatusBarDefault = NO; + imagePickerVc.statusBarStyle = UIStatusBarStyleLightContent; + + // 设置是否显示图片序号 + imagePickerVc.showSelectedIndex = self.showSelectedIndexSwitch.isOn; + + // 设置拍照时是否需要定位,仅对选择器内部拍照有效,外部拍照的,请拷贝demo时手动把pushImagePickerController里定位方法的调用删掉 + // imagePickerVc.allowCameraLocation = NO; + + // 自定义gif播放方案 + [[TZImagePickerConfig sharedInstance] setGifImagePlayBlock:^(TZPhotoPreviewView *view, UIImageView *imageView, NSData *gifData, NSDictionary *info) { + FLAnimatedImage *animatedImage = [FLAnimatedImage animatedImageWithGIFData:gifData]; + FLAnimatedImageView *animatedImageView; + for (UIView *subview in imageView.subviews) { + if ([subview isKindOfClass:[FLAnimatedImageView class]]) { + animatedImageView = (FLAnimatedImageView *)subview; + animatedImageView.frame = imageView.bounds; + animatedImageView.animatedImage = nil; + } + } + if (!animatedImageView) { + animatedImageView = [[FLAnimatedImageView alloc] initWithFrame:imageView.bounds]; + animatedImageView.runLoopMode = NSDefaultRunLoopMode; + [imageView addSubview:animatedImageView]; + } + animatedImageView.animatedImage = animatedImage; + }]; + + // 设置首选语言 / Set preferred language + // imagePickerVc.preferredLanguage = @"zh-Hans"; + +#pragma mark - 到这里为止 + + // You can get the photos by block, the same as by delegate. + // 你可以通过block或者代理,来得到用户选择的照片. + [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray *photos, NSArray *assets, BOOL isSelectOriginalPhoto) { + + }]; + + imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:imagePickerVc animated:YES completion:nil]; +} + +/* +// 设置了navLeftBarButtonSettingBlock后,需打开这个方法,让系统的侧滑返回生效 +- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { + + navigationController.interactivePopGestureRecognizer.enabled = YES; + if (viewController != navigationController.viewControllers[0]) { + navigationController.interactivePopGestureRecognizer.delegate = nil; // 支持侧滑 + } +} +*/ + +#pragma mark - UIImagePickerController + +- (void)takePhoto { + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; + if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) { + // 无相机权限 做一个友好的提示 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; + [alertController addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; + }]]; + [self presentViewController:alertController animated:YES completion:nil]; + } else if (authStatus == AVAuthorizationStatusNotDetermined) { + // fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏 + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { + if (granted) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self takePhoto]; + }); + } + }]; + // 拍照之前还需要检查相册权限 + } else if ([PHPhotoLibrary authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; + [alertController addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; + }]]; + [self presentViewController:alertController animated:YES completion:nil]; + } else if ([PHPhotoLibrary authorizationStatus] == 0) { // 未请求过相册权限 + [[TZImageManager manager] requestAuthorizationWithCompletion:^{ + [self takePhoto]; + }]; + } else { + [self pushImagePickerController]; + } +} + +// 调用相机 +- (void)pushImagePickerController { +#ifdef TZ_HAVE_LOCATION_CODE + // 提前定位 + __weak typeof(self) weakSelf = self; + [[TZLocationManager manager] startLocationWithSuccessBlock:^(NSArray *locations) { + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.location = [locations firstObject]; + } failureBlock:^(NSError *error) { + __strong typeof(weakSelf) strongSelf = weakSelf; + strongSelf.location = nil; + }]; +#endif + + UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; + if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) { + self.imagePickerVc.sourceType = sourceType; + NSMutableArray *mediaTypes = [NSMutableArray array]; + if (self.showTakeVideoBtnSwitch.isOn) { + [mediaTypes addObject:(NSString *)kUTTypeMovie]; + } + if (self.showTakePhotoBtnSwitch.isOn) { + [mediaTypes addObject:(NSString *)kUTTypeImage]; + } + if (mediaTypes.count) { + _imagePickerVc.mediaTypes = mediaTypes; + } + [self presentViewController:_imagePickerVc animated:YES completion:nil]; + } else { + NSLog(@"模拟器中无法打开照相机,请在真机中使用"); + } +} + +- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { + [picker dismissViewControllerAnimated:YES completion:nil]; + NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; + + TZImagePickerController *tzImagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; + tzImagePickerVc.sortAscendingByModificationDate = self.sortAscendingSwitch.isOn; + [tzImagePickerVc showProgressHUD]; + if ([type isEqualToString:@"public.image"]) { + UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; + NSDictionary *meta = [info objectForKey:UIImagePickerControllerMediaMetadata]; + // save photo and get asset / 保存图片,获取到asset + [[TZImageManager manager] savePhotoWithImage:image meta:meta location:self.location completion:^(PHAsset *asset, NSError *error){ + [tzImagePickerVc hideProgressHUD]; + if (error) { + NSLog(@"图片保存失败 %@",error); + } else { + TZAssetModel *assetModel = [[TZImageManager manager] createModelWithAsset:asset]; + if (self.allowCropSwitch.isOn) { // 允许裁剪,去裁剪 + TZImagePickerController *imagePicker = [[TZImagePickerController alloc] initCropTypeWithAsset:assetModel.asset photo:image completion:^(UIImage *cropImage, id asset) { + [self refreshCollectionViewWithAddedAsset:asset image:cropImage]; + }]; + imagePicker.allowPickingImage = YES; + imagePicker.needCircleCrop = self.needCircleCropSwitch.isOn; + imagePicker.circleCropRadius = 100; + [self presentViewController:imagePicker animated:YES completion:nil]; + } else { + [self refreshCollectionViewWithAddedAsset:assetModel.asset image:image]; + } + } + }]; + } else if ([type isEqualToString:@"public.movie"]) { + NSURL *videoUrl = [info objectForKey:UIImagePickerControllerMediaURL]; + if (videoUrl) { + [[TZImageManager manager] saveVideoWithUrl:videoUrl location:self.location completion:^(PHAsset *asset, NSError *error) { + [tzImagePickerVc hideProgressHUD]; + if (!error) { + TZAssetModel *assetModel = [[TZImageManager manager] createModelWithAsset:asset]; + [[TZImageManager manager] getPhotoWithAsset:assetModel.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) { + if (!isDegraded && photo) { + [self refreshCollectionViewWithAddedAsset:assetModel.asset image:photo]; + } + }]; + } + }]; + } + } +} + +- (void)refreshCollectionViewWithAddedAsset:(PHAsset *)asset image:(UIImage *)image { + [_selectedAssets addObject:asset]; + [_selectedPhotos addObject:image]; + [_collectionView reloadData]; +} + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { + if ([picker isKindOfClass:[UIImagePickerController class]]) { + [picker dismissViewControllerAnimated:YES completion:nil]; + } +} + +#pragma mark - TZImagePickerControllerDelegate + +/// User click cancel button +/// 用户点击了取消 +- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker { + // NSLog(@"cancel"); +} + +// The picker should dismiss itself; when it dismissed these handle will be called. +// You can also set autoDismiss to NO, then the picker don't dismiss itself. +// If isOriginalPhoto is YES, user picked the original photo. +// You can get original photo with asset, by the method [[TZImageManager manager] getOriginalPhotoWithAsset:completion:]. +// The UIImage Object in photos default width is 828px, you can set it by photoWidth property. +// 这个照片选择器会自己dismiss,当选择器dismiss的时候,会执行下面的代理方法 +// 你也可以设置autoDismiss属性为NO,选择器就不会自己dismis了 +// 如果isSelectOriginalPhoto为YES,表明用户选择了原图 +// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:] +// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它 +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray *)infos { + _selectedPhotos = [NSMutableArray arrayWithArray:photos]; + _selectedAssets = [NSMutableArray arrayWithArray:assets]; + _isSelectOriginalPhoto = isSelectOriginalPhoto; + [_collectionView reloadData]; + // _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH)); + + // 1.打印图片名字 + [self printAssetsName:assets]; + // 2.图片位置信息 + for (PHAsset *phAsset in assets) { + NSLog(@"location:%@",phAsset.location); + } + + // 3. 获取原图的示例,用队列限制最大并发为1,避免内存暴增 + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 1; + for (NSInteger i = 0; i < assets.count; i++) { + PHAsset *asset = assets[i]; + // 图片上传operation,上传代码请写到operation内的start方法里,内有注释 + TZImageUploadOperation *operation = [[TZImageUploadOperation alloc] initWithAsset:asset completion:^(UIImage * photo, NSDictionary *info, BOOL isDegraded) { + if (isDegraded) return; + NSLog(@"图片获取&上传完成"); + } progressHandler:^(double progress, NSError * _Nonnull error, BOOL * _Nonnull stop, NSDictionary * _Nonnull info) { + NSLog(@"获取原图进度 %f", progress); + }]; + [self.operationQueue addOperation:operation]; + } +} + +/// 如果用户选择了某张照片下面的代理方法会被执行 +/// 如果isSelectOriginalPhoto为YES,表明用户选择了原图 +/// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:] +- (void)imagePickerController:(TZImagePickerController *)picker didSelectAsset:(PHAsset *)asset photo:(UIImage *)photo isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto { +// [_selectedAssets addObject:asset]; +// [_selectedPhotos addObject:photo]; +// [self.collectionView reloadData]; +} + +/// 如果用户取消选择了某张照片下面的代理方法会被执行 +/// 如果isSelectOriginalPhoto为YES,表明用户选择了原图 +/// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:] +- (void)imagePickerController:(TZImagePickerController *)picker didDeselectAsset:(PHAsset *)asset photo:(UIImage *)photo isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto { +// int index = -1; +// for (int i = 0; i < _selectedAssets.count; i++) { +// if ([_selectedAssets[i] isEqual:asset]) { +// index = i; +// } +// } +// if (index > -1) { +// [_selectedAssets removeObjectAtIndex:index]; +// [_selectedPhotos removeObjectAtIndex:index]; +// [self.collectionView reloadData]; +// } +} + +// If user picking a video and allowPickingMultipleVideo is NO, this callback will be called. +// If allowPickingMultipleVideo is YES, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +// 如果用户选择了一个视频且allowPickingMultipleVideo是NO,下面的代理方法会被执行 +// 如果allowPickingMultipleVideo是YES,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(PHAsset *)asset { + _selectedPhotos = [NSMutableArray arrayWithArray:@[coverImage]]; + _selectedAssets = [NSMutableArray arrayWithArray:@[asset]]; + // open this code to send video / 打开这段代码发送视频 + [[TZImageManager manager] getVideoOutputPathWithAsset:asset presetName:AVAssetExportPresetLowQuality success:^(NSString *outputPath) { + // NSData *data = [NSData dataWithContentsOfFile:outputPath]; + NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath); + // Export completed, send video here, send by outputPath or NSData + // 导出完成,在这里写上传代码,通过路径或者通过NSData上传 + } failure:^(NSString *errorMessage, NSError *error) { + NSLog(@"视频导出失败:%@,error:%@",errorMessage, error); + }]; + [_collectionView reloadData]; + // _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH)); +} + +// If allowEditVideo is YES and allowPickingMultipleVideo is NO, When user picking a video, this callback will be called. +// If allowPickingMultipleVideo is YES, video editing is not supported, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +// 当allowEditVideo是YES且allowPickingMultipleVideo是NO是,如果用户选择了一个视频,下面的代理方法会被执行 +// 如果allowPickingMultipleVideo是YES,则不支持编辑视频,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingAndEditingVideo:(UIImage *)coverImage outputPath:(NSString *)outputPath error:(NSString *)errorMsg { + _isAllowEditVideo = YES; + self->_selectedPhotos = [NSMutableArray arrayWithArray:@[coverImage]]; + self->_selectedAssets = [NSMutableArray arrayWithArray:@[[NSURL fileURLWithPath:outputPath]]]; + if (outputPath) { + // NSData *data = [NSData dataWithContentsOfFile:outputPath]; + NSLog(@"视频导出到本地完成,outputPath为:%@",outputPath); + // Export completed, send video here, send by outputPath or NSData + // 导出完成,在这里写上传代码,通过路径或者通过NSData上传 + } else { + NSLog(@"视频导出失败:%@",errorMsg); + } + [self.collectionView reloadData]; +} + +// If user fail to save edited, this callback will be called. +// 如果用户保存编辑好的视频失败,将会调用 +- (void)imagePickerController:(TZImagePickerController *)picker didFailToSaveEditedVideoWithError:(NSError *)error { + NSLog(@"编辑后的视频自动保存到相册失败:%@",error.description); +} + +// If user picking a gif image and allowPickingMultipleVideo is NO, this callback will be called. +// If allowPickingMultipleVideo is YES, will call imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +// 如果用户选择了一个gif图片且allowPickingMultipleVideo是NO,下面的代理方法会被执行 +// 如果allowPickingMultipleVideo是YES,将会调用imagePickerController:didFinishPickingPhotos:sourceAssets:isSelectOriginalPhoto: +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(PHAsset *)asset { + _selectedPhotos = [NSMutableArray arrayWithArray:@[animatedImage]]; + _selectedAssets = [NSMutableArray arrayWithArray:@[asset]]; + [_collectionView reloadData]; +} + +// Decide album show or not't +// 决定相册显示与否 +- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(PHFetchResult *)result { + /* + if ([albumName isEqualToString:@"个人收藏"]) { + return NO; + } + if ([albumName isEqualToString:@"视频"]) { + return NO; + }*/ + return YES; +} + +// Decide asset show or not't +// 决定asset显示与否 +- (BOOL)isAssetCanBeDisplayed:(PHAsset *)asset { + /* + switch (asset.mediaType) { + case PHAssetMediaTypeVideo: { + // 视频时长 + // NSTimeInterval duration = phAsset.duration; + return NO; + } break; + case PHAssetMediaTypeImage: { + // 图片尺寸 + if (asset.pixelWidth > 3000 || asset.pixelHeight > 3000) { + return NO; + } + return YES; + } break; + case PHAssetMediaTypeAudio: + return NO; + break; + case PHAssetMediaTypeUnknown: + return NO; + break; + default: break; + } + */ + return YES; +} + +// Decide asset can be selected +// 决定照片能否被选中 +- (BOOL)isAssetCanBeSelected:(PHAsset *)asset { + /* + switch (asset.mediaType) { + case PHAssetMediaTypeVideo: { + // 视频时长 + // NSTimeInterval duration = phAsset.duration; + return NO; + } break; + case PHAssetMediaTypeImage: { + // 图片尺寸 + if (asset.pixelWidth > 3000 || asset.pixelHeight > 3000) { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"不支持选择超大图片" message:nil preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; + [self.presentedViewController presentViewController:alertController animated:YES completion:nil]; + return NO; + } + return YES; + } break; + case PHAssetMediaTypeAudio: + return NO; + break; + case PHAssetMediaTypeUnknown: + return NO; + break; + default: break; + } + */ + return YES; +} + +#pragma mark - Click Event + +- (void)deleteBtnClik:(UIButton *)sender { + if ([self collectionView:self.collectionView numberOfItemsInSection:0] <= _selectedPhotos.count) { + [_selectedPhotos removeObjectAtIndex:sender.tag]; + [_selectedAssets removeObjectAtIndex:sender.tag]; + [self.collectionView reloadData]; + return; + } + + [_selectedPhotos removeObjectAtIndex:sender.tag]; + [_selectedAssets removeObjectAtIndex:sender.tag]; + [_collectionView performBatchUpdates:^{ + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:sender.tag inSection:0]; + [self->_collectionView deleteItemsAtIndexPaths:@[indexPath]]; + } completion:^(BOOL finished) { + [self->_collectionView reloadData]; + }]; +} + +- (IBAction)showTakePhotoBtnSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + [_allowPickingImageSwitch setOn:YES animated:YES]; + } +} + +- (IBAction)showTakeVideoBtnSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + [_allowPickingVideoSwitch setOn:YES animated:YES]; + } +} + +- (IBAction)showSheetSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + [_allowPickingImageSwitch setOn:YES animated:YES]; + } +} + +- (IBAction)allowPickingOriginPhotoSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + [_allowPickingImageSwitch setOn:YES animated:YES]; + [self.needCircleCropSwitch setOn:NO animated:YES]; + [self.allowCropSwitch setOn:NO animated:YES]; + } +} + +- (IBAction)allowPickingImageSwitchClick:(UISwitch *)sender { + if (!sender.isOn) { + [_allowPickingOriginalPhotoSwitch setOn:NO animated:YES]; + [_allowPickingVideoSwitch setOn:YES animated:YES]; + [_allowPickingGifSwitch setOn:NO animated:YES]; + } +} + +- (IBAction)allowPickingGifSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + [_allowPickingImageSwitch setOn:YES animated:YES]; + } else if (!self.allowPickingVideoSwitch.isOn) { + [self.allowPickingMuitlpleVideoSwitch setOn:NO animated:YES]; + } +} + +- (IBAction)allowPickingVideoSwitchClick:(UISwitch *)sender { + if (!sender.isOn) { + [_allowPickingImageSwitch setOn:YES animated:YES]; + if (!self.allowPickingGifSwitch.isOn) { + [self.allowPickingMuitlpleVideoSwitch setOn:NO animated:YES]; + } + } +} + +- (IBAction)allowCropSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + self.maxCountTF.text = @"1"; + [self.allowPickingOriginalPhotoSwitch setOn:NO animated:YES]; + } else { + if ([self.maxCountTF.text isEqualToString:@"1"]) { + self.maxCountTF.text = @"9"; + } + [self.needCircleCropSwitch setOn:NO animated:YES]; + } +} + +- (IBAction)needCircleCropSwitchClick:(UISwitch *)sender { + if (sender.isOn) { + [self.allowCropSwitch setOn:YES animated:YES]; + self.maxCountTF.text = @"1"; + [self.allowPickingOriginalPhotoSwitch setOn:NO animated:YES]; + } +} + +- (IBAction)allowPickingMultipleVideoSwitchClick:(UISwitch *)sender { + +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self.view endEditing:YES]; +} + +#pragma mark - Private + +/// 打印图片名字 +- (void)printAssetsName:(NSArray *)assets { + NSString *fileName; + for (PHAsset *asset in assets) { + fileName = [asset valueForKey:@"filename"]; + // NSLog(@"图片名字:%@",fileName); + } +} + +#pragma clang diagnostic pop + +@end diff --git a/TZImagePickerController/ar-001.lproj/LaunchScreen.strings b/TZImagePickerController/ar-001.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/TZImagePickerController/ar-001.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/TZImagePickerController/ar-001.lproj/Localizable.strings b/TZImagePickerController/ar-001.lproj/Localizable.strings new file mode 100755 index 0000000000000000000000000000000000000000..0c0bdcfb175ef0581ea1db5cd13a1293dfb6b46a GIT binary patch literal 1886 zcmbu9Ur!T36vgkuJo)H5I%(pY8mLw(g{2fk2_}$`7$1BoP-&%f8z@%%G<;I^cV_?1 zVro#c8Q9LAd+xdS+?k(08g^j&)-Z1ytcKm%Be&_guH{~`I;;)Xb_cFu9ecp{p7rg- z&ZCH?OWdk!60_{~a(t`A?^tRR8$|e3a7}Ps_YUTsdtYLYz+Up)MCixh61N4eUE;RU zFhRw@#t||Bv!3U#vkq*=Ga}|J!Y`piyyAcD)*}8x8=_>!x{B~S;Cig06CYqaMME9c zgh!pLaEDYhu&g(H^o+R5p9H;a_ky*7{!SUCENSS; z6{@pZpPQaIc7^C=w-Pe0@m3%*Z?nF7`lRYTINa>bm_>`4N80&0(lug7)vZes9yr32&bR;v#frn+~NY zJgq5uNPhK2z9vkq=CQ?|rn5!ngP@{~E~y!jwP4ZjtdZ$tIcA*%k7uZs z$Fa(J*qgAcIr4a~iPQ=5R5zoF88J`!H4m|KzGM?S%qtYX2lYF59|kG?mmYjU#|6C; za~knanTrt>=w`ZMUk+3!Uiqec(>apnX{cU0r130giuo4Ddpj;OjG0IAsY=~P=e*y* zcDGC)0xH_zR zS9eTN?Imx0@W*)t+01;(tF8O+%o5PLt75;3-Rjm=^rDk-So2Srb%yV&G``D<`Tl#Y LI-SLhxLE5iEX5p4 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/ar-001.lproj/Main.strings b/TZImagePickerController/ar-001.lproj/Main.strings new file mode 100644 index 0000000..736c8db --- /dev/null +++ b/TZImagePickerController/ar-001.lproj/Main.strings @@ -0,0 +1,48 @@ + +/* Class = "UITextField"; text = "9"; ObjectID = "37K-cO-hgf"; */ +"37K-cO-hgf.text" = "9"; + +/* Class = "UILabel"; text = "允许选择照片原图"; ObjectID = "7mi-Lf-2N5"; */ +"7mi-Lf-2N5.text" = "允许选择照片原图"; + +/* Class = "UILabel"; text = "允许多选视频/GIF/图片"; ObjectID = "7q9-aI-kbz"; */ +"7q9-aI-kbz.text" = "允许多选视频/GIF/图片"; + +/* Class = "UILabel"; text = "允许拍视频"; ObjectID = "8H2-cq-aUq"; */ +"8H2-cq-aUq.text" = "允许拍视频"; + +/* Class = "UILabel"; text = "单选模式下允许裁剪"; ObjectID = "Ibb-kN-MWC"; */ +"Ibb-kN-MWC.text" = "单选模式下允许裁剪"; + +/* Class = "UILabel"; text = "允许选择Gif图片"; ObjectID = "Ly2-uJ-7DN"; */ +"Ly2-uJ-7DN.text" = "允许选择Gif图片"; + +/* Class = "UILabel"; text = "允许拍照"; ObjectID = "R92-Zn-NWV"; */ +"R92-Zn-NWV.text" = "允许拍照"; + +/* Class = "UILabel"; text = "使用圆形裁剪框"; ObjectID = "TiG-df-jDs"; */ +"TiG-df-jDs.text" = "使用圆形裁剪框"; + +/* Class = "UILabel"; text = "照片按修改时间升序排列"; ObjectID = "UL3-n3-Hmt"; */ +"UL3-n3-Hmt.text" = "照片按修改时间升序排列"; + +/* Class = "UITextField"; text = "4"; ObjectID = "YR1-nJ-q0v"; */ +"YR1-nJ-q0v.text" = "4"; + +/* Class = "UILabel"; text = "每行展示照片张数"; ObjectID = "fbH-6q-oeE"; */ +"fbH-6q-oeE.text" = "每行展示照片张数"; + +/* Class = "UILabel"; text = "把拍照/拍视频按钮放在外面"; ObjectID = "jop-5R-ioj"; */ +"jop-5R-ioj.text" = "把拍照/拍视频按钮放在外面"; + +/* Class = "UILabel"; text = "右上角显示图片选中序号"; ObjectID = "nm2-mT-siy"; */ +"nm2-mT-siy.text" = "右上角显示图片选中序号"; + +/* Class = "UILabel"; text = "照片最大可选张数"; ObjectID = "rK3-1U-kcW"; */ +"rK3-1U-kcW.text" = "照片最大可选张数"; + +/* Class = "UILabel"; text = "允许选择照片"; ObjectID = "vNN-OI-9z1"; */ +"vNN-OI-9z1.text" = "允许选择照片"; + +/* Class = "UILabel"; text = "允许选择视频"; ObjectID = "xCu-D3-IZg"; */ +"xCu-D3-IZg.text" = "允许选择视频"; diff --git a/TZImagePickerController/main.m b/TZImagePickerController/main.m new file mode 100644 index 0000000..2c76a8c --- /dev/null +++ b/TZImagePickerController/main.m @@ -0,0 +1,16 @@ +// +// main.m +// TZImagePickerController +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/TZImagePickerController/tz-ru.lproj/Localizable.strings b/TZImagePickerController/tz-ru.lproj/Localizable.strings new file mode 100755 index 0000000000000000000000000000000000000000..0c0bdcfb175ef0581ea1db5cd13a1293dfb6b46a GIT binary patch literal 1886 zcmbu9Ur!T36vgkuJo)H5I%(pY8mLw(g{2fk2_}$`7$1BoP-&%f8z@%%G<;I^cV_?1 zVro#c8Q9LAd+xdS+?k(08g^j&)-Z1ytcKm%Be&_guH{~`I;;)Xb_cFu9ecp{p7rg- z&ZCH?OWdk!60_{~a(t`A?^tRR8$|e3a7}Ps_YUTsdtYLYz+Up)MCixh61N4eUE;RU zFhRw@#t||Bv!3U#vkq*=Ga}|J!Y`piyyAcD)*}8x8=_>!x{B~S;Cig06CYqaMME9c zgh!pLaEDYhu&g(H^o+R5p9H;a_ky*7{!SUCENSS; z6{@pZpPQaIc7^C=w-Pe0@m3%*Z?nF7`lRYTINa>bm_>`4N80&0(lug7)vZes9yr32&bR;v#frn+~NY zJgq5uNPhK2z9vkq=CQ?|rn5!ngP@{~E~y!jwP4ZjtdZ$tIcA*%k7uZs z$Fa(J*qgAcIr4a~iPQ=5R5zoF88J`!H4m|KzGM?S%qtYX2lYF59|kG?mmYjU#|6C; za~knanTrt>=w`ZMUk+3!Uiqec(>apnX{cU0r130giuo4Ddpj;OjG0IAsY=~P=e*y* zcDGC)0xH_zR zS9eTN?Imx0@W*)t+01;(tF8O+%o5PLt75;3-Rjm=^rDk-So2Srb%yV&G``D<`Tl#Y LI-SLhxLE5iEX5p4 literal 0 HcmV?d00001 diff --git a/TZImagePickerController/zh-Hans.lproj/LaunchScreen.strings b/TZImagePickerController/zh-Hans.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/TZImagePickerController/zh-Hans.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/TZImagePickerController/zh-Hans.lproj/Main.strings b/TZImagePickerController/zh-Hans.lproj/Main.strings new file mode 100644 index 0000000..64c63b6 --- /dev/null +++ b/TZImagePickerController/zh-Hans.lproj/Main.strings @@ -0,0 +1,18 @@ + +/* Class = "UILabel"; text = "允许选择照片原图"; ObjectID = "7mi-Lf-2N5"; */ +"7mi-Lf-2N5.text" = "允许选择照片原图"; + +/* Class = "UILabel"; text = "显示内部拍照按钮"; ObjectID = "R92-Zn-NWV"; */ +"R92-Zn-NWV.text" = "显示内部拍照按钮"; + +/* Class = "UILabel"; text = "照片按修改时间升序排列"; ObjectID = "UL3-n3-Hmt"; */ +"UL3-n3-Hmt.text" = "照片按修改时间升序排列"; + +/* Class = "UILabel"; text = "把拍照按钮放在外面"; ObjectID = "jop-5R-ioj"; */ +"jop-5R-ioj.text" = "把拍照按钮放在外面"; + +/* Class = "UILabel"; text = "允许选择照片"; ObjectID = "vNN-OI-9z1"; */ +"vNN-OI-9z1.text" = "允许选择照片"; + +/* Class = "UILabel"; text = "允许选择视频"; ObjectID = "xCu-D3-IZg"; */ +"xCu-D3-IZg.text" = "允许选择视频"; diff --git a/TZImagePickerControllerFramework/Info.plist b/TZImagePickerControllerFramework/Info.plist new file mode 100644 index 0000000..fcd3639 --- /dev/null +++ b/TZImagePickerControllerFramework/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/TZImagePickerControllerFramework/PrivacyInfo.xcprivacy b/TZImagePickerControllerFramework/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..37d5aee --- /dev/null +++ b/TZImagePickerControllerFramework/PrivacyInfo.xcprivacy @@ -0,0 +1,25 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + 3B52.1 + + + + NSPrivacyCollectedDataTypes + + + + NSPrivacyTrackingDomains + + NSPrivacyTracking + + + diff --git a/TZImagePickerControllerTests/Info.plist b/TZImagePickerControllerTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/TZImagePickerControllerTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/TZImagePickerControllerTests/TZImagePickerControllerTests.m b/TZImagePickerControllerTests/TZImagePickerControllerTests.m new file mode 100644 index 0000000..565b02b --- /dev/null +++ b/TZImagePickerControllerTests/TZImagePickerControllerTests.m @@ -0,0 +1,39 @@ +// +// TZImagePickerControllerTests.m +// TZImagePickerControllerTests +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@interface TZImagePickerControllerTests : XCTestCase + +@end + +@implementation TZImagePickerControllerTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/TZImagePickerControllerUITests/Info.plist b/TZImagePickerControllerUITests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/TZImagePickerControllerUITests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/TZImagePickerControllerUITests/TZImagePickerControllerUITests.m b/TZImagePickerControllerUITests/TZImagePickerControllerUITests.m new file mode 100644 index 0000000..ca4f9c9 --- /dev/null +++ b/TZImagePickerControllerUITests/TZImagePickerControllerUITests.m @@ -0,0 +1,40 @@ +// +// TZImagePickerControllerUITests.m +// TZImagePickerControllerUITests +// +// Created by 谭真 on 15/12/24. +// Copyright © 2015年 谭真. All rights reserved. +// + +#import + +@interface TZImagePickerControllerUITests : XCTestCase + +@end + +@implementation TZImagePickerControllerUITests + +- (void)setUp { + [super setUp]; + + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + self.continueAfterFailure = NO; + // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. + [[[XCUIApplication alloc] init] launch]; + + // 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. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +@end