Commit 96921baf authored by Sandy's avatar Sandy

销售录入-修改界面,增加照片附件

parent 7cd30a83
......@@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
19000E861CC6215000DF8D71 /* ChooseShopViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19000E761CC6215000DF8D71 /* ChooseShopViewController.m */; };
19000E871CC6215000DF8D71 /* HistoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19000E781CC6215000DF8D71 /* HistoryViewController.m */; };
19000E881CC6215000DF8D71 /* SalesInputViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19000E7A1CC6215000DF8D71 /* SalesInputViewController.m */; };
19000E891CC6215000DF8D71 /* HistoryTopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 19000E7E1CC6215000DF8D71 /* HistoryTopView.m */; };
19000E8A1CC6215000DF8D71 /* HistoryTopView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19000E7F1CC6215000DF8D71 /* HistoryTopView.xib */; };
19000E8B1CC6215000DF8D71 /* SalesInputTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 19000E811CC6215000DF8D71 /* SalesInputTableViewCell.m */; };
......@@ -29,6 +28,23 @@
1912FCE51CCDF1F6004CF976 /* SalesInputCommitView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1912FCE41CCDF1F6004CF976 /* SalesInputCommitView.xib */; };
1912FCE81CCDF20F004CF976 /* SalesInputCommitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1912FCE71CCDF20F004CF976 /* SalesInputCommitView.m */; };
1912FCF41CCF1493004CF976 /* ChooseProjectTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1912FCF31CCF1493004CF976 /* ChooseProjectTableViewController.m */; };
19D76A881D265A1B006245D6 /* TZAssetCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A761D265A1B006245D6 /* TZAssetCell.m */; };
19D76A891D265A1B006245D6 /* TZAssetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A781D265A1B006245D6 /* TZAssetModel.m */; };
19D76A8A1D265A1B006245D6 /* TZImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A7A1D265A1B006245D6 /* TZImageManager.m */; };
19D76A8B1D265A1B006245D6 /* TZImagePickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 19D76A7B1D265A1B006245D6 /* TZImagePickerController.bundle */; };
19D76A8C1D265A1B006245D6 /* TZImagePickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A7D1D265A1B006245D6 /* TZImagePickerController.m */; };
19D76A8D1D265A1B006245D6 /* TZPhotoPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A7F1D265A1B006245D6 /* TZPhotoPickerController.m */; };
19D76A8E1D265A1B006245D6 /* TZPhotoPreviewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A811D265A1B006245D6 /* TZPhotoPreviewCell.m */; };
19D76A8F1D265A1B006245D6 /* TZPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A831D265A1B006245D6 /* TZPhotoPreviewController.m */; };
19D76A901D265A1B006245D6 /* TZVideoPlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A851D265A1B006245D6 /* TZVideoPlayerController.m */; };
19D76A911D265A1B006245D6 /* UIView+Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A871D265A1B006245D6 /* UIView+Layout.m */; };
19D76A971D266557006245D6 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19D76A921D265CB1006245D6 /* AssetsLibrary.framework */; };
19D76A981D266680006245D6 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19D76A941D265DC9006245D6 /* Photos.framework */; };
19D76A9B1D266780006245D6 /* SalesInputViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A9A1D266780006245D6 /* SalesInputViewController.m */; };
19D76AA01D2667AB006245D6 /* SaleInputPictureTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76A9D1D2667AB006245D6 /* SaleInputPictureTableViewCell.m */; };
19D76AA11D2667AB006245D6 /* SaleInputPictureTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19D76A9E1D2667AB006245D6 /* SaleInputPictureTableViewCell.xib */; };
19D76AA21D2667AB006245D6 /* SaleInputPictureCellHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19D76A9F1D2667AB006245D6 /* SaleInputPictureCellHeader.xib */; };
19D76AA51D266910006245D6 /* CALayer+Addtions.m in Sources */ = {isa = PBXBuildFile; fileRef = 19D76AA41D266910006245D6 /* CALayer+Addtions.m */; };
A0D453625552DAC91D4EB4A7 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5987243B74E897E93DEC7D3 /* libPods.a */; };
C10F161B1BF77CA00065F18C /* ICRAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C10F16121BF77CA00065F18C /* ICRAboutViewController.m */; };
C10F161C1BF77CA00065F18C /* ICRConfigurationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C10F16141BF77CA00065F18C /* ICRConfigurationViewController.m */; };
......@@ -732,8 +748,6 @@
19000E761CC6215000DF8D71 /* ChooseShopViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChooseShopViewController.m; sourceTree = "<group>"; };
19000E771CC6215000DF8D71 /* HistoryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryViewController.h; sourceTree = "<group>"; };
19000E781CC6215000DF8D71 /* HistoryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryViewController.m; sourceTree = "<group>"; };
19000E791CC6215000DF8D71 /* SalesInputViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SalesInputViewController.h; sourceTree = "<group>"; };
19000E7A1CC6215000DF8D71 /* SalesInputViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SalesInputViewController.m; sourceTree = "<group>"; };
19000E7D1CC6215000DF8D71 /* HistoryTopView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryTopView.h; sourceTree = "<group>"; };
19000E7E1CC6215000DF8D71 /* HistoryTopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryTopView.m; sourceTree = "<group>"; };
19000E7F1CC6215000DF8D71 /* HistoryTopView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HistoryTopView.xib; sourceTree = "<group>"; };
......@@ -765,6 +779,35 @@
1912FCE71CCDF20F004CF976 /* SalesInputCommitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SalesInputCommitView.m; sourceTree = "<group>"; };
1912FCF21CCF1493004CF976 /* ChooseProjectTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChooseProjectTableViewController.h; sourceTree = "<group>"; };
1912FCF31CCF1493004CF976 /* ChooseProjectTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChooseProjectTableViewController.m; sourceTree = "<group>"; };
19D76A751D265A1B006245D6 /* TZAssetCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZAssetCell.h; sourceTree = "<group>"; };
19D76A761D265A1B006245D6 /* TZAssetCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZAssetCell.m; sourceTree = "<group>"; };
19D76A771D265A1B006245D6 /* TZAssetModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZAssetModel.h; sourceTree = "<group>"; };
19D76A781D265A1B006245D6 /* TZAssetModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZAssetModel.m; sourceTree = "<group>"; };
19D76A791D265A1B006245D6 /* TZImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImageManager.h; sourceTree = "<group>"; };
19D76A7A1D265A1B006245D6 /* TZImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImageManager.m; sourceTree = "<group>"; };
19D76A7B1D265A1B006245D6 /* TZImagePickerController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TZImagePickerController.bundle; sourceTree = "<group>"; };
19D76A7C1D265A1B006245D6 /* TZImagePickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImagePickerController.h; sourceTree = "<group>"; };
19D76A7D1D265A1B006245D6 /* TZImagePickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImagePickerController.m; sourceTree = "<group>"; };
19D76A7E1D265A1B006245D6 /* TZPhotoPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPickerController.h; sourceTree = "<group>"; };
19D76A7F1D265A1B006245D6 /* TZPhotoPickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPickerController.m; sourceTree = "<group>"; };
19D76A801D265A1B006245D6 /* TZPhotoPreviewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPreviewCell.h; sourceTree = "<group>"; };
19D76A811D265A1B006245D6 /* TZPhotoPreviewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPreviewCell.m; sourceTree = "<group>"; };
19D76A821D265A1B006245D6 /* TZPhotoPreviewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPreviewController.h; sourceTree = "<group>"; };
19D76A831D265A1B006245D6 /* TZPhotoPreviewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPreviewController.m; sourceTree = "<group>"; };
19D76A841D265A1B006245D6 /* TZVideoPlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZVideoPlayerController.h; sourceTree = "<group>"; };
19D76A851D265A1B006245D6 /* TZVideoPlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZVideoPlayerController.m; sourceTree = "<group>"; };
19D76A861D265A1B006245D6 /* UIView+Layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Layout.h"; sourceTree = "<group>"; };
19D76A871D265A1B006245D6 /* UIView+Layout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Layout.m"; sourceTree = "<group>"; };
19D76A921D265CB1006245D6 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
19D76A941D265DC9006245D6 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; };
19D76A991D266780006245D6 /* SalesInputViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SalesInputViewController.h; sourceTree = "<group>"; };
19D76A9A1D266780006245D6 /* SalesInputViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SalesInputViewController.m; sourceTree = "<group>"; };
19D76A9C1D2667AB006245D6 /* SaleInputPictureTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaleInputPictureTableViewCell.h; sourceTree = "<group>"; };
19D76A9D1D2667AB006245D6 /* SaleInputPictureTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SaleInputPictureTableViewCell.m; sourceTree = "<group>"; };
19D76A9E1D2667AB006245D6 /* SaleInputPictureTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SaleInputPictureTableViewCell.xib; sourceTree = "<group>"; };
19D76A9F1D2667AB006245D6 /* SaleInputPictureCellHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SaleInputPictureCellHeader.xib; sourceTree = "<group>"; };
19D76AA31D266910006245D6 /* CALayer+Addtions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+Addtions.h"; sourceTree = "<group>"; };
19D76AA41D266910006245D6 /* CALayer+Addtions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+Addtions.m"; sourceTree = "<group>"; };
710E0C5D8A5E02D32E5C6C2D /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
C10F16111BF77CA00065F18C /* ICRAboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICRAboutViewController.h; path = view_iPhone/templates/settings/ICRAboutViewController.h; sourceTree = "<group>"; };
C10F16121BF77CA00065F18C /* ICRAboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ICRAboutViewController.m; path = view_iPhone/templates/settings/ICRAboutViewController.m; sourceTree = "<group>"; };
......@@ -1972,6 +2015,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
19D76A981D266680006245D6 /* Photos.framework in Frameworks */,
19D76A971D266557006245D6 /* AssetsLibrary.framework in Frameworks */,
190AFDA41CF4434F002698FC /* WebKit.framework in Frameworks */,
C1D58B2C1BB1BC9200D297FE /* QuartzCore.framework in Frameworks */,
C1D58B241BB1BC9200D297FE /* CoreMedia.framework in Frameworks */,
......@@ -2013,8 +2058,8 @@
19000E761CC6215000DF8D71 /* ChooseShopViewController.m */,
19000E771CC6215000DF8D71 /* HistoryViewController.h */,
19000E781CC6215000DF8D71 /* HistoryViewController.m */,
19000E791CC6215000DF8D71 /* SalesInputViewController.h */,
19000E7A1CC6215000DF8D71 /* SalesInputViewController.m */,
19D76A991D266780006245D6 /* SalesInputViewController.h */,
19D76A9A1D266780006245D6 /* SalesInputViewController.m */,
1912FCF21CCF1493004CF976 /* ChooseProjectTableViewController.h */,
1912FCF31CCF1493004CF976 /* ChooseProjectTableViewController.m */,
);
......@@ -2033,6 +2078,10 @@
19000E7C1CC6215000DF8D71 /* View */ = {
isa = PBXGroup;
children = (
19D76A9C1D2667AB006245D6 /* SaleInputPictureTableViewCell.h */,
19D76A9D1D2667AB006245D6 /* SaleInputPictureTableViewCell.m */,
19D76A9E1D2667AB006245D6 /* SaleInputPictureTableViewCell.xib */,
19D76A9F1D2667AB006245D6 /* SaleInputPictureCellHeader.xib */,
19000E8F1CC71DD200DF8D71 /* MyToolBar.h */,
19000E901CC71DD200DF8D71 /* MyToolBar.m */,
19000E7D1CC6215000DF8D71 /* HistoryTopView.h */,
......@@ -2054,9 +2103,38 @@
path = View;
sourceTree = "<group>";
};
19D76A741D265A1B006245D6 /* TZImagePickerController */ = {
isa = PBXGroup;
children = (
19D76A751D265A1B006245D6 /* TZAssetCell.h */,
19D76A761D265A1B006245D6 /* TZAssetCell.m */,
19D76A771D265A1B006245D6 /* TZAssetModel.h */,
19D76A781D265A1B006245D6 /* TZAssetModel.m */,
19D76A791D265A1B006245D6 /* TZImageManager.h */,
19D76A7A1D265A1B006245D6 /* TZImageManager.m */,
19D76A7B1D265A1B006245D6 /* TZImagePickerController.bundle */,
19D76A7C1D265A1B006245D6 /* TZImagePickerController.h */,
19D76A7D1D265A1B006245D6 /* TZImagePickerController.m */,
19D76A7E1D265A1B006245D6 /* TZPhotoPickerController.h */,
19D76A7F1D265A1B006245D6 /* TZPhotoPickerController.m */,
19D76A801D265A1B006245D6 /* TZPhotoPreviewCell.h */,
19D76A811D265A1B006245D6 /* TZPhotoPreviewCell.m */,
19D76A821D265A1B006245D6 /* TZPhotoPreviewController.h */,
19D76A831D265A1B006245D6 /* TZPhotoPreviewController.m */,
19D76A841D265A1B006245D6 /* TZVideoPlayerController.h */,
19D76A851D265A1B006245D6 /* TZVideoPlayerController.m */,
19D76A861D265A1B006245D6 /* UIView+Layout.h */,
19D76A871D265A1B006245D6 /* UIView+Layout.m */,
);
path = TZImagePickerController;
sourceTree = "<group>";
};
C10F17831BF7ACA80065F18C /* 3rd */ = {
isa = PBXGroup;
children = (
19D76AA31D266910006245D6 /* CALayer+Addtions.h */,
19D76AA41D266910006245D6 /* CALayer+Addtions.m */,
19D76A741D265A1B006245D6 /* TZImagePickerController */,
C18A95421C01F56200429BF7 /* DataBaseController */,
C10F17841BF7ACA80065F18C /* General */,
C18A954A1C01FAE500429BF7 /* HTTPController */,
......@@ -2701,6 +2779,8 @@
C1D58B181BB1BC9200D297FE /* Frameworks */ = {
isa = PBXGroup;
children = (
19D76A941D265DC9006245D6 /* Photos.framework */,
19D76A921D265CB1006245D6 /* AssetsLibrary.framework */,
190AFDA31CF4434F002698FC /* WebKit.framework */,
C1D58B191BB1BC9200D297FE /* UIKit.framework */,
C1D58B1B1BB1BC9200D297FE /* Foundation.framework */,
......@@ -4407,6 +4487,7 @@
C19AC88D1C1735E600DE260E /* confirmed@3x.png in Resources */,
C1D595031BB42A6800D297FE /* page-normal@2x.png in Resources */,
C117864F1C0B3A5900DB7E4B /* notice_icon@3x.png in Resources */,
19D76AA11D2667AB006245D6 /* SaleInputPictureTableViewCell.xib in Resources */,
C117866A1C0B4C5200DB7E4B /* bill_remark@2x.png in Resources */,
C19AC89E1C1735E600DE260E /* rejected_big@2x.png in Resources */,
C1DED3391BCEC4B40049BB2D /* user.png in Resources */,
......@@ -4457,6 +4538,7 @@
C19AC88F1C1735E600DE260E /* confirmed_big@3x.png in Resources */,
C19AC8951C1735E600DE260E /* money_red_point@3x.png in Resources */,
C1A06A001BE105140082006F /* VankeAffairsBoard_iPhone.xml in Resources */,
19D76A8B1D265A1B006245D6 /* TZImagePickerController.bundle in Resources */,
C117864A1C0B3A5900DB7E4B /* money_red_point@2x.png in Resources */,
C19AC8931C1735E600DE260E /* money_add@3x.png in Resources */,
C19ADE351BC6C71F00206213 /* floor-def.jpg in Resources */,
......@@ -4488,6 +4570,7 @@
C19AC8911C1735E600DE260E /* money@3x.png in Resources */,
C14D6F7B1BB8098400210172 /* people.png in Resources */,
C16507891BB96C2800CB2FC1 /* login_bg@2x.png in Resources */,
19D76AA21D2667AB006245D6 /* SaleInputPictureCellHeader.xib in Resources */,
C1DED32D1BCEC4B40049BB2D /* blue_bg.png in Resources */,
19000E961CC74DC800DF8D71 /* SalesInputTotalView.xib in Resources */,
C19AC88E1C1735E600DE260E /* confirmed_big@2x.png in Resources */,
......@@ -4646,6 +4729,7 @@
C10F18191BF7ACA80065F18C /* UIImage+Helper.m in Sources */,
C10F18221BF7ACA80065F18C /* IBTAdditionsObserver.m in Sources */,
C1D598D71BB44B2000D297FE /* UIViewController+BeeUISignal.m in Sources */,
19D76A8E1D265A1B006245D6 /* TZPhotoPreviewCell.m in Sources */,
C10F18251BF7ACA80065F18C /* IBTFileManager.m in Sources */,
C1D5992D1BB44B2100D297FE /* Bee_SQLITE.m in Sources */,
C1D598C61BB44B2000D297FE /* UIView+Wireframe.m in Sources */,
......@@ -4707,6 +4791,7 @@
C17ABD4D1BFCD48A00908573 /* VankeStatementDetailListBoard_iPhone.m in Sources */,
C1D598591BB44B2000D297FE /* Bee_UIConfig.m in Sources */,
C12805091BC55773001ECBAA /* VankeBaseAPI.m in Sources */,
19D76A881D265A1B006245D6 /* TZAssetCell.m in Sources */,
C1D599041BB44B2000D297FE /* BeeUISignal+SourceModel.m in Sources */,
19000E941CC74DB000DF8D71 /* SalesInputTotalVIew.m in Sources */,
C1D599291BB44B2100D297FE /* Bee_ActiveProtocol.m in Sources */,
......@@ -4856,6 +4941,7 @@
C16BA6271BD39491001ACB26 /* VankePassengerFlowModel.m in Sources */,
C1D599141BB44B2100D297FE /* Bee_UITemplateParserXMLImpl_v1.m in Sources */,
C1D598631BB44B2000D297FE /* BeeUIBoard+Traversing.m in Sources */,
19D76A8F1D265A1B006245D6 /* TZPhotoPreviewController.m in Sources */,
C1D599351BB44B2100D297FE /* Bee_Log.mm in Sources */,
C1D598FA1BB44B2000D297FE /* BeeUIQuery+Traversing.m in Sources */,
C1D598491BB44B2000D297FE /* Bee_Routine.mm in Sources */,
......@@ -4870,6 +4956,7 @@
C1D598F51BB44B2000D297FE /* BeeUIQuery+Events.m in Sources */,
C1D598F61BB44B2000D297FE /* BeeUIQuery+Manipulation.m in Sources */,
C19BBBFD1BBE85F500831290 /* VankeServiceBoardCell_iPhone.m in Sources */,
19D76A891D265A1B006245D6 /* TZAssetModel.m in Sources */,
C1D599701BB44B2100D297FE /* Bee_Service.m in Sources */,
C1E0AD861C131D1F00DE6BB9 /* VankeTenantTabBoard_iPhone.m in Sources */,
C1CF9F301BEF20DB0033C35E /* VankeNoticeBoard_iPhone.m in Sources */,
......@@ -4917,10 +5004,12 @@
C18A95401C01E98200429BF7 /* IBTModel.m in Sources */,
C1D598921BB44B2000D297FE /* UITextField+UIDataBinding.m in Sources */,
C1D5992F1BB44B2100D297FE /* NSArray+BeeActiveRecord.m in Sources */,
19D76A911D265A1B006245D6 /* UIView+Layout.m in Sources */,
C18A95391C01E8E100429BF7 /* ICRAnnouncementDetailContentView.m in Sources */,
C1D599101BB44B2000D297FE /* UIViewController+BeeUITemplate.m in Sources */,
C1D599371BB44B2100D297FE /* Bee_Runtime.mm in Sources */,
C1D5993A1BB44B2100D297FE /* Bee_SystemInfo.mm in Sources */,
19D76AA01D2667AB006245D6 /* SaleInputPictureTableViewCell.m in Sources */,
C19ADE601BCABBC100206213 /* VankeAppBoard_iPhone.m in Sources */,
C1D598E91BB44B2000D297FE /* UIImageView+LayoutParser.m in Sources */,
C1D598D11BB44B2000D297FE /* BeeUIZoomImageView+UIDataBinding.m in Sources */,
......@@ -4964,6 +5053,7 @@
C10F182F1BF7ACA80065F18C /* ICRLoginContentView.m in Sources */,
C1D5991C1BB44B2100D297FE /* Bee_System.mm in Sources */,
C10F18441BF7ACA80065F18C /* IBTUIControl.m in Sources */,
19D76A9B1D266780006245D6 /* SalesInputViewController.m in Sources */,
C1D5995C1BB44B2100D297FE /* Bee_HTTPConnectionPool2.m in Sources */,
C11BAB1E1C08BF83007BBCCC /* VankePassengerListBoardCell_iPhone.m in Sources */,
C10F182A1BF7ACA80065F18C /* IBTTextFieldCell.m in Sources */,
......@@ -4978,7 +5068,6 @@
C1D598AC1BB44B2000D297FE /* Bee_UIScrollView.m in Sources */,
C1D599191BB44B2100D297FE /* UITextField+XMLParser.m in Sources */,
C1D599521BB44B2100D297FE /* Bee_Network.m in Sources */,
19000E881CC6215000DF8D71 /* SalesInputViewController.m in Sources */,
C1D5991B1BB44B2100D297FE /* UIView+XMLParser.m in Sources */,
C12804DA1BC12A67001ECBAA /* VankeWeatherController.m in Sources */,
C1D599211BB44B2100D297FE /* Bee_FileCache.mm in Sources */,
......@@ -4988,6 +5077,7 @@
C19BBBF91BBE85F500831290 /* VankeMainBoard_iPhone.m in Sources */,
C1D599261BB44B2100D297FE /* NSObject+BeeUserDefaults.mm in Sources */,
C10F18401BF7ACA80065F18C /* IBTTabBarController.m in Sources */,
19D76A901D265A1B006245D6 /* TZVideoPlayerController.m in Sources */,
C1D598741BB44B2000D297FE /* UIActivityIndicatorView+BeeUIStyle.m in Sources */,
C10F186F1BF8EE600065F18C /* VankeStatementListBoard_iPhone.m in Sources */,
C1D599901BB44B2100D297FE /* unzip.c in Sources */,
......@@ -5020,6 +5110,7 @@
C1D599381BB44B2100D297FE /* Bee_Sandbox.mm in Sources */,
C1D598BA1BB44B2000D297FE /* UIView+HoldGesture.m in Sources */,
C1D5991A1BB44B2100D297FE /* UITextView+XMLParser.m in Sources */,
19D76A8A1D265A1B006245D6 /* TZImageManager.m in Sources */,
C1D598751BB44B2000D297FE /* UIButton+BeeUIStyle.m in Sources */,
C1D599491BB44B2100D297FE /* NSObject+BeeTicker.mm in Sources */,
C1D598541BB44B2000D297FE /* Bee_UICollection.m in Sources */,
......@@ -5036,6 +5127,7 @@
C1D598F81BB44B2000D297FE /* BeeUIQuery+Offset.m in Sources */,
C1D5986E1BB44B2000D297FE /* UIViewController+UINavigationController.m in Sources */,
1912FCE31CCDECF8004CF976 /* PaymentTypeModel.m in Sources */,
19D76A8C1D265A1B006245D6 /* TZImagePickerController.m in Sources */,
C1D598B21BB44B2000D297FE /* Bee_UITableView.m in Sources */,
C19BBC051BBE85F500831290 /* VankeWeatherCell_iPhone.m in Sources */,
C10F183D1BF7ACA80065F18C /* IBTObject.m in Sources */,
......@@ -5043,6 +5135,7 @@
C1D598F41BB44B2000D297FE /* BeeUIQuery+Effects.m in Sources */,
C1D599121BB44B2000D297FE /* Bee_UITemplateParserXML.m in Sources */,
C1D598C91BB44B2000D297FE /* Bee_UIFootLoader.m in Sources */,
19D76A8D1D265A1B006245D6 /* TZPhotoPickerController.m in Sources */,
C1D5984E1BB44B2000D297FE /* BeeMessage+BeeXML.mm in Sources */,
C1D598A91BB44B2000D297FE /* Bee_UIPageViewController.m in Sources */,
C1D599851BB44B2100D297FE /* CXMLDocument_PrivateExtensions.m in Sources */,
......@@ -5072,6 +5165,7 @@
C1D58B341BB1BC9200D297FE /* main.m in Sources */,
C1D598C01BB44B2000D297FE /* UIView+Screenshot.m in Sources */,
C1D5991D1BB44B2100D297FE /* Bee_SystemConfig.mm in Sources */,
19D76AA51D266910006245D6 /* CALayer+Addtions.m in Sources */,
C1D598D51BB44B2000D297FE /* BeeUISignal+SourceView.m in Sources */,
C1D598561BB44B2000D297FE /* UIColor+BeeExtension.m in Sources */,
C10F18491BF7ACA80065F18C /* IBTUITextField.m in Sources */,
......@@ -5256,6 +5350,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 710E0C5D8A5E02D32E5C6C2D /* Pods.release.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = NO;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = NO;
......@@ -5271,10 +5366,42 @@
INFOPLIST_FILE = vanke/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-l\"AFNetworking\"",
"-l\"CocoaSecurity\"",
"-l\"CustomBadge\"",
"-l\"FMDB\"",
"-l\"IQKeyboardManager\"",
"-l\"MBProgressHUD\"",
"-l\"MJExtension\"",
"-l\"PNChart\"",
"-l\"SDWebImage\"",
"-l\"UICountingLabel\"",
"-l\"sqlite3\"",
"-framework",
"\"CoreGraphics\"",
"-framework",
"\"Foundation\"",
"-framework",
"\"ImageIO\"",
"-framework",
"\"MobileCoreServices\"",
"-framework",
"\"QuartzCore\"",
"-framework",
"\"Security\"",
"-framework",
"\"SystemConfiguration\"",
"-framework",
"\"UIKit\"",
);
PRODUCT_BUNDLE_IDENTIFIER = com.gomore.vanke;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
TARGETED_DEVICE_FAMILY = 1;
VALID_ARCHS = "arm64 armv7 armv7s";
VERSIONING_SYSTEM = "";
};
name = Release;
......@@ -5283,6 +5410,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = F0AF65C76AE6E38D28DC2D1B /* Pods.debug.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = NO;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = NO;
......@@ -5298,10 +5426,43 @@
INFOPLIST_FILE = vanke/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-l\"AFNetworking\"",
"-l\"CocoaSecurity\"",
"-l\"CustomBadge\"",
"-l\"FMDB\"",
"-l\"IQKeyboardManager\"",
"-l\"MBProgressHUD\"",
"-l\"MJExtension\"",
"-l\"PNChart\"",
"-l\"SDWebImage\"",
"-l\"UICountingLabel\"",
"-l\"sqlite3\"",
"-framework",
"\"CoreGraphics\"",
"-framework",
"\"Foundation\"",
"-framework",
"\"ImageIO\"",
"-framework",
"\"MobileCoreServices\"",
"-framework",
"\"QuartzCore\"",
"-framework",
"\"Security\"",
"-framework",
"\"SystemConfiguration\"",
"-framework",
"\"UIKit\"",
);
PRODUCT_BUNDLE_IDENTIFIER = com.gomore.vanke;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
TARGETED_DEVICE_FAMILY = 1;
VALID_ARCHS = "arm64 armv7 armv7s";
VERSIONING_SYSTEM = "";
};
name = Debug;
......
//
// CALayer+Addtions.h
// RealEstateManagement
//
// Created by Z on 16/6/24.
// Copyright © 2016年 上海勾芒信息科技. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer (Addtions)
@end
//
// CALayer+Addtions.m
// RealEstateManagement
//
// Created by Z on 16/6/24.
// Copyright © 2016年 上海勾芒信息科技. All rights reserved.
//
#import "CALayer+Addtions.h"
#import <objc/runtime.h>
@implementation CALayer (Addtions)
- (void)setBorderColorFromUI:(UIColor *)color
{
self.borderColor = color.CGColor;
// NSLog(@"%@", color);
}
@end
//
// TZAssetCell.h
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <Photos/Photos.h>
typedef enum : NSUInteger {
TZAssetCellTypePhoto = 0,
TZAssetCellTypeLivePhoto,
TZAssetCellTypeVideo,
TZAssetCellTypeAudio,
} TZAssetCellType;
@class TZAssetModel;
@interface TZAssetCell : UICollectionViewCell
@property (weak, nonatomic) UIButton *selectPhotoButton;
@property (nonatomic, strong) TZAssetModel *model;
@property (nonatomic, copy) void (^didSelectPhotoBlock)(BOOL);
@property (nonatomic, assign) TZAssetCellType type;
@property (nonatomic, copy) NSString *representedAssetIdentifier;
@property (nonatomic, assign) PHImageRequestID imageRequestID;
@end
@class TZAlbumModel;
@interface TZAlbumCell : UITableViewCell
@property (nonatomic, strong) TZAlbumModel *model;
@property (weak, nonatomic) UIButton *selectedCountButton;
@end
@interface TZAssetCameraCell : UICollectionViewCell
@property (nonatomic, strong) UIImageView *imageView;
@end
\ No newline at end of file
//
// TZAssetCell.m
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import "TZAssetCell.h"
#import "TZAssetModel.h"
#import "UIView+Layout.h"
#import "TZImageManager.h"
#import "TZImagePickerController.h"
@interface TZAssetCell ()
@property (weak, nonatomic) UIImageView *imageView; // The photo / 照片
@property (weak, nonatomic) UIImageView *selectImageView;
@property (weak, nonatomic) UIView *bottomView;
@property (weak, nonatomic) UILabel *timeLength;
@property (nonatomic, weak) UIImageView *viewImgView;
@end
@implementation TZAssetCell
// Now we use code to create subViews for improve performance
// 现在我们用代码来创建TZAssetCell和TZAlbumCell的子控件,以提高性能
/*
- (void)awakeFromNib {
self.timeLength.font = [UIFont boldSystemFontOfSize:11];
}
*/
- (void)setModel:(TZAssetModel *)model {
_model = model;
if (iOS8Later) {
self.representedAssetIdentifier = [[TZImageManager manager] getAssetIdentifier:model.asset];
}
PHImageRequestID 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 (!iOS8Later) {
self.imageView.image = photo; return;
}
if ([self.representedAssetIdentifier isEqualToString:[[TZImageManager manager] getAssetIdentifier:model.asset]]) {
self.imageView.image = photo;
} else {
// NSLog(@"this cell is showing other asset");
[[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID];
}
if (!isDegraded) {
self.imageRequestID = 0;
}
}];
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 ? [UIImage imageNamedFromMyBundle:@"photo_sel_photoPickerVc.png"] : [UIImage imageNamedFromMyBundle:@"photo_def_photoPickerVc.png"];
self.type = TZAssetCellTypePhoto;
if (model.type == TZAssetModelMediaTypeLivePhoto) self.type = TZAssetCellTypeLivePhoto;
else if (model.type == TZAssetModelMediaTypeAudio) self.type = TZAssetCellTypeAudio;
else if (model.type == TZAssetModelMediaTypeVideo) {
self.type = TZAssetCellTypeVideo;
self.timeLength.text = model.timeLength;
}
}
- (void)setType:(TZAssetCellType)type {
_type = type;
if (type == TZAssetCellTypePhoto || type == TZAssetCellTypeLivePhoto) {
_selectImageView.hidden = NO;
_selectPhotoButton.hidden = NO;
_bottomView.hidden = YES;
} else {
_selectImageView.hidden = YES;
_selectPhotoButton.hidden = YES;
_bottomView.hidden = NO;
}
}
- (void)selectPhotoButtonClick:(UIButton *)sender {
if (self.didSelectPhotoBlock) {
self.didSelectPhotoBlock(sender.isSelected);
}
self.selectImageView.image = sender.isSelected ? [UIImage imageNamedFromMyBundle:@"photo_sel_photoPickerVc.png"] : [UIImage imageNamedFromMyBundle:@"photo_def_photoPickerVc.png"];
if (sender.isSelected) {
[UIView showOscillatoryAnimationWithLayer:_selectImageView.layer type:TZOscillatoryAnimationToBigger];
}
}
#pragma mark - Lazy load
- (UIButton *)selectPhotoButton {
if (_selectImageView == nil) {
UIButton *selectImageView = [[UIButton alloc] init];
selectImageView.frame = CGRectMake(self.tz_width - 44, 0, 44, 44);
[selectImageView addTarget:self action:@selector(selectPhotoButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:selectImageView];
_selectPhotoButton = selectImageView;
}
return _selectPhotoButton;
}
- (UIImageView *)imageView {
if (_imageView == nil) {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(0, 0, self.tz_width, self.tz_height);
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
[self.contentView addSubview:imageView];
_imageView = imageView;
[self.contentView bringSubviewToFront:_selectImageView];
[self.contentView bringSubviewToFront:_bottomView];
}
return _imageView;
}
- (UIImageView *)selectImageView {
if (_selectImageView == nil) {
UIImageView *selectImageView = [[UIImageView alloc] init];
selectImageView.frame = CGRectMake(self.tz_width - 27, 0, 27, 27);
[self.contentView addSubview:selectImageView];
_selectImageView = selectImageView;
}
return _selectImageView;
}
- (UIView *)bottomView {
if (_bottomView == nil) {
UIView *bottomView = [[UIView alloc] init];
bottomView.frame = CGRectMake(0, self.tz_height - 17, self.tz_width, 17);
bottomView.backgroundColor = [UIColor blackColor];
bottomView.alpha = 0.8;
[self.contentView addSubview:bottomView];
_bottomView = bottomView;
}
return _bottomView;
}
- (UIImageView *)viewImgView {
if (_viewImgView == nil) {
UIImageView *viewImgView = [[UIImageView alloc] init];
viewImgView.frame = CGRectMake(8, 0, 17, 17);
[viewImgView setImage:[UIImage imageNamedFromMyBundle:@"VideoSendIcon.png"]];
[self.bottomView addSubview:viewImgView];
_viewImgView = viewImgView;
}
return _viewImgView;
}
- (UILabel *)timeLength {
if (_timeLength == nil) {
UILabel *timeLength = [[UILabel alloc] init];
timeLength.font = [UIFont boldSystemFontOfSize:11];
timeLength.frame = CGRectMake(self.viewImgView.tz_right, 0, self.tz_width - self.viewImgView.tz_right - 5, 17);
timeLength.textColor = [UIColor whiteColor];
timeLength.textAlignment = NSTextAlignmentRight;
[self.bottomView addSubview:timeLength];
_timeLength = timeLength;
}
return _timeLength;
}
@end
@interface TZAlbumCell ()
@property (weak, nonatomic) UIImageView *posterImageView;
@property (weak, nonatomic) UILabel *titleLable;
@property (weak, nonatomic) UIImageView *arrowImageView;
@end
@implementation TZAlbumCell
/*
- (void)awakeFromNib {
self.posterImageView.clipsToBounds = YES;
}
*/
- (void)setModel:(TZAlbumModel *)model {
_model = model;
NSMutableAttributedString *nameString = [[NSMutableAttributedString alloc] initWithString:model.name attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor blackColor]}];
NSAttributedString *countString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" (%zd)",model.count] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor lightGrayColor]}];
[nameString appendAttributedString:countString];
self.titleLable.attributedText = nameString;
[[TZImageManager manager] getPostImageWithAlbumModel:model completion:^(UIImage *postImage) {
self.posterImageView.image = postImage;
}];
if (model.selectedCount) {
self.selectedCountButton.hidden = NO;
[self.selectedCountButton setTitle:[NSString stringWithFormat:@"%zd",model.selectedCount] forState:UIControlStateNormal];
} else {
self.selectedCountButton.hidden = YES;
}
}
/// For fitting iOS6
- (void)layoutSubviews {
if (iOS7Later) [super layoutSubviews];
_selectedCountButton.frame = CGRectMake(self.tz_width - 24 - 30, 23, 24, 24);
}
- (void)layoutSublayersOfLayer:(CALayer *)layer {
if (iOS7Later) [super layoutSublayersOfLayer:layer];
}
#pragma mark - Lazy load
- (UIImageView *)posterImageView {
if (_arrowImageView == nil) {
UIImageView *posterImageView = [[UIImageView alloc] init];
posterImageView.contentMode = UIViewContentModeScaleAspectFill;
posterImageView.clipsToBounds = YES;
posterImageView.frame = CGRectMake(0, 0, 70, 70);
[self.contentView addSubview:posterImageView];
_posterImageView = posterImageView;
}
return _posterImageView;
}
- (UILabel *)titleLable {
if (_titleLable == nil) {
UILabel *titleLable = [[UILabel alloc] init];
titleLable.font = [UIFont boldSystemFontOfSize:17];
titleLable.frame = CGRectMake(80, 0, self.tz_width - 80 - 50, self.tz_height);
titleLable.textColor = [UIColor blackColor];
titleLable.textAlignment = NSTextAlignmentLeft;
[self.contentView addSubview:titleLable];
_titleLable = titleLable;
}
return _titleLable;
}
- (UIImageView *)arrowImageView {
if (_arrowImageView == nil) {
UIImageView *arrowImageView = [[UIImageView alloc] init];
CGFloat arrowWH = 15;
arrowImageView.frame = CGRectMake(self.tz_width - arrowWH - 12, 28, arrowWH, arrowWH);
[arrowImageView setImage:[UIImage imageNamedFromMyBundle:@"TableViewArrow.png"]];
[self.contentView addSubview:arrowImageView];
_arrowImageView = arrowImageView;
}
return _arrowImageView;
}
- (UIButton *)selectedCountButton {
if (_selectedCountButton == nil) {
UIButton *selectedCountButton = [[UIButton alloc] init];
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 addSubview:_imageView];
self.clipsToBounds = YES;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
_imageView.frame = self.bounds;
}
@end
//
// TZAssetModel.h
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum : NSUInteger {
TZAssetModelMediaTypePhoto = 0,
TZAssetModelMediaTypeLivePhoto,
TZAssetModelMediaTypeVideo,
TZAssetModelMediaTypeAudio
} TZAssetModelMediaType;
@class PHAsset;
@interface TZAssetModel : NSObject
@property (nonatomic, strong) id asset; ///< PHAsset or ALAsset
@property (nonatomic, assign) BOOL isSelected; ///< The select status of a photo, default is No
@property (nonatomic, assign) TZAssetModelMediaType type;
@property (nonatomic, copy) NSString *timeLength;
/// Init a photo dataModel With a asset
/// 用一个PHAsset/ALAsset实例,初始化一个照片模型
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type;
+ (instancetype)modelWithAsset:(id)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) id result; ///< PHFetchResult<PHAsset> or ALAssetsGroup<ALAsset>
@property (nonatomic, strong) NSArray *models;
@property (nonatomic, strong) NSArray *selectedModels;
@property (nonatomic, assign) NSUInteger selectedCount;
@end
\ No newline at end of file
//
// TZAssetModel.m
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import "TZAssetModel.h"
#import "TZImageManager.h"
@implementation TZAssetModel
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type{
TZAssetModel *model = [[TZAssetModel alloc] init];
model.asset = asset;
model.isSelected = NO;
model.type = type;
return model;
}
+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength {
TZAssetModel *model = [self modelWithAsset:asset type:type];
model.timeLength = timeLength;
return model;
}
@end
@implementation TZAlbumModel
- (void)setResult:(id)result {
_result = result;
BOOL allowPickingImage = [[[NSUserDefaults standardUserDefaults] objectForKey:@"tz_allowPickingImage"] isEqualToString:@"1"];
BOOL allowPickingVideo = [[[NSUserDefaults standardUserDefaults] objectForKey:@"tz_allowPickingVideo"] isEqualToString:@"1"];
[[TZImageManager manager] getAssetsFromFetchResult:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage completion:^(NSArray<TZAssetModel *> *models) {
_models = models;
if (_selectedModels) {
[self checkSelectedModels];
}
}];
}
- (void)setSelectedModels:(NSArray *)selectedModels {
_selectedModels = selectedModels;
if (_models) {
[self checkSelectedModels];
}
}
- (void)checkSelectedModels {
self.selectedCount = 0;
NSMutableArray *selectedAssets = [NSMutableArray array];
for (TZAssetModel *model in _selectedModels) {
[selectedAssets addObject:model.asset];
}
for (TZAssetModel *model in _models) {
if ([[TZImageManager manager] isAssetsArray:selectedAssets containAsset:model.asset]) {
self.selectedCount ++;
}
}
}
@end
\ No newline at end of file
//
// TZImageManager.h
// TZImagePickerController
//
// Created by 谭真 on 16/1/4.
// Copyright © 2016年 谭真. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <Photos/Photos.h>
@class TZAlbumModel,TZAssetModel;
@interface TZImageManager : NSObject
@property (nonatomic, strong) PHCachingImageManager *cachingImageManager;
+ (instancetype)manager;
@property (nonatomic, assign) BOOL shouldFixOrientation;
/// Default is 600px / 默认600像素宽
@property (nonatomic, assign) CGFloat photoPreviewMaxWidth;
/// Sort photos ascending by modificationDate,Default is YES
/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个
@property (nonatomic, assign) BOOL sortAscendingByModificationDate;
/// Return YES if Authorized 返回YES如果得到了授权
- (BOOL)authorizationStatusAuthorized;
/// Get Album 获得相册/相册数组
- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAlbumModel *model))completion;
- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAlbumModel *> *models))completion;
/// Get Assets 获得Asset数组
- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *model))completion;
/// Get photo 获得照片
- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *postImage))completion;
- (PHImageRequestID)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (PHImageRequestID)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion;
/// Save photo 保存照片
- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)())completion;
/// Get video 获得视频
- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem * playerItem, NSDictionary * info))completion;
/// Export video 导出视频
- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion;
/// Get photo bytes 获得一组照片的大小
- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion;
/// Judge is a assets array contain the asset 判断一个assets数组是否包含这个asset
- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset;
- (NSString *)getAssetIdentifier:(id)asset;
@end
//
// TZImageManager.m
// TZImagePickerController
//
// Created by 谭真 on 16/1/4.
// Copyright © 2016年 谭真. All rights reserved.
//
#import "TZImageManager.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import "TZAssetModel.h"
#import "TZImagePickerController.h"
@interface TZImageManager ()
@property (nonatomic, strong) ALAssetsLibrary *assetLibrary;
@end
@implementation TZImageManager
static CGSize AssetGridThumbnailSize;
static CGFloat TZScreenWidth;
static CGFloat TZScreenScale;
+ (instancetype)manager {
static TZImageManager *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
manager.cachingImageManager = [[PHCachingImageManager alloc] init];
manager.cachingImageManager.allowsCachingHighQualityImages = NO;
TZScreenWidth = [UIScreen mainScreen].bounds.size.width;
// 测试发现,如果scale在plus真机上取到3.0,内存会增大特别多。故这里写死成2.0
TZScreenScale = 2.0;
if (TZScreenWidth > 700) {
TZScreenScale = 1.5;
}
CGFloat margin = 4;
CGFloat itemWH = (TZScreenWidth - 2 * margin - 4) / 4 - margin;
AssetGridThumbnailSize = CGSizeMake(itemWH * TZScreenScale, itemWH * TZScreenScale);
});
return manager;
}
- (ALAssetsLibrary *)assetLibrary {
if (_assetLibrary == nil) _assetLibrary = [[ALAssetsLibrary alloc] init];
return _assetLibrary;
}
/// Return YES if Authorized 返回YES如果得到了授权
- (BOOL)authorizationStatusAuthorized {
if (iOS8Later) {
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized) return YES;
} else {
if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusAuthorized) return YES;
}
return NO;
}
#pragma mark - Get Album
/// Get Album 获得相册/相册数组
- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAlbumModel *))completion{
__block TZAlbumModel *model;
if (iOS8Later) {
PHFetchOptions *option = [[PHFetchOptions alloc] init];
if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
PHAssetMediaTypeVideo];
// option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]];
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];
for (PHAssetCollection *collection in smartAlbums) {
if ([collection.localizedTitle isEqualToString:@"Camera Roll"] || [collection.localizedTitle isEqualToString:@"相机胶卷"] || [collection.localizedTitle isEqualToString:@"所有照片"] || [collection.localizedTitle isEqualToString:@"All Photos"]) {
PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
model = [self modelWithResult:fetchResult name:collection.localizedTitle];
if (completion) completion(model);
break;
}
}
} else {
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if ([group numberOfAssets] < 1) return;
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([name isEqualToString:@"Camera Roll"] || [name isEqualToString:@"相机胶卷"] || [name isEqualToString:@"所有照片"] || [name isEqualToString:@"All Photos"]) {
model = [self modelWithResult:group name:name];
if (completion) completion(model);
*stop = YES;
}
} failureBlock:nil];
}
}
- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAlbumModel *> *))completion{
NSMutableArray *albumArr = [NSMutableArray array];
if (iOS8Later) {
PHFetchOptions *option = [[PHFetchOptions alloc] init];
if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
PHAssetMediaTypeVideo];
// option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]];
PHAssetCollectionSubtype smartAlbumSubtype = PHAssetCollectionSubtypeSmartAlbumUserLibrary | PHAssetCollectionSubtypeSmartAlbumRecentlyAdded | PHAssetCollectionSubtypeSmartAlbumVideos;
// For iOS 9, We need to show ScreenShots Album && SelfPortraits Album
if (iOS9Later) {
smartAlbumSubtype = PHAssetCollectionSubtypeSmartAlbumUserLibrary | PHAssetCollectionSubtypeSmartAlbumRecentlyAdded | PHAssetCollectionSubtypeSmartAlbumScreenshots | PHAssetCollectionSubtypeSmartAlbumSelfPortraits | PHAssetCollectionSubtypeSmartAlbumVideos;
}
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:smartAlbumSubtype options:nil];
for (PHAssetCollection *collection in smartAlbums) {
PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
if (fetchResult.count < 1) continue;
if ([collection.localizedTitle containsString:@"Deleted"] || [collection.localizedTitle isEqualToString:@"最近删除"]) continue;
if ([collection.localizedTitle isEqualToString:@"Camera Roll"] || [collection.localizedTitle isEqualToString:@"相机胶卷"]) {
[albumArr insertObject:[self modelWithResult:fetchResult name:collection.localizedTitle] atIndex:0];
} else {
[albumArr addObject:[self modelWithResult:fetchResult name:collection.localizedTitle]];
}
}
PHFetchResult *albums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular | PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil];
for (PHAssetCollection *collection in albums) {
PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
if (fetchResult.count < 1) continue;
if ([collection.localizedTitle isEqualToString:@"My Photo Stream"] || [collection.localizedTitle isEqualToString:@"我的照片流"]) {
[albumArr insertObject:[self modelWithResult:fetchResult name:collection.localizedTitle] atIndex:1];
} else {
[albumArr addObject:[self modelWithResult:fetchResult name:collection.localizedTitle]];
}
}
if (completion && albumArr.count > 0) completion(albumArr);
} else {
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group == nil) {
if (completion && albumArr.count > 0) completion(albumArr);
}
if ([group numberOfAssets] < 1) return;
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([name isEqualToString:@"Camera Roll"] || [name isEqualToString:@"相机胶卷"]) {
[albumArr insertObject:[self modelWithResult:group name:name] atIndex:0];
} else if ([name isEqualToString:@"My Photo Stream"] || [name isEqualToString:@"我的照片流"]) {
[albumArr insertObject:[self modelWithResult:group name:name] atIndex:1];
} else {
[albumArr addObject:[self modelWithResult:group name:name]];
}
} failureBlock:nil];
}
}
#pragma mark - Get Assets
/// Get Assets 获得照片数组
- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *))completion {
NSMutableArray *photoArr = [NSMutableArray array];
if ([result isKindOfClass:[PHFetchResult class]]) {
PHFetchResult *fetchResult = (PHFetchResult *)result;
[fetchResult enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PHAsset *asset = (PHAsset *)obj;
TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
if (asset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo;
else if (asset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio;
else if (asset.mediaType == PHAssetMediaTypeImage) {
if (iOS9_1Later) {
// if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive) type = TZAssetModelMediaTypeLivePhoto;
}
}
if (!allowPickingVideo && type == TZAssetModelMediaTypeVideo) return;
if (!allowPickingImage && type == TZAssetModelMediaTypePhoto) return;
NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",asset.duration] : @"";
timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
[photoArr addObject:[TZAssetModel modelWithAsset:asset type:type timeLength:timeLength]];
}];
if (completion) completion(photoArr);
} else if ([result isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = (ALAssetsGroup *)result;
if (allowPickingImage && allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allAssets]];
} else if (allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allVideos]];
} else if (allowPickingImage) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
}
ALAssetsGroupEnumerationResultsBlock resultBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result == nil) {
if (completion) completion(photoArr);
}
TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
if (!allowPickingVideo){
[photoArr addObject:[TZAssetModel modelWithAsset:result type:type]];
return;
}
/// Allow picking video
if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
type = TZAssetModelMediaTypeVideo;
NSTimeInterval duration = [[result valueForProperty:ALAssetPropertyDuration] integerValue];
NSString *timeLength = [NSString stringWithFormat:@"%0.0f",duration];
timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
[photoArr addObject:[TZAssetModel modelWithAsset:result type:type timeLength:timeLength]];
} else {
[photoArr addObject:[TZAssetModel modelWithAsset:result type:type]];
}
};
if (self.sortAscendingByModificationDate) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (resultBlock) { resultBlock(result,index,stop); }
}];
} else {
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (resultBlock) { resultBlock(result,index,stop); }
}];
}
}
}
/// Get asset at index 获得下标为index的单个照片
- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *))completion {
if ([result isKindOfClass:[PHFetchResult class]]) {
PHFetchResult *fetchResult = (PHFetchResult *)result;
PHAsset *asset = fetchResult[index];
TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
if (asset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo;
else if (asset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio;
else if (asset.mediaType == PHAssetMediaTypeImage) {
if (iOS9_1Later) {
// if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive) type = TZAssetModelMediaTypeLivePhoto;
}
}
NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",asset.duration] : @"";
timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
if (completion) completion(model);
} else if ([result isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = (ALAssetsGroup *)result;
if (allowPickingImage && allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allAssets]];
} else if (allowPickingVideo) {
[group setAssetsFilter:[ALAssetsFilter allVideos]];
} else if (allowPickingImage) {
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
}
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
[group enumerateAssetsAtIndexes:indexSet options:NSEnumerationConcurrent usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
TZAssetModel *model;
TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
if (!allowPickingVideo){
model = [TZAssetModel modelWithAsset:result type:type];
if (completion) completion(model);
return;
}
/// Allow picking video
if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
type = TZAssetModelMediaTypeVideo;
NSTimeInterval duration = [[result valueForProperty:ALAssetPropertyDuration] integerValue];
NSString *timeLength = [NSString stringWithFormat:@"%0.0f",duration];
timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
model = [TZAssetModel modelWithAsset:result type:type timeLength:timeLength];
} else {
model = [TZAssetModel modelWithAsset:result type:type];
}
if (completion) completion(model);
}];
}
}
- (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 {
__block NSInteger dataLength = 0;
__block NSInteger assetCount = 0;
for (NSInteger i = 0; i < photos.count; i++) {
TZAssetModel *model = photos[i];
if ([model.asset isKindOfClass:[PHAsset class]]) {
[[PHImageManager defaultManager] requestImageDataForAsset:model.asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
if (model.type != TZAssetModelMediaTypeVideo) dataLength += imageData.length;
assetCount ++;
if (assetCount >= photos.count) {
NSString *bytes = [self getBytesFromDataLength:dataLength];
if (completion) completion(bytes);
}
}];
} else if ([model.asset isKindOfClass:[ALAsset class]]) {
ALAssetRepresentation *representation = [model.asset defaultRepresentation];
if (model.type != TZAssetModelMediaTypeVideo) dataLength += (NSInteger)representation.size;
if (i >= photos.count - 1) {
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:(id)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {
CGFloat fullScreenWidth = TZScreenWidth;
if (fullScreenWidth > _photoPreviewMaxWidth) {
fullScreenWidth = _photoPreviewMaxWidth;
}
return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion];
}
- (PHImageRequestID)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
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;
CGFloat pixelHeight = photoWidth / aspectRatio;
imageSize = CGSizeMake(pixelWidth, pixelHeight);
}
// 修复获取图片时出现的瞬间内存过高问题
// 下面两行代码,来自hsjcom,他的github是:https://github.com/hsjcom 表示感谢
PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
option.resizeMode = PHImageRequestOptionsResizeModeFast;
PHImageRequestID imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
if (downloadFinined && result) {
result = [self fixOrientation:result];
if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
}
// Download image from iCloud / 从iCloud下载图片
if ([info objectForKey:PHImageResultIsInCloudKey] && !result) {
PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
option.networkAccessAllowed = YES;
option.resizeMode = PHImageRequestOptionsResizeModeFast;
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:option resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
resultImage = [self scaleImage:resultImage toSize:imageSize];
if (resultImage) {
resultImage = [self fixOrientation:resultImage];
if (completion) completion(resultImage,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
}
}];
}
}];
return imageRequestID;
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
dispatch_async(dispatch_get_global_queue(0,0), ^{
CGImageRef thumbnailImageRef = alAsset.thumbnail;
UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnailImageRef scale:2.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(thumbnailImage,nil,YES);
if (photoWidth == TZScreenWidth || photoWidth == _photoPreviewMaxWidth) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(fullScrennImage,nil,NO);
});
});
}
});
});
}
return 0;
}
/// Get postImage / 获取封面图
- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *))completion {
if (iOS8Later) {
id asset = [model.result lastObject];
if (!self.sortAscendingByModificationDate) {
asset = [model.result firstObject];
}
[[TZImageManager manager] getPhotoWithAsset:asset photoWidth:80 completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
if (completion) completion(photo);
}];
} else {
ALAssetsGroup *group = model.result;
UIImage *postImage = [UIImage imageWithCGImage:group.posterImage];
if (completion) completion(postImage);
}
}
/// Get Original Photo / 获取原图
- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
option.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
if (downloadFinined && result) {
result = [self fixOrientation:result];
if (completion) completion(result,info);
}
}];
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
dispatch_async(dispatch_get_global_queue(0,0), ^{
CGImageRef originalImageRef = [assetRep fullResolutionImage];
UIImage *originalImage = [UIImage imageWithCGImage:originalImageRef scale:1.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) completion(originalImage,nil);
});
});
}
}
#pragma mark - Save photo
- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)())completion {
NSData *data = UIImageJPEGRepresentation(image, 0.9);
if (iOS9Later) { // 这里有坑... iOS8系统下这个方法保存图片会失败
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
options.shouldMoveFile = YES;
[[PHAssetCreationRequest creationRequestForAsset] addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
dispatch_sync(dispatch_get_main_queue(), ^{
if (success && completion) {
completion();
} else if (error) {
NSLog(@"保存照片出错:%@",error.localizedDescription);
}
});
}];
} else {
[self.assetLibrary writeImageToSavedPhotosAlbum:image.CGImage orientation:[self orientationFromImage:image] completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"保存图片失败:%@",error.localizedDescription);
} else {
if (completion) {
completion();
}
}
}];
}
}
#pragma mark - Get Video
/// Get Video / 获取视频
- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem * _Nullable, NSDictionary * _Nullable))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
[[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:nil resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
if (completion) completion(playerItem,info);
}];
} else if ([asset isKindOfClass:[ALAsset class]]) {
ALAsset *alAsset = (ALAsset *)asset;
ALAssetRepresentation *defaultRepresentation = [alAsset defaultRepresentation];
NSString *uti = [defaultRepresentation UTI];
NSURL *videoURL = [[asset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:videoURL];
if (completion && playerItem) completion(playerItem,nil);
}
}
#pragma mark - Export video
/// Export Video / 导出视频,暂仅仅支持iOS8.0+
- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionOriginal;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
// NSLog(@"Info:\n%@",info);
AVURLAsset* myAsset = (AVURLAsset*)avasset;
// NSLog(@"AVAsset URL: %@",myAsset.URL);
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:myAsset];
// NSLog(@"%@",compatiblePresets);
if ([compatiblePresets containsObject:AVAssetExportPresetHighestQuality]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:myAsset presetName:AVAssetExportPresetMediumQuality];
NSDateFormatter *formater = [[NSDateFormatter alloc] init];
[formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
NSLog(@"video outputPath = %@",outputPath);
exportSession.outputURL = [NSURL fileURLWithPath:outputPath];
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
switch (exportSession.status) {
case AVAssetExportSessionStatusUnknown:
NSLog(@"AVAssetExportSessionStatusUnknown"); break;
case AVAssetExportSessionStatusWaiting:
NSLog(@"AVAssetExportSessionStatusWaiting"); break;
case AVAssetExportSessionStatusExporting:
NSLog(@"AVAssetExportSessionStatusExporting"); break;
case AVAssetExportSessionStatusCompleted:
NSLog(@"AVAssetExportSessionStatusCompleted");
if (completion) {
completion(outputPath);
}
break;
case AVAssetExportSessionStatusFailed:
NSLog(@"AVAssetExportSessionStatusFailed"); break;
default: break;
}
}];
}
}];
} else {
NSLog(@"iOS8以前的系统,导出视频代码暂未更新...");
}
}
/// Judge is a assets array contain the asset 判断一个assets数组是否包含这个asset
- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset {
if (iOS8Later) {
return [assets containsObject:asset];
} else {
NSMutableArray *selectedAssetUrls = [NSMutableArray array];
for (ALAsset *asset_item in assets) {
[selectedAssetUrls addObject:[asset_item valueForProperty:ALAssetPropertyURLs]];
}
return [selectedAssetUrls containsObject:[asset valueForProperty:ALAssetPropertyURLs]];
}
}
- (NSString *)getAssetIdentifier:(id)asset {
if (iOS8Later) {
PHAsset *phAsset = (PHAsset *)asset;
return phAsset.localIdentifier;
} else {
ALAsset *alAsset = (ALAsset *)asset;
NSURL *assetUrl = [alAsset valueForProperty:ALAssetPropertyAssetURL];
return assetUrl.absoluteString;
}
}
#pragma mark - Private Method
- (TZAlbumModel *)modelWithResult:(id)result name:(NSString *)name{
TZAlbumModel *model = [[TZAlbumModel alloc] init];
model.result = result;
model.name = [self getNewAlbumName:name];
if ([result isKindOfClass:[PHFetchResult class]]) {
PHFetchResult *fetchResult = (PHFetchResult *)result;
model.count = fetchResult.count;
} else if ([result isKindOfClass:[ALAssetsGroup class]]) {
ALAssetsGroup *group = (ALAssetsGroup *)result;
model.count = [group numberOfAssets];
}
return model;
}
- (NSString *)getNewAlbumName:(NSString *)name {
if (iOS8Later) {
NSString *newName;
if ([name rangeOfString:@"Roll"].location != NSNotFound) newName = @"相机胶卷";
else if ([name rangeOfString:@"Stream"].location != NSNotFound) newName = @"我的照片流";
else if ([name rangeOfString:@"Added"].location != NSNotFound) newName = @"最近添加";
else if ([name rangeOfString:@"Selfies"].location != NSNotFound) newName = @"自拍";
else if ([name rangeOfString:@"shots"].location != NSNotFound) newName = @"截屏";
else if ([name rangeOfString:@"Videos"].location != NSNotFound) newName = @"视频";
else if ([name rangeOfString:@"Panoramas"].location != NSNotFound) newName = @"全景照片";
else if ([name rangeOfString:@"Favorites"].location != NSNotFound) newName = @"个人收藏";
else newName = name;
return newName;
} else {
return name;
}
}
- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size {
if (image.size.width > size.width) {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
} else {
return image;
}
}
- (ALAssetOrientation)orientationFromImage:(UIImage *)image {
NSInteger orientation = image.imageOrientation;
return orientation;
}
- (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;
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
</dict>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="grQ-4c-o22" customClass="TZAlbumCell">
<rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="MN9-Rx-foD">
<rect key="frame" x="0.0" y="0.0" width="70" height="70"/>
<constraints>
<constraint firstAttribute="width" constant="70" id="9QL-fc-DfO"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mrv-sA-Nuw">
<rect key="frame" x="80" y="0.0" width="190" height="70"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="TableViewArrow" translatesAutoresizingMaskIntoConstraints="NO" id="Nj8-PM-Kqf">
<rect key="frame" x="293" y="28" width="15" height="15"/>
<constraints>
<constraint firstAttribute="width" constant="15" id="HiN-sC-FNK"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="Mrv-sA-Nuw" firstAttribute="leading" secondItem="MN9-Rx-foD" secondAttribute="trailing" constant="10" id="1QF-Ux-8Eq"/>
<constraint firstAttribute="trailing" secondItem="Mrv-sA-Nuw" secondAttribute="trailing" constant="50" id="Hdc-BO-uDe"/>
<constraint firstAttribute="trailing" secondItem="Nj8-PM-Kqf" secondAttribute="trailing" constant="12" id="NDX-ya-7lu"/>
<constraint firstItem="MN9-Rx-foD" firstAttribute="leading" secondItem="grQ-4c-o22" secondAttribute="leading" id="Qgb-hx-Zng"/>
<constraint firstItem="MN9-Rx-foD" firstAttribute="top" secondItem="grQ-4c-o22" secondAttribute="top" id="ZZm-Sk-o83"/>
<constraint firstAttribute="bottom" secondItem="Mrv-sA-Nuw" secondAttribute="bottom" id="ca9-ki-vgD"/>
<constraint firstAttribute="bottom" secondItem="Nj8-PM-Kqf" secondAttribute="bottom" constant="27" id="cry-id-f46"/>
<constraint firstItem="Mrv-sA-Nuw" firstAttribute="top" secondItem="grQ-4c-o22" secondAttribute="top" id="gZb-1z-CPx"/>
<constraint firstItem="Nj8-PM-Kqf" firstAttribute="top" secondItem="grQ-4c-o22" secondAttribute="top" constant="28" id="rdB-Pt-8ly"/>
<constraint firstAttribute="bottom" secondItem="MN9-Rx-foD" secondAttribute="bottom" id="vxW-5h-txe"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="posterImageView" destination="MN9-Rx-foD" id="tOI-0s-GLe"/>
<outlet property="titleLable" destination="Mrv-sA-Nuw" id="Khi-UM-B6w"/>
</connections>
<point key="canvasLocation" x="584" y="432"/>
</view>
</objects>
<resources>
<image name="TableViewArrow" width="27" height="27"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="TZAssetCell">
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Yy8-bS-MRb">
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
</imageView>
<button opaque="NO" contentMode="topRight" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dNW-bU-KEf">
<rect key="frame" x="36" y="0.0" width="44" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="35a-xB-9kD"/>
<constraint firstAttribute="width" constant="44" id="c1d-za-0ro"/>
</constraints>
<connections>
<action selector="selectPhotoButtonClick:" destination="gTV-IL-0wX" eventType="touchUpInside" id="XWB-QX-A3P"/>
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="photo_def_photoPickerVc@2x" translatesAutoresizingMaskIntoConstraints="NO" id="ova-UI-tV1">
<rect key="frame" x="53" y="0.0" width="27" height="27"/>
<constraints>
<constraint firstAttribute="height" constant="27" id="QwD-vG-feB"/>
<constraint firstAttribute="width" constant="27" id="nLi-1g-3Sr"/>
</constraints>
</imageView>
<view alpha="0.80000000000000004" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a4Q-ox-UyB" userLabel="VideoView">
<rect key="frame" x="0.0" y="63" width="80" height="17"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="VideoSendIcon" translatesAutoresizingMaskIntoConstraints="NO" id="N0z-qh-hcG">
<rect key="frame" x="8" y="0.0" width="17" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="17" id="1p5-vb-QAu"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:12" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BXd-4T-A1o">
<rect key="frame" x="25" y="0.0" width="49" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="17" id="C2G-yW-u1e"/>
<constraint firstAttribute="trailing" secondItem="BXd-4T-A1o" secondAttribute="trailing" constant="6" id="ET8-ta-Vkb"/>
<constraint firstItem="BXd-4T-A1o" firstAttribute="top" secondItem="a4Q-ox-UyB" secondAttribute="top" id="Uks-Bh-Vdg"/>
<constraint firstAttribute="bottom" secondItem="BXd-4T-A1o" secondAttribute="bottom" id="Uvh-dT-9bi"/>
<constraint firstItem="BXd-4T-A1o" firstAttribute="leading" secondItem="N0z-qh-hcG" secondAttribute="trailing" id="cHE-ea-FX4"/>
<constraint firstItem="N0z-qh-hcG" firstAttribute="top" secondItem="a4Q-ox-UyB" secondAttribute="top" id="dHJ-vE-Lsl"/>
<constraint firstItem="N0z-qh-hcG" firstAttribute="leading" secondItem="a4Q-ox-UyB" secondAttribute="leading" constant="8" id="iq8-Yc-XwI"/>
<constraint firstAttribute="bottom" secondItem="N0z-qh-hcG" secondAttribute="bottom" id="nr0-UX-ihC"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<constraints>
<constraint firstAttribute="trailing" secondItem="a4Q-ox-UyB" secondAttribute="trailing" id="4hT-aw-TYf"/>
<constraint firstAttribute="trailing" secondItem="Yy8-bS-MRb" secondAttribute="trailing" id="5Gq-So-iWs"/>
<constraint firstAttribute="trailing" secondItem="ova-UI-tV1" secondAttribute="trailing" id="GRy-ue-4Qr"/>
<constraint firstItem="ova-UI-tV1" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="Glw-Yv-tQT"/>
<constraint firstAttribute="bottom" secondItem="Yy8-bS-MRb" secondAttribute="bottom" id="Gsd-C1-gkC"/>
<constraint firstItem="Yy8-bS-MRb" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="Iv6-lu-ZGo"/>
<constraint firstItem="a4Q-ox-UyB" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="OZ3-n0-vkk"/>
<constraint firstAttribute="trailing" secondItem="dNW-bU-KEf" secondAttribute="trailing" id="Ofl-9X-gij"/>
<constraint firstAttribute="bottom" secondItem="a4Q-ox-UyB" secondAttribute="bottom" id="X3A-bD-wef"/>
<constraint firstItem="dNW-bU-KEf" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="epf-0O-UJg"/>
<constraint firstItem="Yy8-bS-MRb" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="s7f-8d-u0B"/>
</constraints>
<connections>
<outlet property="bottomView" destination="a4Q-ox-UyB" id="3k1-bw-ZPW"/>
<outlet property="imageView" destination="Yy8-bS-MRb" id="q1a-cl-0zn"/>
<outlet property="selectImageView" destination="ova-UI-tV1" id="xXa-XQ-rUc"/>
<outlet property="selectPhotoButton" destination="dNW-bU-KEf" id="vDo-uv-cp6"/>
<outlet property="timeLength" destination="BXd-4T-A1o" id="dbx-Cf-g5W"/>
</connections>
</collectionViewCell>
</objects>
<resources>
<image name="VideoSendIcon" width="27" height="27"/>
<image name="photo_def_photoPickerVc@2x" width="27" height="27"/>
</resources>
</document>
//
// TZImagePickerController.h
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
// version 1.5.0
/*
经过测试,比起xib的方式,把TZAssetCell改用纯代码的方式来写,滑动帧数明显提高了(约提高10帧左右)
最初发现这个问题并修复的是@小鱼周凌宇同学,她的博客地址: http://zhoulingyu.com/
表示感谢~
原来xib确实会导致性能问题啊...大家也要注意了...
*/
#import <UIKit/UIKit.h>
#import "TZAssetModel.h"
#define iOS7Later ([UIDevice currentDevice].systemVersion.floatValue >= 7.0f)
#define iOS8Later ([UIDevice currentDevice].systemVersion.floatValue >= 8.0f)
#define iOS9Later ([UIDevice currentDevice].systemVersion.floatValue >= 9.0f)
#define iOS9_1Later ([UIDevice currentDevice].systemVersion.floatValue >= 9.1f)
@protocol TZImagePickerControllerDelegate;
@interface TZImagePickerController : UINavigationController
/// Use this init method / 用这个初始化方法
- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id<TZImagePickerControllerDelegate>)delegate;
/// This init method just for previewing photos / 用这个初始化方法以预览图片
- (instancetype)initWithSelectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index;
/// Default is 9 / 默认最大可选9张图片
@property (nonatomic, assign) NSInteger maxImagesCount;
/// Sort photos ascending by modificationDate,Default is YES
/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个
@property (nonatomic, assign) BOOL sortAscendingByModificationDate;
/// Default is 828px / 默认828像素宽
@property (nonatomic, assign) CGFloat photoWidth;
/// Default is 600px / 默认600像素宽
@property (nonatomic, assign) CGFloat photoPreviewMaxWidth;
/// Default is 15, While fetching photo, HUD will dismiss automatic if timeout;
/// 超时时间,默认为15秒,当取图片时间超过15秒还没有取成功时,会自动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 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;
/// The photos user have selected
/// 用户选中过的图片数组
@property (nonatomic, strong) NSMutableArray *selectedAssets;
@property (nonatomic, strong) NSMutableArray<TZAssetModel *> *selectedModels;
- (void)showAlertWithTitle:(NSString *)title;
- (void)showProgressHUD;
- (void)hideProgressHUD;
@property (nonatomic, assign) BOOL isSelectOriginalPhoto;
/// Appearance / 外观颜色
@property (nonatomic, strong) UIColor *oKButtonTitleColorNormal;
@property (nonatomic, strong) UIColor *oKButtonTitleColorDisabled;
// The picker should dismiss itself; when it dismissed these handle will be called.
// 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的时候,会执行下面的handle
// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它
@property (nonatomic, copy) void (^didFinishPickingPhotosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto);
@property (nonatomic, copy) void (^didFinishPickingPhotosWithInfosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto,NSArray<NSDictionary *> *infos);
@property (nonatomic, copy) void (^imagePickerControllerDidCancelHandle)();
// If user picking a video, this handle will be called.
// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
// 如果用户选择了一个视频,下面的handle会被执行
// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,id asset);
@property (nonatomic, weak) id<TZImagePickerControllerDelegate> pickerDelegate;
@end
@protocol TZImagePickerControllerDelegate <NSObject>
@optional
// The picker should dismiss itself; when it dismissed these handle will be called.
// 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的时候,会执行下面的handle
// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto;
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray<NSDictionary *> *)infos;
- (void)imagePickerControllerDidCancel:(TZImagePickerController *)picker;
// If user picking a video, this callback will be called.
// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
// 如果用户选择了一个视频,下面的handle会被执行
// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(id)asset;
@end
@interface TZAlbumPickerController : UIViewController
@end
@interface UIImage (MyBundle)
+ (UIImage *)imageNamedFromMyBundle:(NSString *)name;
@end
//
// TZImagePickerController.m
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import "TZImagePickerController.h"
#import "TZPhotoPickerController.h"
#import "TZPhotoPreviewController.h"
#import "TZAssetModel.h"
#import "TZAssetCell.h"
#import "UIView+Layout.h"
#import "TZImageManager.h"
@interface TZImagePickerController () {
NSTimer *_timer;
UILabel *_tipLable;
BOOL _pushToPhotoPickerVc;
UIButton *_progressHUD;
UIView *_HUDContainer;
UIActivityIndicatorView *_HUDIndicatorView;
UILabel *_HUDLable;
UIStatusBarStyle _originStatusBarStyle;
}
@end
@implementation TZImagePickerController
- (void)viewDidLoad {
[super viewDidLoad];
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];
if (iOS7Later) {
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;
}
UIBarButtonItem *barItem;
if (iOS9Later) {
barItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]];
} else {
barItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil];
}
NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
textAttrs[NSForegroundColorAttributeName] = [UIColor whiteColor];
textAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:15];
[barItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
[UIApplication sharedApplication].statusBarStyle = iOS7Later ? UIStatusBarStyleLightContent : UIStatusBarStyleBlackOpaque;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle;
[self hideProgressHUD];
}
- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id<TZImagePickerControllerDelegate>)delegate {
TZAlbumPickerController *albumPickerVc = [[TZAlbumPickerController alloc] init];
self = [super initWithRootViewController:albumPickerVc];
if (self) {
self.maxImagesCount = maxImagesCount > 0 ? maxImagesCount : 9; // Default is 9 / 默认最大可选9张图片
self.pickerDelegate = delegate;
self.selectedModels = [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.timeout = 15;
self.photoWidth = 828.0;
self.photoPreviewMaxWidth = 600;
self.sortAscendingByModificationDate = YES;
if (![[TZImageManager manager] authorizationStatusAuthorized]) {
_tipLable = [[UILabel alloc] init];
_tipLable.frame = CGRectMake(8, 0, self.view.tz_width - 16, 300);
_tipLable.textAlignment = NSTextAlignmentCenter;
_tipLable.numberOfLines = 0;
_tipLable.font = [UIFont systemFontOfSize:16];
_tipLable.textColor = [UIColor blackColor];
NSString *appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleDisplayName"];
if (!appName) appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleName"];
_tipLable.text = [NSString stringWithFormat:@"请在%@的\"设置-隐私-照片\"选项中,\r允许%@访问你的手机相册。",[UIDevice currentDevice].model,appName];
[self.view addSubview:_tipLable];
_timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:YES];
} else {
[self pushToPhotoPickerVc];
}
}
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.timeout = 15;
self.photoWidth = 828.0;
self.maxImagesCount = selectedAssets.count;
self.photoPreviewMaxWidth = 600;
previewVc.photos = [NSMutableArray arrayWithArray:selectedPhotos];
previewVc.currentIndex = index;
__weak typeof(self) weakSelf = self;
[previewVc setOkButtonClickBlockWithPreviewType:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
if (weakSelf.didFinishPickingPhotosHandle) {
weakSelf.didFinishPickingPhotosHandle(photos,assets,isSelectOriginalPhoto);
}
[weakSelf dismissViewControllerAnimated:YES completion:nil];
}];
}
return self;
}
- (void)observeAuthrizationStatusChange {
if ([[TZImageManager manager] authorizationStatusAuthorized]) {
[self pushToPhotoPickerVc];
[_tipLable removeFromSuperview];
[_timer invalidate];
_timer = nil;
}
}
- (void)pushToPhotoPickerVc {
_pushToPhotoPickerVc = YES;
if (_pushToPhotoPickerVc) {
TZPhotoPickerController *photoPickerVc = [[TZPhotoPickerController alloc] init];
photoPickerVc.isFirstAppear = YES;
[[TZImageManager manager] getCameraRollAlbum:self.allowPickingVideo allowPickingImage:self.allowPickingImage completion:^(TZAlbumModel *model) {
photoPickerVc.model = model;
[self pushViewController:photoPickerVc animated:YES];
_pushToPhotoPickerVc = NO;
}];
}
}
- (void)showAlertWithTitle:(NSString *)title {
if (iOS8Later) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"我知道了" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:title message:nil delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil, nil] show];
}
}
- (void)showProgressHUD {
if (!_progressHUD) {
_progressHUD = [UIButton buttonWithType:UIButtonTypeCustom];
[_progressHUD setBackgroundColor:[UIColor clearColor]];
_HUDContainer = [[UIView alloc] init];
_HUDContainer.frame = CGRectMake((self.view.tz_width - 120) / 2, (self.view.tz_height - 90) / 2, 120, 90);
_HUDContainer.layer.cornerRadius = 8;
_HUDContainer.clipsToBounds = YES;
_HUDContainer.backgroundColor = [UIColor darkGrayColor];
_HUDContainer.alpha = 0.7;
_HUDIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
_HUDIndicatorView.frame = CGRectMake(45, 15, 30, 30);
_HUDLable = [[UILabel alloc] init];
_HUDLable.frame = CGRectMake(0,40, 120, 50);
_HUDLable.textAlignment = NSTextAlignmentCenter;
_HUDLable.text = @"正在处理...";
_HUDLable.font = [UIFont systemFontOfSize:15];
_HUDLable.textColor = [UIColor whiteColor];
[_HUDContainer addSubview:_HUDLable];
[_HUDContainer addSubview:_HUDIndicatorView];
[_progressHUD addSubview:_HUDContainer];
}
[_HUDIndicatorView startAnimating];
[[UIApplication sharedApplication].keyWindow addSubview:_progressHUD];
// if over time, dismiss HUD automatic
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.timeout * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self hideProgressHUD];
});
}
- (void)hideProgressHUD {
if (_progressHUD) {
[_HUDIndicatorView stopAnimating];
[_progressHUD removeFromSuperview];
}
}
- (void)setTimeout:(NSInteger)timeout {
_timeout = timeout;
if (timeout < 5) {
_timeout = 5;
} else if (_timeout > 60) {
_timeout = 60;
}
}
- (void)setPhotoPreviewMaxWidth:(CGFloat)photoPreviewMaxWidth {
_photoPreviewMaxWidth = photoPreviewMaxWidth;
if (photoPreviewMaxWidth > 800) {
_photoPreviewMaxWidth = 800;
} else if (photoPreviewMaxWidth < 500) {
_photoPreviewMaxWidth = 500;
}
[TZImageManager manager].photoPreviewMaxWidth = _photoPreviewMaxWidth;
}
- (void)setSelectedAssets:(NSMutableArray *)selectedAssets {
_selectedAssets = selectedAssets;
_selectedModels = [NSMutableArray array];
for (id asset in selectedAssets) {
TZAssetModel *model = [TZAssetModel modelWithAsset:asset type:TZAssetModelMediaTypePhoto];
model.isSelected = YES;
[_selectedModels addObject:model];
}
}
- (void)setAllowPickingImage:(BOOL)allowPickingImage {
_allowPickingImage = allowPickingImage;
NSString *allowPickingImageStr = _allowPickingImage ? @"1" : @"0";
[[NSUserDefaults standardUserDefaults] setObject:allowPickingImageStr forKey:@"tz_allowPickingImage"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)setAllowPickingVideo:(BOOL)allowPickingVideo {
_allowPickingVideo = allowPickingVideo;
NSString *allowPickingVideoStr = _allowPickingVideo ? @"1" : @"0";
[[NSUserDefaults standardUserDefaults] setObject:allowPickingVideoStr forKey:@"tz_allowPickingVideo"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)setSortAscendingByModificationDate:(BOOL)sortAscendingByModificationDate {
_sortAscendingByModificationDate = sortAscendingByModificationDate;
[TZImageManager manager].sortAscendingByModificationDate = sortAscendingByModificationDate;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (iOS7Later) viewController.automaticallyAdjustsScrollViewInsets = NO;
if (_timer) { [_timer invalidate]; _timer = nil;}
if (self.childViewControllers.count > 0) {
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(3, 0, 50, 44)];
[backButton setImage:[UIImage imageNamedFromMyBundle:@"navi_back.png"] forState:UIControlStateNormal];
backButton.imageEdgeInsets = UIEdgeInsetsMake(0, -5, 0, 0);
[backButton setTitle:@"返回" forState:UIControlStateNormal];
backButton.titleLabel.font = [UIFont systemFontOfSize:15];
[backButton addTarget:self action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
}
[super pushViewController:viewController animated:animated];
}
@end
@interface TZAlbumPickerController ()<UITableViewDataSource,UITableViewDelegate> {
UITableView *_tableView;
}
@property (nonatomic, strong) NSMutableArray *albumArr;
@end
@implementation TZAlbumPickerController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = @"照片";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"取消" style:UIBarButtonItemStylePlain target:self action:@selector(cancel)];
[self configTableView];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
[imagePickerVc hideProgressHUD];
if (_albumArr) {
for (TZAlbumModel *albumModel in _albumArr) {
albumModel.selectedModels = imagePickerVc.selectedModels;
}
[_tableView reloadData];
} else {
[self configTableView];
}
}
- (void)configTableView {
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
[[TZImageManager manager] getAllAlbums:imagePickerVc.allowPickingVideo allowPickingImage:imagePickerVc.allowPickingImage completion:^(NSArray<TZAlbumModel *> *models) {
_albumArr = [NSMutableArray arrayWithArray:models];
for (TZAlbumModel *albumModel in _albumArr) {
albumModel.selectedModels = imagePickerVc.selectedModels;
}
if (!_tableView) {
CGFloat top = 44;
if (iOS7Later) top += 20;
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, top, self.view.tz_width, self.view.tz_height - top) style:UITableViewStylePlain];
_tableView.rowHeight = 70;
_tableView.tableFooterView = [[UIView alloc] init];
_tableView.dataSource = self;
_tableView.delegate = self;
[_tableView registerClass:[TZAlbumCell class] forCellReuseIdentifier:@"TZAlbumCell"];
[self.view addSubview:_tableView];
} else {
[_tableView reloadData];
}
}];
}
#pragma mark - Click Event
- (void)cancel {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerControllerDidCancel:)]) {
[imagePickerVc.pickerDelegate imagePickerControllerDidCancel:imagePickerVc];
}
if (imagePickerVc.imagePickerControllerDidCancelHandle) {
imagePickerVc.imagePickerControllerDidCancelHandle();
}
}
#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"];
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
cell.selectedCountButton.backgroundColor = imagePickerVc.oKButtonTitleColorNormal;
cell.model = _albumArr[indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TZPhotoPickerController *photoPickerVc = [[TZPhotoPickerController alloc] init];
TZAlbumModel *model = _albumArr[indexPath.row];
photoPickerVc.model = model;
__weak typeof(self) weakSelf = self;
[photoPickerVc setBackButtonClickHandle:^(TZAlbumModel *model) {
[weakSelf.albumArr replaceObjectAtIndex:indexPath.row withObject:model];
}];
[self.navigationController pushViewController:photoPickerVc animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
@end
@implementation UIImage (MyBundle)
+ (UIImage *)imageNamedFromMyBundle:(NSString *)name {
UIImage *image = [UIImage imageNamed:[@"TZImagePickerController.bundle" stringByAppendingPathComponent:name]];
if (image) {
return image;
} else {
image = [UIImage imageNamed:[@"Frameworks/TZImagePickerController.framework/TZImagePickerController.bundle" stringByAppendingPathComponent:name]];
return image;
}
}
@end
//
// TZPhotoPickerController.h
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import <UIKit/UIKit.h>
@class TZAlbumModel;
@interface TZPhotoPickerController : UIViewController
@property (nonatomic, assign) BOOL isFirstAppear;
@property (nonatomic, strong) TZAlbumModel *model;
@property (nonatomic, copy) void (^backButtonClickHandle)(TZAlbumModel *model);
@end
//
// 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+Layout.h"
#import "TZImageManager.h"
#import "TZVideoPlayerController.h"
@interface TZPhotoPickerController ()<UICollectionViewDataSource,UICollectionViewDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UIAlertViewDelegate> {
NSMutableArray *_models;
UIButton *_previewButton;
UIButton *_okButton;
UIImageView *_numberImageView;
UILabel *_numberLable;
UIButton *_originalPhotoButton;
UILabel *_originalPhotoLable;
BOOL _shouldScrollToBottom;
BOOL _showTakePhotoBtn;
}
@property CGRect previousPreheatRect;
@property (nonatomic, assign) BOOL isSelectOriginalPhoto;
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) UIImagePickerController *imagePickerVc;
@end
static CGSize AssetGridThumbnailSize;
@implementation TZPhotoPickerController
- (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 (iOS9Later) {
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];
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
_isSelectOriginalPhoto = tzImagePickerVc.isSelectOriginalPhoto;
_shouldScrollToBottom = YES;
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = _model.name;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"取消" style:UIBarButtonItemStylePlain target:self action:@selector(cancel)];
_showTakePhotoBtn = (([_model.name isEqualToString:@"相机胶卷"] || [_model.name isEqualToString:@"Camera Roll"] || [_model.name isEqualToString:@"所有照片"] || [_model.name isEqualToString:@"All Photos"]) && tzImagePickerVc.allowTakePicture);
if (!tzImagePickerVc.sortAscendingByModificationDate && _isFirstAppear && iOS8Later) {
[[TZImageManager manager] getCameraRollAlbum:tzImagePickerVc.allowPickingVideo allowPickingImage:tzImagePickerVc.allowPickingImage completion:^(TZAlbumModel *model) {
_model = model;
_models = [NSMutableArray arrayWithArray:_model.models];
[self initSubviews];
}];
} else {
if (_showTakePhotoBtn || !iOS8Later || _isFirstAppear) {
[[TZImageManager manager] getAssetsFromFetchResult:_model.result allowPickingVideo:tzImagePickerVc.allowPickingVideo allowPickingImage:tzImagePickerVc.allowPickingImage completion:^(NSArray<TZAssetModel *> *models) {
_models = [NSMutableArray arrayWithArray:models];
[self initSubviews];
}];
} else {
_models = [NSMutableArray arrayWithArray:_model.models];
[self initSubviews];
}
}
// [self resetCachedAssets];
}
- (void)initSubviews {
[self checkSelectedModels];
[self configCollectionView];
[self configBottomToolBar];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
tzImagePickerVc.isSelectOriginalPhoto = _isSelectOriginalPhoto;
if (self.backButtonClickHandle) {
self.backButtonClickHandle(_model);
}
}
- (void)configCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
CGFloat margin = 4;
CGFloat itemWH = (self.view.tz_width - 2 * margin - 4) / 4 - margin;
layout.itemSize = CGSizeMake(itemWH, itemWH);
layout.minimumInteritemSpacing = margin;
layout.minimumLineSpacing = margin;
CGFloat top = margin + 44;
if (iOS7Later) top += 20;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(margin, top, self.view.tz_width - 2 * margin, self.view.tz_height - 50 - top) collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.dataSource = self;
_collectionView.delegate = self;
_collectionView.alwaysBounceHorizontal = NO;
if (iOS7Later) _collectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, 2);
_collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 0, -2);
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (_showTakePhotoBtn && tzImagePickerVc.allowTakePicture ) {
_collectionView.contentSize = CGSizeMake(self.view.tz_width, ((_model.count + 4) / 4) * self.view.tz_width);
} else {
_collectionView.contentSize = CGSizeMake(self.view.tz_width, ((_model.count + 3) / 4) * self.view.tz_width);
}
[self.view addSubview:_collectionView];
[_collectionView registerClass:[TZAssetCell class] forCellWithReuseIdentifier:@"TZAssetCell"];
[_collectionView registerClass:[TZAssetCameraCell class] forCellWithReuseIdentifier:@"TZAssetCameraCell"];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self scrollCollectionViewToBottom];
// 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);
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (iOS8Later) {
// [self updateCachedAssets];
}
}
- (void)configBottomToolBar {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
UIView *bottomToolBar = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.tz_height - 50, self.view.tz_width, 50)];
CGFloat rgb = 253 / 255.0;
bottomToolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0];
_previewButton = [UIButton buttonWithType:UIButtonTypeCustom];
_previewButton.frame = CGRectMake(10, 3, 44, 44);
[_previewButton addTarget:self action:@selector(previewButtonClick) forControlEvents:UIControlEventTouchUpInside];
_previewButton.titleLabel.font = [UIFont systemFontOfSize:16];
[_previewButton setTitle:@"预览" forState:UIControlStateNormal];
[_previewButton setTitle:@"预览" forState:UIControlStateDisabled];
[_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.frame = CGRectMake(50, self.view.tz_height - 50, 130, 50);
_originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, -8, 0, 0);
_originalPhotoButton.contentEdgeInsets = UIEdgeInsetsMake(0, -45, 0, 0);
[_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside];
_originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:16];
[_originalPhotoButton setTitle:@"原图" forState:UIControlStateNormal];
[_originalPhotoButton setTitle:@"原图" forState:UIControlStateSelected];
[_originalPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
[_originalPhotoButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected];
[_originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_def.png"] forState:UIControlStateNormal];
[_originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_sel.png"] forState:UIControlStateSelected];
_originalPhotoButton.selected = _isSelectOriginalPhoto;
_originalPhotoButton.enabled = tzImagePickerVc.selectedModels.count > 0;
_originalPhotoLable = [[UILabel alloc] init];
_originalPhotoLable.frame = CGRectMake(70, 0, 60, 50);
_originalPhotoLable.textAlignment = NSTextAlignmentLeft;
_originalPhotoLable.font = [UIFont systemFontOfSize:16];
_originalPhotoLable.textColor = [UIColor blackColor];
if (_isSelectOriginalPhoto) [self getSelectedPhotoBytes];
}
_okButton = [UIButton buttonWithType:UIButtonTypeCustom];
_okButton.frame = CGRectMake(self.view.tz_width - 44 - 12, 3, 44, 44);
_okButton.titleLabel.font = [UIFont systemFontOfSize:16];
[_okButton addTarget:self action:@selector(okButtonClick) forControlEvents:UIControlEventTouchUpInside];
[_okButton setTitle:@"确定" forState:UIControlStateNormal];
[_okButton setTitle:@"确定" forState:UIControlStateDisabled];
[_okButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
[_okButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled];
_okButton.enabled = tzImagePickerVc.selectedModels.count;
_numberImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamedFromMyBundle:@"photo_number_icon.png"]];
_numberImageView.frame = CGRectMake(self.view.tz_width - 56 - 24, 12, 26, 26);
_numberImageView.hidden = tzImagePickerVc.selectedModels.count <= 0;
_numberImageView.backgroundColor = [UIColor clearColor];
_numberLable = [[UILabel alloc] init];
_numberLable.frame = _numberImageView.frame;
_numberLable.font = [UIFont systemFontOfSize:16];
_numberLable.textColor = [UIColor whiteColor];
_numberLable.textAlignment = NSTextAlignmentCenter;
_numberLable.text = [NSString stringWithFormat:@"%zd",tzImagePickerVc.selectedModels.count];
_numberLable.hidden = tzImagePickerVc.selectedModels.count <= 0;
_numberLable.backgroundColor = [UIColor clearColor];
UIView *divide = [[UIView alloc] init];
CGFloat rgb2 = 222 / 255.0;
divide.backgroundColor = [UIColor colorWithRed:rgb2 green:rgb2 blue:rgb2 alpha:1.0];
divide.frame = CGRectMake(0, 0, self.view.tz_width, 1);
[bottomToolBar addSubview:divide];
[bottomToolBar addSubview:_previewButton];
[bottomToolBar addSubview:_okButton];
[bottomToolBar addSubview:_numberImageView];
[bottomToolBar addSubview:_numberLable];
[self.view addSubview:bottomToolBar];
[self.view addSubview:_originalPhotoButton];
[_originalPhotoButton addSubview:_originalPhotoLable];
}
#pragma mark - Click Event
- (void)cancel {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerControllerDidCancel:)]) {
[imagePickerVc.pickerDelegate imagePickerControllerDidCancel:imagePickerVc];
}
if (imagePickerVc.imagePickerControllerDidCancelHandle) {
imagePickerVc.imagePickerControllerDidCancelHandle();
}
}
- (void)previewButtonClick {
TZPhotoPreviewController *photoPreviewVc = [[TZPhotoPreviewController alloc] init];
[self pushPhotoPrevireViewController:photoPreviewVc];
}
- (void)originalPhotoButtonClick {
_originalPhotoButton.selected = !_originalPhotoButton.isSelected;
_isSelectOriginalPhoto = _originalPhotoButton.isSelected;
_originalPhotoLable.hidden = !_originalPhotoButton.isSelected;
if (_isSelectOriginalPhoto) [self getSelectedPhotoBytes];
}
- (void)okButtonClick {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
[tzImagePickerVc showProgressHUD];
NSMutableArray *photos = [NSMutableArray array];
NSMutableArray *assets = [NSMutableArray array];
NSMutableArray *infoArr = [NSMutableArray array];
for (NSInteger i = 0; i < tzImagePickerVc.selectedModels.count; i++) { [photos addObject:@1];[assets addObject:@1];[infoArr addObject:@1]; }
[TZImageManager manager].shouldFixOrientation = YES;
for (NSInteger i = 0; i < tzImagePickerVc.selectedModels.count; i++) {
TZAssetModel *model = tzImagePickerVc.selectedModels[i];
[[TZImageManager manager] getPhotoWithAsset:model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
if (isDegraded) return;
if (photo) {
photo = [self 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 ([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);
}
[tzImagePickerVc hideProgressHUD];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}];
}
}
#pragma mark - UICollectionViewDataSource && Delegate
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (_showTakePhotoBtn) {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (tzImagePickerVc.allowPickingImage && tzImagePickerVc.allowTakePicture) {
return _models.count + 1;
}
}
return _models.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// the cell lead to take a picture / 去拍照的cell
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (((tzImagePickerVc.sortAscendingByModificationDate && indexPath.row >= _models.count) || (!tzImagePickerVc.sortAscendingByModificationDate && indexPath.row == 0)) && _showTakePhotoBtn) {
TZAssetCameraCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZAssetCameraCell" forIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamedFromMyBundle:@"takePicture.png"];
return cell;
}
// the cell dipaly photo or video / 展示照片或视频的cell
TZAssetCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZAssetCell" forIndexPath:indexPath];
TZAssetModel *model;
if (tzImagePickerVc.sortAscendingByModificationDate || !_showTakePhotoBtn) {
model = _models[indexPath.row];
} else {
model = _models[indexPath.row - 1];
}
cell.model = model;
__weak typeof(cell) weakCell = cell;
__weak typeof(self) weakSelf = self;
__weak typeof(_numberImageView.layer) weakLayer = _numberImageView.layer;
cell.didSelectPhotoBlock = ^(BOOL isSelected) {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)weakSelf.navigationController;
// 1. cancel select / 取消选择
if (isSelected) {
weakCell.selectPhotoButton.selected = NO;
model.isSelected = NO;
NSArray *selectedModels = [NSArray arrayWithArray:tzImagePickerVc.selectedModels];
for (TZAssetModel *model_item in selectedModels) {
if ([[[TZImageManager manager] getAssetIdentifier:model.asset] isEqualToString:[[TZImageManager manager] getAssetIdentifier:model_item.asset]]) {
[tzImagePickerVc.selectedModels removeObject:model_item];
}
}
[weakSelf refreshBottomToolBarStatus];
} else {
// 2. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制
if (tzImagePickerVc.selectedModels.count < tzImagePickerVc.maxImagesCount) {
weakCell.selectPhotoButton.selected = YES;
model.isSelected = YES;
[tzImagePickerVc.selectedModels addObject:model];
[weakSelf refreshBottomToolBarStatus];
} else {
[tzImagePickerVc showAlertWithTitle:[NSString stringWithFormat:@"你最多只能选择%zd张照片",tzImagePickerVc.maxImagesCount]];
}
}
[UIView showOscillatoryAnimationWithLayer:weakLayer type:TZOscillatoryAnimationToSmaller];
};
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// take a photo / 去拍照
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (((tzImagePickerVc.sortAscendingByModificationDate && indexPath.row >= _models.count) || (!tzImagePickerVc.sortAscendingByModificationDate && indexPath.row == 0)) && _showTakePhotoBtn) {
[self takePhoto]; return;
}
// preview phote or video / 预览照片或视频
NSInteger index = indexPath.row;
if (!tzImagePickerVc.sortAscendingByModificationDate && _showTakePhotoBtn) {
index = indexPath.row - 1;
}
TZAssetModel *model = _models[index];
if (model.type == TZAssetModelMediaTypeVideo) {
if (tzImagePickerVc.selectedModels.count > 0) {
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
[imagePickerVc showAlertWithTitle:@"选择照片时不能选择视频"];
} else {
TZVideoPlayerController *videoPlayerVc = [[TZVideoPlayerController alloc] init];
videoPlayerVc.model = model;
[self.navigationController pushViewController:videoPlayerVc 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 (iOS8Later) {
// [self updateCachedAssets];
}
}
#pragma mark - Private Method
- (void)takePhoto {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if ((authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied) && iOS8Later) {
// 无权限 做一个友好的提示
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
[alert show];
} else { // 调用相机
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerVc.sourceType = sourceType;
if(iOS8Later) {
_imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[self presentViewController:_imagePickerVc animated:YES completion:nil];
} else {
NSLog(@"模拟器中无法打开照相机,请在真机中使用");
}
}
}
- (void)refreshBottomToolBarStatus {
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
_previewButton.enabled = imagePickerVc.selectedModels.count > 0;
_okButton.enabled = imagePickerVc.selectedModels.count > 0;
_numberImageView.hidden = imagePickerVc.selectedModels.count <= 0;
_numberLable.hidden = imagePickerVc.selectedModels.count <= 0;
_numberLable.text = [NSString stringWithFormat:@"%zd",imagePickerVc.selectedModels.count];
_originalPhotoButton.enabled = imagePickerVc.selectedModels.count > 0;
_originalPhotoButton.selected = (_isSelectOriginalPhoto && _originalPhotoButton.enabled);
_originalPhotoLable.hidden = (!_originalPhotoButton.isSelected);
if (_isSelectOriginalPhoto) [self getSelectedPhotoBytes];
}
- (void)pushPhotoPrevireViewController:(TZPhotoPreviewController *)photoPreviewVc {
__weak typeof(self) weakSelf = self;
photoPreviewVc.isSelectOriginalPhoto = _isSelectOriginalPhoto;
photoPreviewVc.backButtonClickBlock = ^(BOOL isSelectOriginalPhoto) {
weakSelf.isSelectOriginalPhoto = isSelectOriginalPhoto;
[weakSelf.collectionView reloadData];
[weakSelf refreshBottomToolBarStatus];
};
photoPreviewVc.okButtonClickBlock = ^(BOOL isSelectOriginalPhoto){
weakSelf.isSelectOriginalPhoto = isSelectOriginalPhoto;
[weakSelf okButtonClick];
};
[self.navigationController pushViewController:photoPreviewVc animated:YES];
}
- (void)getSelectedPhotoBytes {
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
[[TZImageManager manager] getPhotosBytesWithArray:imagePickerVc.selectedModels completion:^(NSString *totalBytes) {
_originalPhotoLable.text = [NSString stringWithFormat:@"(%@)",totalBytes];
}];
}
/// Scale image / 缩放图片
- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size {
if (image.size.width < size.width) {
return image;
}
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
- (void)scrollCollectionViewToBottom {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (_shouldScrollToBottom && _models.count > 0 && tzImagePickerVc.sortAscendingByModificationDate) {
NSInteger item = _models.count - 1;
if (_showTakePhotoBtn) {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (tzImagePickerVc.allowPickingImage && tzImagePickerVc.allowTakePicture) {
item += 1;
}
}
[_collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:item inSection:0] atScrollPosition:UICollectionViewScrollPositionBottom animated:NO];
_shouldScrollToBottom = NO;
}
}
- (void)checkSelectedModels {
for (TZAssetModel *model in _models) {
model.isSelected = NO;
NSMutableArray *selectedAssets = [NSMutableArray array];
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
for (TZAssetModel *model in tzImagePickerVc.selectedModels) {
[selectedAssets addObject:model.asset];
}
if ([[TZImageManager manager] isAssetsArray:selectedAssets containAsset:model.asset]) {
model.isSelected = YES;
}
}
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
if (iOS8Later) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
} else {
// [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Privacy&path=Photos"]];
}
}
}
#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 *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[[TZImageManager manager] savePhotoWithImage:image completion:^{
[self reloadPhotoArray];
}];
}
}
- (void)reloadPhotoArray {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
[[TZImageManager manager] getCameraRollAlbum:tzImagePickerVc.allowPickingVideo allowPickingImage:tzImagePickerVc.allowPickingImage completion:^(TZAlbumModel *model) {
_model = model;
[[TZImageManager manager] getAssetsFromFetchResult:_model.result allowPickingVideo:tzImagePickerVc.allowPickingVideo allowPickingImage:tzImagePickerVc.allowPickingImage completion:^(NSArray<TZAssetModel *> *models) {
[tzImagePickerVc hideProgressHUD];
TZAssetModel *assetModel;
if (tzImagePickerVc.sortAscendingByModificationDate) {
assetModel = [models lastObject];
[_models addObject:assetModel];
} else {
assetModel = [models firstObject];
[_models insertObject:assetModel atIndex:0];
}
if (tzImagePickerVc.selectedModels.count < tzImagePickerVc.maxImagesCount) {
assetModel.isSelected = YES;
[tzImagePickerVc.selectedModels addObject:assetModel];
[self refreshBottomToolBarStatus];
}
[_collectionView reloadData];
_shouldScrollToBottom = YES;
[self scrollCollectionViewToBottom];
}];
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:nil];
}
#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;
}
@end
//
// TZPhotoPreviewCell.h
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import <UIKit/UIKit.h>
@class TZAssetModel;
@interface TZPhotoPreviewCell : UICollectionViewCell
@property (nonatomic, strong) TZAssetModel *model;
@property (nonatomic, copy) void (^singleTapGestureBlock)();
@end
//
// TZPhotoPreviewCell.m
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import "TZPhotoPreviewCell.h"
#import "TZAssetModel.h"
#import "UIView+Layout.h"
#import "TZImageManager.h"
@interface TZPhotoPreviewCell ()<UIGestureRecognizerDelegate,UIScrollViewDelegate> {
CGFloat _aspectRatio;
}
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIView *imageContainerView;
@end
@implementation TZPhotoPreviewCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor blackColor];
_scrollView = [[UIScrollView alloc] init];
_scrollView.frame = CGRectMake(0, 0, self.tz_width, self.tz_height);
_scrollView.bouncesZoom = YES;
_scrollView.maximumZoomScale = 2.5;
_scrollView.minimumZoomScale = 1.0;
_scrollView.multipleTouchEnabled = YES;
_scrollView.delegate = self;
_scrollView.scrollsToTop = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_scrollView.delaysContentTouches = NO;
_scrollView.canCancelContentTouches = YES;
_scrollView.alwaysBounceVertical = NO;
[self addSubview:_scrollView];
_imageContainerView = [[UIView alloc] init];
_imageContainerView.clipsToBounds = YES;
[_scrollView addSubview:_imageContainerView];
_imageView = [[UIImageView alloc] init];
_imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500];
_imageView.clipsToBounds = YES;
[_imageContainerView addSubview:_imageView];
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];
}
return self;
}
- (void)setModel:(TZAssetModel *)model {
_model = model;
[_scrollView setZoomScale:1.0 animated:NO];
[[TZImageManager manager] getPhotoWithAsset:model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
self.imageView.image = photo;
[self resizeSubviews];
}];
}
- (void)resizeSubviews {
_imageContainerView.tz_origin = CGPointZero;
_imageContainerView.tz_width = self.tz_width;
UIImage *image = _imageView.image;
if (image.size.height / image.size.width > self.tz_height / self.tz_width) {
_imageContainerView.tz_height = floor(image.size.height / (image.size.width / self.tz_width));
} else {
CGFloat height = image.size.height / image.size.width * self.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;
}
_scrollView.contentSize = CGSizeMake(self.tz_width, MAX(_imageContainerView.tz_height, self.tz_height));
[_scrollView scrollRectToVisible:self.bounds animated:NO];
_scrollView.alwaysBounceVertical = _imageContainerView.tz_height <= self.tz_height ? NO : YES;
_imageView.frame = _imageContainerView.bounds;
}
#pragma mark - UITapGestureRecognizer Event
- (void)doubleTap:(UITapGestureRecognizer *)tap {
if (_scrollView.zoomScale > 1.0) {
[_scrollView setZoomScale:1.0 animated:YES];
} else {
CGPoint touchPoint = [tap locationInView:self.imageView];
CGFloat newZoomScale = _scrollView.maximumZoomScale;
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
- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return _imageContainerView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
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
//
// TZPhotoPreviewController.h
// TZImagePickerController
//
// Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import <UIKit/UIKit.h>
@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 / 是否返回原图
/// Return the new selected photos / 返回最新的选中图片数组
@property (nonatomic, copy) void (^backButtonClickBlock)(BOOL isSelectOriginalPhoto);
@property (nonatomic, copy) void (^okButtonClickBlock)(BOOL isSelectOriginalPhoto);
@property (nonatomic, copy) void (^okButtonClickBlockWithPreviewType)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto);
@end
//
// 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+Layout.h"
#import "TZImagePickerController.h"
#import "TZImageManager.h"
@interface TZPhotoPreviewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UIScrollViewDelegate> {
UICollectionView *_collectionView;
BOOL _isHideNaviBar;
NSArray *_photosTemp;
NSArray *_assetsTemp;
UIView *_naviBar;
UIButton *_backButton;
UIButton *_selectButton;
UIView *_toolBar;
UIButton *_okButton;
UIImageView *_numberImageView;
UILabel *_numberLable;
UIButton *_originalPhotoButton;
UILabel *_originalPhotoLable;
}
@end
@implementation TZPhotoPreviewController
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)weakSelf.navigationController;
if (!self.models.count) {
self.models = [NSMutableArray arrayWithArray:_tzImagePickerVc.selectedModels];
_assetsTemp = [NSMutableArray arrayWithArray:_tzImagePickerVc.selectedAssets];
self.isSelectOriginalPhoto = _tzImagePickerVc.isSelectOriginalPhoto;
}
[self configCollectionView];
[self configCustomNaviBar];
[self configBottomToolBar];
}
- (void)setPhotos:(NSMutableArray *)photos {
_photos = photos;
_photosTemp = [NSArray arrayWithArray:photos];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = YES;
if (_currentIndex) [_collectionView setContentOffset:CGPointMake((self.view.tz_width) * _currentIndex, 0) animated:NO];
[self refreshNaviBarAndBottomBarState];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = NO;
}
- (void)configCustomNaviBar {
_naviBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.tz_width, 64)];
_naviBar.backgroundColor = [UIColor colorWithRed:(34/255.0) green:(34/255.0) blue:(34/255.0) alpha:1.0];
_naviBar.alpha = 0.7;
_backButton = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 44, 44)];
[_backButton setImage:[UIImage imageNamedFromMyBundle:@"navi_back.png"] forState:UIControlStateNormal];
[_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
_selectButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.tz_width - 54, 10, 42, 42)];
[_selectButton setImage:[UIImage imageNamedFromMyBundle:@"photo_def_photoPickerVc.png"] forState:UIControlStateNormal];
[_selectButton setImage:[UIImage imageNamedFromMyBundle:@"photo_sel_photoPickerVc.png"] forState:UIControlStateSelected];
[_selectButton addTarget:self action:@selector(select:) forControlEvents:UIControlEventTouchUpInside];
[_naviBar addSubview:_selectButton];
[_naviBar addSubview:_backButton];
[self.view addSubview:_naviBar];
}
- (void)configBottomToolBar {
_toolBar = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.tz_height - 44, self.view.tz_width, 44)];
CGFloat rgb = 34 / 255.0;
_toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0];
_toolBar.alpha = 0.7;
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (_tzImagePickerVc.allowPickingOriginalPhoto) {
_originalPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_originalPhotoButton.frame = CGRectMake(5, 0, 120, 44);
_originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, -8, 0, 0);
_originalPhotoButton.contentEdgeInsets = UIEdgeInsetsMake(0, -50, 0, 0);
_originalPhotoButton.backgroundColor = [UIColor clearColor];
[_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside];
_originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:13];
[_originalPhotoButton setTitle:@"原图" forState:UIControlStateNormal];
[_originalPhotoButton setTitle:@"原图" forState:UIControlStateSelected];
[_originalPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
[_originalPhotoButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
[_originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"preview_original_def.png"] forState:UIControlStateNormal];
[_originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_sel.png"] forState:UIControlStateSelected];
_originalPhotoLable = [[UILabel alloc] init];
_originalPhotoLable.frame = CGRectMake(60, 0, 70, 44);
_originalPhotoLable.textAlignment = NSTextAlignmentLeft;
_originalPhotoLable.font = [UIFont systemFontOfSize:13];
_originalPhotoLable.textColor = [UIColor whiteColor];
_originalPhotoLable.backgroundColor = [UIColor clearColor];
if (_isSelectOriginalPhoto) [self showPhotoBytes];
}
_okButton = [UIButton buttonWithType:UIButtonTypeCustom];
_okButton.frame = CGRectMake(self.view.tz_width - 44 - 12, 0, 44, 44);
_okButton.titleLabel.font = [UIFont systemFontOfSize:16];
[_okButton addTarget:self action:@selector(okButtonClick) forControlEvents:UIControlEventTouchUpInside];
[_okButton setTitle:@"确定" forState:UIControlStateNormal];
[_okButton setTitleColor:_tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
_numberImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamedFromMyBundle:@"photo_number_icon.png"]];
_numberImageView.backgroundColor = [UIColor clearColor];
_numberImageView.frame = CGRectMake(self.view.tz_width - 56 - 24, 9, 26, 26);
_numberImageView.hidden = _tzImagePickerVc.selectedModels.count <= 0;
_numberLable = [[UILabel alloc] init];
_numberLable.frame = _numberImageView.frame;
_numberLable.font = [UIFont systemFontOfSize:16];
_numberLable.textColor = [UIColor whiteColor];
_numberLable.textAlignment = NSTextAlignmentCenter;
_numberLable.text = [NSString stringWithFormat:@"%zd",_tzImagePickerVc.selectedModels.count];
_numberLable.hidden = _tzImagePickerVc.selectedModels.count <= 0;
_numberLable.backgroundColor = [UIColor clearColor];
[_originalPhotoButton addSubview:_originalPhotoLable];
[_toolBar addSubview:_okButton];
[_toolBar addSubview:_originalPhotoButton];
[_toolBar addSubview:_numberImageView];
[_toolBar addSubview:_numberLable];
[self.view addSubview:_toolBar];
}
- (void)configCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(self.view.tz_width, self.view.tz_height);
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 0;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.tz_width , self.view.tz_height) 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.view.tz_width * _models.count, self.view.tz_height);
[self.view addSubview:_collectionView];
[_collectionView registerClass:[TZPhotoPreviewCell class] forCellWithReuseIdentifier:@"TZPhotoPreviewCell"];
}
#pragma mark - Click Event
- (void)select:(UIButton *)selectButton {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
TZAssetModel *model = _models[_currentIndex];
if (!selectButton.isSelected) {
// 1. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制
if (_tzImagePickerVc.selectedModels.count >= _tzImagePickerVc.maxImagesCount) {
[_tzImagePickerVc showAlertWithTitle:[NSString stringWithFormat:@"你最多只能选择%zd张照片",_tzImagePickerVc.maxImagesCount]];
return;
// 2. if not over the maxImagesCount / 如果没有超过最大个数限制
} else {
[_tzImagePickerVc.selectedModels addObject:model];
if (self.photos) {
[_tzImagePickerVc.selectedAssets addObject:_assetsTemp[_currentIndex]];
[self.photos addObject:_photosTemp[_currentIndex]];
}
if (model.type == TZAssetModelMediaTypeVideo) {
[_tzImagePickerVc showAlertWithTitle:@"多选状态下选择视频,默认将视频当图片发送"];
}
}
} else {
NSArray *selectedModels = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
for (TZAssetModel *model_item in selectedModels) {
if ([model.asset isEqual:model_item.asset]) {
[_tzImagePickerVc.selectedModels removeObject:model_item];
if (self.photos) {
[_tzImagePickerVc.selectedAssets removeObject:_assetsTemp[_currentIndex]];
[self.photos removeObject:_photosTemp[_currentIndex]];
}
}
}
}
model.isSelected = !selectButton.isSelected;
[self refreshNaviBarAndBottomBarState];
if (model.isSelected) {
[UIView showOscillatoryAnimationWithLayer:selectButton.imageView.layer type:TZOscillatoryAnimationToBigger];
}
[UIView showOscillatoryAnimationWithLayer:_numberImageView.layer type:TZOscillatoryAnimationToSmaller];
}
- (void)back {
if (self.navigationController.childViewControllers.count < 2) {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
return;
}
[self.navigationController popViewControllerAnimated:YES];
if (self.backButtonClickBlock) {
self.backButtonClickBlock(_isSelectOriginalPhoto);
}
}
- (void)okButtonClick {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (_tzImagePickerVc.selectedModels.count == 0) {
TZAssetModel *model = _models[_currentIndex];
[_tzImagePickerVc.selectedModels addObject:model];
}
if (self.okButtonClickBlock) {
self.okButtonClickBlock(_isSelectOriginalPhoto);
}
if (self.okButtonClickBlockWithPreviewType) {
self.okButtonClickBlockWithPreviewType(self.photos,_tzImagePickerVc.selectedAssets,self.isSelectOriginalPhoto);
}
}
- (void)originalPhotoButtonClick {
_originalPhotoButton.selected = !_originalPhotoButton.isSelected;
_isSelectOriginalPhoto = _originalPhotoButton.isSelected;
_originalPhotoLable.hidden = !_originalPhotoButton.isSelected;
if (_isSelectOriginalPhoto) {
[self showPhotoBytes];
if (!_selectButton.isSelected) [self select:_selectButton];
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offSet = scrollView.contentOffset;
_currentIndex = (offSet.x + (self.view.tz_width * 0.5)) / self.view.tz_width;
[self refreshNaviBarAndBottomBarState];
}
#pragma mark - UICollectionViewDataSource && Delegate
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return _models.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TZPhotoPreviewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZPhotoPreviewCell" forIndexPath:indexPath];
cell.model = _models[indexPath.row];
__block BOOL _weakIsHideNaviBar = _isHideNaviBar;
__weak typeof(_naviBar) weakNaviBar = _naviBar;
__weak typeof(_toolBar) weakToolBar = _toolBar;
if (!cell.singleTapGestureBlock) {
cell.singleTapGestureBlock = ^(){
// show or hide naviBar / 显示或隐藏导航栏
_weakIsHideNaviBar = !_weakIsHideNaviBar;
weakNaviBar.hidden = _weakIsHideNaviBar;
weakToolBar.hidden = _weakIsHideNaviBar;
};
}
return cell;
}
#pragma mark - Private Method
- (void)refreshNaviBarAndBottomBarState {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
TZAssetModel *model = _models[_currentIndex];
_selectButton.selected = model.isSelected;
_numberLable.text = [NSString stringWithFormat:@"%zd",_tzImagePickerVc.selectedModels.count];
_numberImageView.hidden = (_tzImagePickerVc.selectedModels.count <= 0 || _isHideNaviBar);
_numberLable.hidden = (_tzImagePickerVc.selectedModels.count <= 0 || _isHideNaviBar);
_originalPhotoButton.selected = _isSelectOriginalPhoto;
_originalPhotoLable.hidden = !_originalPhotoButton.isSelected;
if (_isSelectOriginalPhoto) [self showPhotoBytes];
// If is previewing video, hide original photo button
// 如果正在预览的是视频,隐藏原图按钮
if (_isHideNaviBar) return;
if (model.type == TZAssetModelMediaTypeVideo) {
_originalPhotoButton.hidden = YES;
_originalPhotoLable.hidden = YES;
} else {
_originalPhotoButton.hidden = NO;
if (_isSelectOriginalPhoto) _originalPhotoLable.hidden = NO;
}
}
- (void)showPhotoBytes {
[[TZImageManager manager] getPhotosBytesWithArray:@[_models[_currentIndex]] completion:^(NSString *totalBytes) {
_originalPhotoLable.text = [NSString stringWithFormat:@"(%@)",totalBytes];
}];
}
@end
//
// TZVideoPlayerController.h
// TZImagePickerController
//
// Created by 谭真 on 16/1/5.
// Copyright © 2016年 谭真. All rights reserved.
//
#import <UIKit/UIKit.h>
@class TZAssetModel;
@interface TZVideoPlayerController : UIViewController
@property (nonatomic, strong) TZAssetModel *model;
@end
\ No newline at end of file
//
// TZVideoPlayerController.m
// TZImagePickerController
//
// Created by 谭真 on 16/1/5.
// Copyright © 2016年 谭真. All rights reserved.
//
#import "TZVideoPlayerController.h"
#import <MediaPlayer/MediaPlayer.h>
#import "UIView+Layout.h"
#import "TZImageManager.h"
#import "TZAssetModel.h"
#import "TZImagePickerController.h"
#import "TZPhotoPreviewController.h"
@interface TZVideoPlayerController () {
AVPlayer *_player;
UIButton *_playButton;
UIImage *_cover;
UIView *_toolBar;
UIButton *_okButton;
UIProgressView *_progress;
}
@end
@implementation TZVideoPlayerController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
self.navigationItem.title = @"视频预览";
[self configMoviePlayer];
}
- (void)configMoviePlayer {
[[TZImageManager manager] getPhotoWithAsset:_model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
_cover = photo;
}];
[[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
_player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
playerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:playerLayer];
[self addProgressObserver];
[self configPlayButton];
[self configBottomToolBar];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:AVPlayerItemDidPlayToEndTimeNotification object:_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.frame = CGRectMake(0, 64, self.view.tz_width, self.view.tz_height - 64 - 44);
[_playButton setImage:[UIImage imageNamedFromMyBundle:@"MMVideoPreviewPlay.png"] forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageNamedFromMyBundle:@"MMVideoPreviewPlayHL.png"] forState:UIControlStateHighlighted];
[_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_playButton];
}
- (void)configBottomToolBar {
_toolBar = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.tz_height - 44, self.view.tz_width, 44)];
CGFloat rgb = 34 / 255.0;
_toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0];
_toolBar.alpha = 0.7;
_okButton = [UIButton buttonWithType:UIButtonTypeCustom];
_okButton.frame = CGRectMake(self.view.tz_width - 44 - 12, 0, 44, 44);
_okButton.titleLabel.font = [UIFont systemFontOfSize:16];
[_okButton addTarget:self action:@selector(okButtonClick) forControlEvents:UIControlEventTouchUpInside];
[_okButton setTitle:@"确定" forState:UIControlStateNormal];
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
[_okButton setTitleColor:imagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
[_toolBar addSubview:_okButton];
[self.view addSubview:_toolBar];
}
#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];
[self.navigationController setNavigationBarHidden:YES];
_toolBar.hidden = YES;
[_playButton setImage:nil forState:UIControlStateNormal];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = YES;
} else {
[self pausePlayerAndShowNaviBar];
}
}
- (void)okButtonClick {
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
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);
}
if (self.navigationController) {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
} else {
[self dismissViewControllerAnimated:YES completion:nil];
}
}
#pragma mark - Notification Method
- (void)pausePlayerAndShowNaviBar {
[_player pause];
_toolBar.hidden = NO;
[self.navigationController setNavigationBarHidden:NO];
[_playButton setImage:[UIImage imageNamedFromMyBundle:@"MMVideoPreviewPlay.png"] forState:UIControlStateNormal];
if (iOS7Later) [UIApplication sharedApplication].statusBarHidden = NO;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
//
// UIView+Layout.h
//
// Created by 谭真 on 15/2/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef enum : NSUInteger {
TZOscillatoryAnimationToBigger,
TZOscillatoryAnimationToSmaller,
} TZOscillatoryAnimationType;
@interface UIView (Layout)
@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
//
// UIView+Layout.m
//
// Created by 谭真 on 15/2/24.
// Copyright © 2015年 谭真. All rights reserved.
//
#import "UIView+Layout.h"
@implementation UIView (Layout)
- (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
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "add-photo_icon@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "add-photo_icon@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
......@@ -21,9 +21,27 @@
#import "PaymentTypeModel.h"
#import "SalesInputCommitView.h"
#import "ChooseProjectTableViewController.h"
#import "SaleInputPictureTableViewCell.h"
#import "TZImagePickerController.h"
#define kCellCount 20
#define kCellID @"SalesInputTableViewCell.h"
#define kPicCellId @"SaleInputPictureTableViewCell.h"
#define kAutoValue(value) (float)value / 375 * self.view.frame.size.width
/**
* colors
*/
#define kSysWhite [UIColor whiteColor]
//红 #ED1B23
#define kMainRedColor [UIColor colorWithRed:0.929 green:0.106 blue:0.137 alpha:1.000];
//蓝 #478FF1
#define kMainBlueColor [UIColor colorWithRed:0.278 green:0.561 blue:0.945 alpha:1.000];
//橙 #EA6402
#define kMainOrangeColor [UIColor colorWithRed:0.918 green:0.392 blue:0.008 alpha:1.000];
//紫 #5435AD
#define kMainPurpleColor [UIColor colorWithRed:0.329 green:0.208 blue:0.678 alpha:1.000];
#define kTabbarColor [UIColor colorWithWhite:0.973 alpha:1.000];
@interface SalesInputViewController ()<UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) SalesInputTopView *topView;
......@@ -35,7 +53,8 @@
@property (nonatomic, strong) NSMutableArray *arrPaymentType;
@property (nonatomic, strong) SalesInputCommitView *submitView;
@property (nonatomic, copy) NSString *todayTotalAmount;
@property (nonatomic, strong) NSMutableArray *arrPics;
@property (nonatomic, strong) NSMutableArray *selectedAssets;
@end
@implementation SalesInputViewController
......@@ -89,39 +108,129 @@ ON_WILL_APPEAR( signal )
- (void)setUpTableView {
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 125, SCREEN_WIDTH, SCREEN_HEIGHT - self.topView.bottom - 70) style:UITableViewStylePlain];
self.tableView.contentInset = UIEdgeInsetsMake(179, 0, 0, 0);
// self.tableView.contentInset = UIEdgeInsetsMake(179, 0, 0, 0);
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.tableView registerNib:[UINib nibWithNibName:@"SalesInputTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kCellID];
[self.tableView registerNib:[UINib nibWithNibName:@"SaleInputPictureTableViewCell" bundle:nil] forCellReuseIdentifier:kPicCellId];
[self.view addSubview:self.tableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.arrPaymentType.count;
if (section == 0) {
return self.arrPaymentType.count;
}else{
return self.arrPics.count % 2 != 0 ? self.arrPics.count / 2 + 1: self.arrPics.count / 2; //有奇数个元素
}
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *view = [self viewWithNibName:@"SaleInputPictureCellHeader"];
return view;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if (section == 0) {
return CGFLOAT_MIN;
}else{
return 50;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SalesInputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID forIndexPath:indexPath];
cell.paymentType.text = [self.arrPaymentType[indexPath.row] name];
[cell cellWithArray:[self getCellDataArrWithIndexPath:indexPath]];
WS(weakSelf)
cell.updateCellData = ^(NSArray *dataArr){
[weakSelf.cellDataDic setObject:dataArr forKey:indexPath];
[weakSelf countTotalMonney];
};
if (indexPath.section == 0) {
SalesInputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID forIndexPath:indexPath];
cell.paymentType.text = [self.arrPaymentType[indexPath.row] name];
[cell cellWithArray:[self getCellDataArrWithIndexPath:indexPath]];
WS(weakSelf);
cell.updateCellData = ^(NSArray *dataArr){
[weakSelf.cellDataDic setObject:dataArr forKey:indexPath];
[weakSelf countTotalMonney];
};
return cell;
}else{
SaleInputPictureTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPicCellId forIndexPath:indexPath];
[cell setUpCellWithPictureArr:self.arrPics indexPath:indexPath];
cell.addPicBlock = ^(NSInteger tag){
[self pushImagePickerController];
};
cell.seePicBlock = ^(NSInteger tag){
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithSelectedAssets:_selectedAssets selectedPhotos:_arrPics index:tag];
imagePickerVc.allowPickingOriginalPhoto = NO;
imagePickerVc.isSelectOriginalPhoto = NO;
[imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
_selectedAssets = [NSMutableArray arrayWithArray:assets];
_arrPics = [NSMutableArray arrayWithArray:photos];
[self.tableView reloadData];
}];
[self presentViewController:imagePickerVc animated:YES completion:nil];
};
return cell;
}
}
return cell;
#pragma mark - TZImagePickerController
- (void)pushImagePickerController {
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:5 delegate:nil];
#pragma mark - 四类个性化设置,这些参数都可以不传,此时会走默认设置
imagePickerVc.isSelectOriginalPhoto = NO;
// 1.如果你需要将拍照按钮放在外面,不要传这个参数
imagePickerVc.selectedAssets = _selectedAssets; // optional, 可选的
// imagePickerVc.allowTakePicture = self.showTakePhotoBtnSwitch.isOn; // 在内部显示拍照按钮
// 2. Set the appearance
// 2. 在这里设置imagePickerVc的外观
imagePickerVc.navigationBar.barTintColor = kMainOrangeColor;
// imagePickerVc.oKButtonTitleColorDisabled = [UIColor lightGrayColor];
imagePickerVc.oKButtonTitleColorNormal = kMainOrangeColor;
// 3. Set allow picking video & photo & originalPhoto or not
// 3. 设置是否可以选择视频/图片/原图
// imagePickerVc.allowPickingVideo = self.allowPickingVideoSwitch.isOn;
// imagePickerVc.allowPickingImage = self.allowPickingImageSwitch.isOn;
imagePickerVc.allowPickingOriginalPhoto = NO;
//
// // 4. 照片排列按修改时间升序
// imagePickerVc.sortAscendingByModificationDate = self.sortAscendingSwitch.isOn;
#pragma mark - 到这里为止
// You can get the photos by block, the same as by delegate.
// 你可以通过block或者代理,来得到用户选择的照片.
[imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
_selectedAssets = [NSMutableArray arrayWithArray:assets];
_arrPics = [NSMutableArray arrayWithArray:photos];
[_arrPics addObject:[UIImage imageNamed:@"add-photo_icon"]];
[self.tableView reloadData];
}];
[self presentViewController:imagePickerVc animated:YES completion:nil];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
if (indexPath.section == 0) {
return 50;
}else{
return kAutoValue(150);
}
}
- (void)setUpNavigationBar {
......@@ -166,8 +275,7 @@ ON_WILL_APPEAR( signal )
- (void)setUpTotalView {
self.totalView = [self viewWithNibName:@"SalesInputTotalView"];
self.totalView.frame = CGRectMake(0, -179, SCREEN_WIDTH, 179);
[self.tableView addSubview:self.totalView];
self.tableView.tableHeaderView = self.totalView;
}
......@@ -367,6 +475,19 @@ ON_WILL_APPEAR( signal )
return myDictionary;
}
- (NSMutableArray *)arrPics {
if (!_arrPics) {
_arrPics = [NSMutableArray array];
[_arrPics addObject:[UIImage imageNamed:@"add-photo_icon"]];
}
return _arrPics;
}
/** 添加选择的照片 */
- (void)addPic:(UIImage *)image {
[self.arrPics insertObject:image atIndex:self.arrPics.count - 1];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9532" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clipsSubviews="YES" contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="333" height="57"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="照片附件" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vKU-7C-kxt">
<rect key="frame" x="16" y="17" width="76" height="23"/>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<color key="textColor" red="0.95294117647058818" green="0.4392156862745098" blue="0.062745098039215685" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="vKU-7C-kxt" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="YAe-pd-3B6"/>
<constraint firstItem="vKU-7C-kxt" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="eCl-UR-pSr"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="342.5" y="304.5"/>
</view>
</objects>
</document>
//
// SaleInputPictureTableViewCell.h
// RealEstateManagement
//
// Created by Z on 16/6/28.
// Copyright © 2016年 上海勾芒信息科技. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void (^actionBlock)(NSInteger);
@interface SaleInputPictureTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIButton *btnLeft;
@property (weak, nonatomic) IBOutlet UIButton *btnRight;
@property (nonatomic, copy) actionBlock addPicBlock;
@property (nonatomic, copy) actionBlock seePicBlock;
- (void)setUpCellWithPictureArr:(NSArray *)arrPic indexPath:(NSIndexPath *)indexPath;
@end
//
// SaleInputPictureTableViewCell.m
// RealEstateManagement
//
// Created by Z on 16/6/28.
// Copyright © 2016年 上海勾芒信息科技. All rights reserved.
//
#import "SaleInputPictureTableViewCell.h"
@interface SaleInputPictureTableViewCell ()
@property (nonatomic, strong) NSMutableArray *arrPictures;
@end
@implementation SaleInputPictureTableViewCell
- (void)awakeFromNib {
self.btnLeft.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.btnRight.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.selectionStyle = UITableViewCellSelectionStyleNone;
// Initialization code
}
- (void)setUpCellWithPictureArr:(NSArray *)arrPic indexPath:(NSIndexPath *)indexPath {
self.arrPictures = arrPic;
[self.btnLeft setImage:arrPic[indexPath.row * 2] forState:UIControlStateNormal];
self.btnLeft.tag = indexPath.row * 2;
self.btnRight.hidden = YES;
if (indexPath.row * 2 + 1 <= arrPic.count - 1) {
[self.btnRight setImage:arrPic[indexPath.row * 2 + 1] forState:UIControlStateNormal];
self.btnRight.tag = indexPath.row * 2 + 1;
self.btnRight.hidden = NO;
}
[self.btnLeft addTarget:self action:@selector(actionSeePic:) forControlEvents:UIControlEventTouchUpInside];
[self.btnRight addTarget:self action:@selector(actionSeePic:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)actionSeePic:(UIButton *)btn {
// CLog(@"%ld", btn.tag);
if (btn.tag == self.arrPictures.count - 1) {
self.addPicBlock(0);
}else{
self.seePicBlock(btn.tag);
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9532" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="110" id="KGk-i7-Jjw" customClass="SaleInputPictureTableViewCell">
<rect key="frame" x="0.0" y="0.0" width="320" height="110"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="109"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Pbc-cV-k3t">
<rect key="frame" x="160" y="0.0" width="1" height="109"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" constant="1" id="bxO-0c-aSg"/>
</constraints>
</view>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XI0-hY-18L">
<rect key="frame" x="16" y="16" width="136" height="77"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.borderWidth">
<integer key="value" value="1"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="layer.borderColorFromUI">
<color key="value" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="0.69905048076923082" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</button>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yMx-iz-kxN">
<rect key="frame" x="169" y="16" width="135" height="77"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.borderWidth">
<integer key="value" value="1"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="layer.borderColorFromUI">
<color key="value" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="0.70191105769230766" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</button>
</subviews>
<constraints>
<constraint firstItem="yMx-iz-kxN" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="16" id="32F-rn-yLl"/>
<constraint firstItem="Pbc-cV-k3t" firstAttribute="centerX" secondItem="H2p-sc-9uM" secondAttribute="centerX" id="BCF-XG-YpW"/>
<constraint firstAttribute="bottom" secondItem="yMx-iz-kxN" secondAttribute="bottom" constant="16" id="Ng5-UN-AKy"/>
<constraint firstAttribute="trailing" secondItem="yMx-iz-kxN" secondAttribute="trailing" constant="16" id="P5t-B7-nsE"/>
<constraint firstItem="XI0-hY-18L" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="16" id="Rch-Kq-kdz"/>
<constraint firstItem="yMx-iz-kxN" firstAttribute="leading" secondItem="Pbc-cV-k3t" secondAttribute="trailing" constant="8" id="Sdw-RY-AZR"/>
<constraint firstAttribute="bottom" secondItem="XI0-hY-18L" secondAttribute="bottom" constant="16" id="XfH-eC-g8W"/>
<constraint firstAttribute="bottom" secondItem="Pbc-cV-k3t" secondAttribute="bottom" id="fxy-Tr-z24"/>
<constraint firstItem="XI0-hY-18L" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="k25-sK-Hi5"/>
<constraint firstItem="Pbc-cV-k3t" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="qJO-3M-Q2J"/>
<constraint firstItem="Pbc-cV-k3t" firstAttribute="leading" secondItem="XI0-hY-18L" secondAttribute="trailing" constant="8" id="yLz-za-PTT"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="btnLeft" destination="XI0-hY-18L" id="dP9-3K-9kU"/>
<outlet property="btnRight" destination="yMx-iz-kxN" id="Hfo-yU-UP7"/>
</connections>
<point key="canvasLocation" x="263" y="262"/>
</tableViewCell>
</objects>
</document>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment