Jelajahi Sumber

Merge branch 'master' of http://gogs.hnwmzp.cn/nzk1/Asteria-APP

# Conflicts:
#	Asteria/Product/CTMediatoaTargets/CTMediator+ASTargerts.m
iOS-Abel 2 tahun lalu
induk
melakukan
dde2f51dff
100 mengubah file dengan 49915 tambahan dan 27137 penghapusan
  1. 45 11
      Asteria.xcodeproj/project.pbxproj
  2. 8 0
      Asteria.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  3. 0 0
      Asteria/ASUI/ColorDefine.h
  4. 0 0
      Asteria/ASUI/Extensions/UIColor+AS.h
  5. 0 0
      Asteria/ASUI/Extensions/UIColor+AS.m
  6. 0 0
      Asteria/ASUI/Extensions/UIView+PublicInit.h
  7. 0 0
      Asteria/ASUI/Extensions/UIView+PublicInit.m
  8. 0 0
      Asteria/ASUI/SizeDefine.h
  9. 0 0
      Asteria/ASUI/Tools/LYTools.h
  10. 0 0
      Asteria/ASUI/Tools/LYTools.m
  11. 6 3
      Asteria/Fuction/AMoule/AViewController.m
  12. 23 0
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/Contents.json
  13. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/组 8031.png
  14. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/组 8031@2x.png
  15. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/组 8031@3x.png
  16. 23 0
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/Contents.json
  17. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/组 6866.png
  18. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/组 6866@2x.png
  19. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/组 6866@3x.png
  20. 23 0
      Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/Contents.json
  21. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/组 10988.png
  22. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/组 10988@2x.png
  23. TEMPAT SAMPAH
      Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/组 10988@3x.png
  24. 3 1
      Asteria/Fuction/Login/BaseView/PassWordSecureBtnV.m
  25. 16 0
      Asteria/Fuction/Login/V/LoginSignUpV.h
  26. 310 0
      Asteria/Fuction/Login/V/LoginSignUpV.m
  27. 3 1
      Asteria/Fuction/Login/V/LoginThirdAuthV.m
  28. 0 0
      Asteria/Fuction/Login/VC/AS_LoginC.h
  29. 64 4
      Asteria/Fuction/Login/AS_LoginC.m
  30. 16 0
      Asteria/Fuction/Login/VC/AS_SignUpC.h
  31. 97 0
      Asteria/Fuction/Login/VC/AS_SignUpC.m
  32. 1 1
      Asteria/Fuction/UserCenter/Target_userCenter.h
  33. 10 1
      Asteria/PreFixHeader.h
  34. 8 0
      Asteria/CTMediatoaTargets/CTMediator+ASTargerts.h
  35. 1 0
      Asteria/CTMediatoaTargets/CTMediator+ASTargerts.m
  36. 0 0
      Asteria/Product/Config/Font/Roboto/LICENSE.txt
  37. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Black.ttf
  38. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-BlackItalic.ttf
  39. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Bold.ttf
  40. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-BoldItalic.ttf
  41. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Italic.ttf
  42. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Light.ttf
  43. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-LightItalic.ttf
  44. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Medium.ttf
  45. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-MediumItalic.ttf
  46. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Regular.ttf
  47. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-Thin.ttf
  48. 0 0
      Asteria/Product/Config/Font/Roboto/Roboto-ThinItalic.ttf
  49. 7 5
      Asteria/Config/ProjectConfig.h
  50. 16 0
      Asteria/ThirdPartService.h
  51. 84 0
      Asteria/ThirdPartService.m
  52. 20 1
      Podfile.lock
  53. 51 0
      Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressModel.h
  54. 24 0
      Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressModel.m
  55. 13634 0
      Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressPickerView.bundle/BRCity.json
  56. 127 0
      Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressPickerView.h
  57. 562 0
      Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressPickerView.m
  58. 17 0
      Pods/BRPickerView/BRPickerView/BRPickerView.h
  59. 76 0
      Pods/BRPickerView/BRPickerView/Base/BRBaseView.h
  60. 398 0
      Pods/BRPickerView/BRPickerView/Base/BRBaseView.m
  61. 251 0
      Pods/BRPickerView/BRPickerView/Base/BRPickerStyle.h
  62. 494 0
      Pods/BRPickerView/BRPickerView/Base/BRPickerStyle.m
  63. 35 0
      Pods/BRPickerView/BRPickerView/Base/BRPickerView.bundle/en.lproj/Localizable.strings
  64. 35 0
      Pods/BRPickerView/BRPickerView/Base/BRPickerView.bundle/zh-Hans.lproj/Localizable.strings
  65. 35 0
      Pods/BRPickerView/BRPickerView/Base/BRPickerView.bundle/zh-Hant.lproj/Localizable.strings
  66. 87 0
      Pods/BRPickerView/BRPickerView/Base/BRPickerViewMacro.h
  67. 26 0
      Pods/BRPickerView/BRPickerView/Base/NSBundle+BRPickerView.h
  68. 68 0
      Pods/BRPickerView/BRPickerView/Base/NSBundle+BRPickerView.m
  69. 111 0
      Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView+BR.h
  70. 755 0
      Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView+BR.m
  71. 274 0
      Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView.h
  72. 1965 0
      Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView.m
  73. 126 0
      Pods/BRPickerView/BRPickerView/DatePickerView/NSDate+BRPickerView.h
  74. 400 0
      Pods/BRPickerView/BRPickerView/DatePickerView/NSDate+BRPickerView.m
  75. 37 0
      Pods/BRPickerView/BRPickerView/StringPickerView/BRResultModel.h
  76. 41 0
      Pods/BRPickerView/BRPickerView/StringPickerView/BRResultModel.m
  77. 191 0
      Pods/BRPickerView/BRPickerView/StringPickerView/BRStringPickerView.h
  78. 571 0
      Pods/BRPickerView/BRPickerView/StringPickerView/BRStringPickerView.m
  79. 21 0
      Pods/BRPickerView/LICENSE
  80. 530 0
      Pods/BRPickerView/README.md
  81. 6 0
      Pods/Local Podspecs/WMBase.podspec.json
  82. 20 1
      Pods/Manifest.lock
  83. 27820 27102
      Pods/Pods.xcodeproj/project.pbxproj
  84. 26 0
      Pods/Target Support Files/BRPickerView/BRPickerView-Info.plist
  85. 5 0
      Pods/Target Support Files/BRPickerView/BRPickerView-dummy.m
  86. 12 0
      Pods/Target Support Files/BRPickerView/BRPickerView-prefix.pch
  87. 28 0
      Pods/Target Support Files/BRPickerView/BRPickerView-umbrella.h
  88. 13 0
      Pods/Target Support Files/BRPickerView/BRPickerView.debug.xcconfig
  89. 6 0
      Pods/Target Support Files/BRPickerView/BRPickerView.modulemap
  90. 13 0
      Pods/Target Support Files/BRPickerView/BRPickerView.release.xcconfig
  91. 51 0
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.markdown
  92. 63 0
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.plist
  93. 3 3
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.debug.xcconfig
  94. 3 3
      Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.release.xcconfig
  95. 51 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.markdown
  96. 63 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.plist
  97. 2 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-input-files.xcfilelist
  98. 2 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-output-files.xcfilelist
  99. 2 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-input-files.xcfilelist
  100. 0 0
      Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-output-files.xcfilelist

+ 45 - 11
Asteria.xcodeproj/project.pbxproj

@@ -58,6 +58,9 @@
 		9A8DD8C52A0B8F1700573324 /* As_GoodsSizeC.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8DD8C42A0B8F1700573324 /* As_GoodsSizeC.m */; };
 		9A8DD8C82A0B93F700573324 /* GoodsDetailsVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A8DD8C72A0B93F600573324 /* GoodsDetailsVM.m */; };
 		9ACBEC212A14585300A8F97A /* CTMediator+ASTargerts.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ACBEC202A14585300A8F97A /* CTMediator+ASTargerts.m */; };
+		9ACBEC252A14707400A8F97A /* AS_SignUpC.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ACBEC242A14707400A8F97A /* AS_SignUpC.m */; };
+		9ACBEC282A1472AF00A8F97A /* LoginSignUpV.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ACBEC272A1472AF00A8F97A /* LoginSignUpV.m */; };
+		9ACBEC2B2A14CCA300A8F97A /* ThirdPartService.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ACBEC292A14CCA200A8F97A /* ThirdPartService.m */; };
 		9AD3459E2A08D545005CA070 /* GoodsDetailSrcView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD3459D2A08D545005CA070 /* GoodsDetailSrcView.m */; };
 		9AD345A72A08D571005CA070 /* TYPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD345A32A08D571005CA070 /* TYPageControl.m */; };
 		9AD345A82A08D571005CA070 /* TYCyclePagerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD345A42A08D571005CA070 /* TYCyclePagerView.m */; };
@@ -220,6 +223,12 @@
 		9A8DD8C72A0B93F600573324 /* GoodsDetailsVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoodsDetailsVM.m; sourceTree = "<group>"; };
 		9ACBEC1F2A14585300A8F97A /* CTMediator+ASTargerts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CTMediator+ASTargerts.h"; sourceTree = "<group>"; };
 		9ACBEC202A14585300A8F97A /* CTMediator+ASTargerts.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CTMediator+ASTargerts.m"; sourceTree = "<group>"; };
+		9ACBEC232A14707400A8F97A /* AS_SignUpC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AS_SignUpC.h; sourceTree = "<group>"; };
+		9ACBEC242A14707400A8F97A /* AS_SignUpC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AS_SignUpC.m; sourceTree = "<group>"; };
+		9ACBEC262A1472AF00A8F97A /* LoginSignUpV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoginSignUpV.h; sourceTree = "<group>"; };
+		9ACBEC272A1472AF00A8F97A /* LoginSignUpV.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LoginSignUpV.m; sourceTree = "<group>"; };
+		9ACBEC292A14CCA200A8F97A /* ThirdPartService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThirdPartService.m; sourceTree = "<group>"; };
+		9ACBEC2A2A14CCA200A8F97A /* ThirdPartService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThirdPartService.h; sourceTree = "<group>"; };
 		9AD3459C2A08D545005CA070 /* GoodsDetailSrcView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GoodsDetailSrcView.h; sourceTree = "<group>"; };
 		9AD3459D2A08D545005CA070 /* GoodsDetailSrcView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoodsDetailSrcView.m; sourceTree = "<group>"; };
 		9AD345A12A08D571005CA070 /* TYCyclePagerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TYCyclePagerView.h; sourceTree = "<group>"; };
@@ -304,7 +313,7 @@
 		9AD3461C2A08D6EF005CA070 /* GoodsInformationM.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoodsInformationM.m; sourceTree = "<group>"; };
 		9AD3461E2A08E30E005CA070 /* SelectVCollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SelectVCollectionViewCell.h; sourceTree = "<group>"; };
 		9AD3461F2A08E30E005CA070 /* SelectVCollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SelectVCollectionViewCell.m; sourceTree = "<group>"; };
-		9AD346212A08E828005CA070 /* ProjectConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProjectConfig.h; sourceTree = "<group>"; };
+		9AD346212A08E828005CA070 /* ProjectConfigDefine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProjectConfigDefine.h; sourceTree = "<group>"; };
 		9AD364C42A05E73E00452C7A /* AS_GoodsDetailsC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AS_GoodsDetailsC.h; sourceTree = "<group>"; };
 		9AD364C52A05E73E00452C7A /* AS_GoodsDetailsC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AS_GoodsDetailsC.m; sourceTree = "<group>"; };
 		9AD364CF2A05EC7800452C7A /* AS_TabBarViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AS_TabBarViewController.h; sourceTree = "<group>"; };
@@ -364,9 +373,12 @@
 		814F5CF12A11B337003847A9 /* ASUI */ = {
 			isa = PBXGroup;
 			children = (
+				81C3B45029F669C900D79294 /* ColorDefine.h */,
+				8199001E2A0206F7006FE68C /* SizeDefine.h */,
+				81C3B44B29F6691300D79294 /* Extensions */,
+				8199001F2A020A4F006FE68C /* Tools */,
 				81E257F72A122AAB004EEF71 /* Icons */,
 				81E257EF2A12093A004EEF71 /* CustomView */,
-				814F5CF62A11B76F003847A9 /* Font */,
 				814F5CF22A11B35B003847A9 /* ASUserAvater */,
 				814F5CF02A11B317003847A9 /* SimpleBase */,
 			);
@@ -433,17 +445,16 @@
 		8172449C29F3B2ED005FA9C9 /* Asteria */ = {
 			isa = PBXGroup;
 			children = (
-				9ACBEC1E2A1457E800A8F97A /* CTMediatoaTargets */,
+				9A2646BA2A187B6100CBFBDC /* Product */,
 				9A2027F32A137B6A00FF4DAF /* Asteria.entitlements */,
 				81C3B44F29F6699900D79294 /* PreFixHeader.h */,
 				9A8DD8CC2A0B9E0C00573324 /* Assets */,
 				9AD364CE2A05EC4500452C7A /* Tabber */,
-				9AD364CD2A05EC2700452C7A /* Config */,
 				9AD364CC2A05EBE800452C7A /* Fuction */,
-				8199001F2A020A4F006FE68C /* Tools */,
-				81C3B44B29F6691300D79294 /* Extensions */,
 				8172449D29F3B2ED005FA9C9 /* AppDelegate.h */,
 				8172449E29F3B2ED005FA9C9 /* AppDelegate.m */,
+				9ACBEC2A2A14CCA200A8F97A /* ThirdPartService.h */,
+				9ACBEC292A14CCA200A8F97A /* ThirdPartService.m */,
 				814F5CF12A11B337003847A9 /* ASUI */,
 				817244A929F3B2EE005FA9C9 /* Assets.xcassets */,
 				817244AB29F3B2EE005FA9C9 /* LaunchScreen.storyboard */,
@@ -550,6 +561,15 @@
 			path = CutomBottomBar;
 			sourceTree = "<group>";
 		};
+		9A2646BA2A187B6100CBFBDC /* Product */ = {
+			isa = PBXGroup;
+			children = (
+				9AD364CD2A05EC2700452C7A /* Config */,
+				9ACBEC1E2A1457E800A8F97A /* CTMediatoaTargets */,
+			);
+			path = Product;
+			sourceTree = "<group>";
+		};
 		9A337E342A04EE1A00D058A5 /* BViewController */ = {
 			isa = PBXGroup;
 			children = (
@@ -603,12 +623,11 @@
 		9A5C64522A11E58F00CBB185 /* Login */ = {
 			isa = PBXGroup;
 			children = (
+				9ACBEC222A1464CD00A8F97A /* VC */,
 				9A65DE4E2A132BDF00BB1269 /* V */,
 				9AD6A5462A123799001DE3D9 /* Target */,
 				9AD6A53A2A120C56001DE3D9 /* Assets */,
 				9AD6A53F2A1218D0001DE3D9 /* BaseView */,
-				9A5C64562A12064300CBB185 /* AS_LoginC.h */,
-				9A5C64572A12064300CBB185 /* AS_LoginC.m */,
 			);
 			path = Login;
 			sourceTree = "<group>";
@@ -617,7 +636,9 @@
 			isa = PBXGroup;
 			children = (
 				9A65DE4F2A132FB700BB1269 /* LoginThirdAuthV.h */,
+				9ACBEC262A1472AF00A8F97A /* LoginSignUpV.h */,
 				9A65DE502A132FB700BB1269 /* LoginThirdAuthV.m */,
+				9ACBEC272A1472AF00A8F97A /* LoginSignUpV.m */,
 			);
 			path = V;
 			sourceTree = "<group>";
@@ -649,6 +670,17 @@
 			path = CTMediatoaTargets;
 			sourceTree = "<group>";
 		};
+		9ACBEC222A1464CD00A8F97A /* VC */ = {
+			isa = PBXGroup;
+			children = (
+				9A5C64562A12064300CBB185 /* AS_LoginC.h */,
+				9A5C64572A12064300CBB185 /* AS_LoginC.m */,
+				9ACBEC232A14707400A8F97A /* AS_SignUpC.h */,
+				9ACBEC242A14707400A8F97A /* AS_SignUpC.m */,
+			);
+			path = VC;
+			sourceTree = "<group>";
+		};
 		9AD3459F2A08D55D005CA070 /* Banner */ = {
 			isa = PBXGroup;
 			children = (
@@ -844,9 +876,8 @@
 		9AD364CD2A05EC2700452C7A /* Config */ = {
 			isa = PBXGroup;
 			children = (
-				9AD346212A08E828005CA070 /* ProjectConfig.h */,
-				81C3B45029F669C900D79294 /* ColorDefine.h */,
-				8199001E2A0206F7006FE68C /* SizeDefine.h */,
+				814F5CF62A11B76F003847A9 /* Font */,
+				9AD346212A08E828005CA070 /* ProjectConfigDefine.h */,
 			);
 			path = Config;
 			sourceTree = "<group>";
@@ -1159,6 +1190,7 @@
 				81C3B44A29F6661500D79294 /* ASBaseNavController.m in Sources */,
 				9AD3460C2A08D60F005CA070 /* ZFVolumeBrightnessView.m in Sources */,
 				9AD346072A08D60F005CA070 /* UIViewController+ZFPlayerRotation.m in Sources */,
+				9ACBEC2B2A14CCA300A8F97A /* ThirdPartService.m in Sources */,
 				9AD346142A08D60F005CA070 /* ZFSpeedLoadingView.m in Sources */,
 				9AD346062A08D60F005CA070 /* ZFReachabilityManager.m in Sources */,
 				9AD345FE2A08D60F005CA070 /* UIScrollView+ZFPlayer.m in Sources */,
@@ -1189,9 +1221,11 @@
 				9A5C64582A12064300CBB185 /* AS_LoginC.m in Sources */,
 				9AD345FD2A08D60F005CA070 /* ZFPersentInteractiveTransition.m in Sources */,
 				9AD345FC2A08D60F005CA070 /* ZFPlayerLogManager.m in Sources */,
+				9ACBEC252A14707400A8F97A /* AS_SignUpC.m in Sources */,
 				9AD346162A08D60F005CA070 /* UIImageView+ZFCache.m in Sources */,
 				9AD345A92A08D571005CA070 /* TYCyclePagerTransformLayout.m in Sources */,
 				81932E2B29F7539B007C37AF /* UIColor+AS.m in Sources */,
+				9ACBEC282A1472AF00A8F97A /* LoginSignUpV.m in Sources */,
 				9AD346152A08D60F005CA070 /* ZFPortraitControlView.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 8 - 0
Asteria.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?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>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

Asteria/Config/ColorDefine.h → Asteria/ASUI/ColorDefine.h


Asteria/Extensions/UIColor+AS.h → Asteria/ASUI/Extensions/UIColor+AS.h


Asteria/Extensions/UIColor+AS.m → Asteria/ASUI/Extensions/UIColor+AS.m


Asteria/Extensions/UIView+PublicInit.h → Asteria/ASUI/Extensions/UIView+PublicInit.h


Asteria/Extensions/UIView+PublicInit.m → Asteria/ASUI/Extensions/UIView+PublicInit.m


Asteria/Config/SizeDefine.h → Asteria/ASUI/SizeDefine.h


Asteria/Tools/LYTools.h → Asteria/ASUI/Tools/LYTools.h


Asteria/Tools/LYTools.m → Asteria/ASUI/Tools/LYTools.m


+ 6 - 3
Asteria/Fuction/AMoule/AViewController.m

@@ -47,9 +47,12 @@
     
 }
 -(void)buttonTap:(UIButton *)btn{
-    UIViewController *login = [[CTMediator sharedInstance] Login_LoginC:@{}];
-    login.modalPresentationStyle  =  UIModalPresentationFullScreen;
-    [self.navigationController presentViewController:login animated:YES completion:nil];
+    UIViewController *loginC = [[CTMediator sharedInstance] Login_LoginC:@{}];
+    
+    QMUINavigationController *uikitNavController = [[QMUINavigationController alloc] initWithRootViewController:loginC];
+    uikitNavController.navigationBar.hidden = YES;
+    uikitNavController.modalPresentationStyle =UIModalPresentationFullScreen;
+    [self.navigationController presentViewController:uikitNavController animated:YES completion:nil];
 }
 #pragma mark - getters and setters
 - (UIButton *)pushBViewControllerButton

+ 23 - 0
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "组 8031.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "组 8031@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "组 8031@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/组 8031.png


TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/组 8031@2x.png


TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido.imageset/组 8031@3x.png


+ 23 - 0
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "组 6866.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "组 6866@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "组 6866@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/组 6866.png


TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/组 6866@2x.png


TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_selectRido_select.imageset/组 6866@3x.png


+ 23 - 0
Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "组 10988.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "组 10988@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "组 10988@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/组 10988.png


TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/组 10988@2x.png


TEMPAT SAMPAH
Asteria/Fuction/Login/Assets/Login.xcassets/login_signup.imageset/组 10988@3x.png


+ 3 - 1
Asteria/Fuction/Login/BaseView/PassWordSecureBtnV.m

@@ -71,9 +71,11 @@ if (textField == self.xxx_passwordTF && self.xxx_passwordTF.secureTextEntry) {
     if (!_xxx_secureBtn) {
         _xxx_secureBtn = [UIButton buttonWithType:UIButtonTypeCustom];
         _xxx_secureBtn.frame = CGRectMake(KScreenWidth-40-50, 0,50 , 50);
-        [_xxx_secureBtn setTitle:@"VIEW" forState:UIControlStateNormal];
+        [_xxx_secureBtn setAttributedTitle:[[NSMutableAttributedString alloc] initWithString:@"VIEW"] forState:UIControlStateNormal];
         NSMutableAttributedString *attrSleStr = [[NSMutableAttributedString alloc] initWithString:@"VIEW"                                                                                    attributes:@{NSStrikethroughStyleAttributeName : @(NSUnderlineStyleSingle)}];
         [_xxx_secureBtn setAttributedTitle:attrSleStr forState:UIControlStateSelected];
+        [_xxx_secureBtn setTitleColor:[UIColor qmui_colorWithHexString:@"#000000"] forState:UIControlStateNormal];
+        _xxx_secureBtn.titleLabel.font = [UIFont fontWithName:Rob_Bold size:14];
         [_xxx_secureBtn addTarget:self action:@selector(xxx_changeSecure:) forControlEvents:UIControlEventTouchUpInside];
         _xxx_secureBtn.selected = NO;
         _xxx_secureBtn.backgroundColor = [UIColor clearColor];

+ 16 - 0
Asteria/Fuction/Login/V/LoginSignUpV.h

@@ -0,0 +1,16 @@
+//
+//  LoginSignUpV.h
+//  Asteria
+//
+//  Created by 王猛 on 2023/5/17.
+//
+
+#import <WMBase/WMBase.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface LoginSignUpV : TT_BaseV
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 310 - 0
Asteria/Fuction/Login/V/LoginSignUpV.m

@@ -0,0 +1,310 @@
+//
+//  LoginSignUpV.m
+//  Asteria
+//
+//  Created by 王猛 on 2023/5/17.
+//
+
+#import "LoginSignUpV.h"
+#import "PassWordSecureBtnV.h"
+#import "EamilTFmatchV.h"
+#import <BRPickerView/BRPickerView.h>
+
+@interface LoginSignUpV ()
+@property (nonatomic, strong) TT_CustonTF *xxx_firstName;
+@property (nonatomic, strong) TT_CustonTF *xxx_lasetName;
+@property (nonatomic, strong) EamilTFmatchV *xxx_regMmailV;
+
+
+@property (nonatomic, strong) PassWordSecureBtnV *xxx_regPassWord;
+@property (nonatomic, strong) UILabel *xxx_dateLab;
+@property (nonatomic, strong) UIButton *xxx_creatBtn;
+
+
+@property (nonatomic, strong) UIButton *xxx_subscribedBtn;
+@property (nonatomic, strong) QMUILabel *xxx_subscribedLab;
+
+@property (nonatomic, strong) YYLabel *xxx_ClickLab;
+@property (nonatomic, strong) UIButton *xxx_selectBtn;
+
+@property (nonatomic, strong) NSDate *birthdaySelectDate;
+
+
+@end
+
+@implementation LoginSignUpV
+
+- (void)tt_setupViews{
+    [self addSubview:self.xxx_firstName];
+    [self addSubview:self.xxx_lasetName];
+    [self addSubview:self.xxx_regMmailV];
+    [self addSubview:self.xxx_regPassWord];
+    [self addSubview:self.xxx_dateLab];
+    [self addSubview:self.xxx_creatBtn];
+    [self addSubview:self.xxx_subscribedBtn];
+    [self addSubview:self.xxx_subscribedLab];
+    [self addSubview:self.xxx_selectBtn];
+    [self addSubview:self.xxx_ClickLab];
+    
+    [self bringSubviewToFront:self.xxx_regMmailV];
+    
+    self.birthdaySelectDate = [NSDate date];
+}
+#pragma mark - **************** action ****************
+-(void)action_dateOfBirth{
+    UIViewController *topVC =  topViewController();
+    [topVC.view endEditing:YES];
+    BRDatePickerView *datePickerView = [[BRDatePickerView alloc]init];
+    datePickerView.pickerMode = BRDatePickerModeDate;
+    datePickerView.title = @"Please Select The Date Of Birth";
+    datePickerView.selectDate = self.birthdaySelectDate;
+    datePickerView.minDate = [NSDate br_setYear:1900 month:1 day:1];
+    datePickerView.maxDate = [NSDate date];
+    datePickerView.isAutoSelect = YES;
+    datePickerView.resultBlock = ^(NSDate *selectDate, NSString *selectValue) {
+        self.birthdaySelectDate = selectDate;
+        NSDateFormatter *formartter= [[NSDateFormatter alloc]init];
+        [formartter setDateFormat:@"MM/dd/yyyy"];
+        NSString *currentDateStr = [formartter stringFromDate:selectDate];
+        self.xxx_dateLab.text = currentDateStr;
+        self.xxx_dateLab.textColor = [UIColor qmui_colorWithHexString:@"#000000"];
+        NSLog(@"selectValue=%@", selectValue);
+        NSLog(@"selectDate=%@", selectDate);
+        NSLog(@"---------------------------------");
+        
+    };
+    [datePickerView show];
+}
+-(void)action_creatClick{
+    if (self.xxx_selectBtn.selected == NO) {
+        [self makeToast:@"Please select 'I Agree' to continue." duration:2 position:CSToastPositionCenter];
+        return;
+    }else if (self.xxx_firstName.text.length == 0) {
+        [self makeToast:@"Please Input FirstName" duration:2 position:CSToastPositionCenter];
+        return;
+    }else if (self.xxx_lasetName.text.length == 0){
+        [self makeToast:@"Please Input LastName" duration:2 position:CSToastPositionCenter];
+        return;
+    }else if(self.xxx_regMmailV.xxx_emailTF.text.length == 0 || ![Current_normalTool xxx_isValidateEmail:self.xxx_regMmailV.xxx_emailTF.text]){
+        [self makeToast:@"Please prvide an email address." duration:2 position:CSToastPositionCenter];
+        return;
+    }else if(self.xxx_regPassWord.xxx_passwordTF.text.length<6){
+        [self makeToast:@"Please set the correct password." duration:2 position:CSToastPositionCenter];
+        return;
+    }
+    
+    NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
+    [tempDic setObject:self.xxx_firstName.text forKey:@"firstName"];
+    [tempDic setObject:self.xxx_lasetName.text forKey:@"lastName"];
+    [tempDic setObject:self.xxx_regMmailV.xxx_emailTF.text forKey:@"email"];
+    [tempDic setObject:self.xxx_regPassWord.xxx_passwordTF.text forKey:@"password"];
+    BOOL isSubscribedSelect = self.xxx_subscribedBtn.selected;
+    [tempDic setObject:[NSString stringWithFormat:@"%d",isSubscribedSelect] forKey:@"is_subscribed"];
+    if ([self.xxx_dateLab.text isEqualToString:@"Date Of Birth"]) {
+        [tempDic setObject:@"" forKey:@"birthday"];
+    }else{
+        [tempDic setObject:self.xxx_dateLab.text forKey:@"birthday"];
+    }
+    [self generaltriggermethodType:1 data:tempDic];
+}
+-(void)action_xxx_subscribedBtnClick:(UIButton *)btn{
+    btn.selected = !btn.selected;
+}
+-(void)action_selectClick:(UIButton *)btn{
+    btn.selected = !btn.selected;
+}
+
+-(TT_CustonTF *)xxx_firstName{
+    if (!_xxx_firstName) {
+        _xxx_firstName = [TT_ControlTool FTT_ControlToolUITextFieldFrame:CGRectMake(20, 0, (KScreenWidth-60)/2, 50)
+                                                             PlaceHolder:@"* FIRST NAME"
+                                                             andLifImage:nil
+                                                           AndRightImage:nil
+                                                          LiftImageFrame:CGRectZero
+                                                         RightImageFrame:CGRectZero
+                                                                  AndTag:0
+                                                         AndKeyboardType:UIKeyboardTypeDefault
+                                                         clearButtonMode:UITextFieldViewModeAlways
+                                                        AndReturnKeyType:UIReturnKeyDone
+                                                           masksToBounds:YES
+                                                            conrenRadius:4
+                                                             BorderColor:[UIColor colorWithHexString:@"#000000"]
+                                                             BorderWidth:1];
+        _xxx_firstName.font = [UIFont fontWithName:Rob_Regular size:14];
+        _xxx_firstName.backgroundColor = [UIColor colorWithHexString:@"#FFFFFF"];
+    }
+    return _xxx_firstName;
+}
+
+-(TT_CustonTF *)xxx_lasetName{
+    if (!_xxx_lasetName) {
+        _xxx_lasetName = [TT_ControlTool FTT_ControlToolUITextFieldFrame:CGRectMake(CGRectGetMaxX(self.xxx_firstName.frame)+20, 0, (KScreenWidth-60)/2, 50)
+                                                             PlaceHolder:@"* LAST NAME"
+                                                             andLifImage:nil
+                                                           AndRightImage:nil
+                                                          LiftImageFrame:CGRectZero
+                                                         RightImageFrame:CGRectZero
+                                                                  AndTag:0
+                                                         AndKeyboardType:UIKeyboardTypeDefault
+                                                         clearButtonMode:UITextFieldViewModeAlways
+                                                        AndReturnKeyType:UIReturnKeyDone
+                                                           masksToBounds:YES
+                                                            conrenRadius:4
+                                                             BorderColor:[UIColor colorWithHexString:@"#000000"]
+                                                             BorderWidth:1];
+        _xxx_lasetName.font = [UIFont fontWithName:Rob_Regular size:14];
+        _xxx_lasetName.backgroundColor = [UIColor colorWithHexString:@"#FFFFFF"];
+    
+    }
+    return _xxx_lasetName;
+}
+-(EamilTFmatchV *)xxx_regMmailV{
+    if (!_xxx_regMmailV) {
+        _xxx_regMmailV = [[EamilTFmatchV alloc]initWithFrame:CGRectMake(0,CGRectGetMaxY(self.xxx_firstName.frame)+30 , KScreenWidth, 50)];
+    }
+    return _xxx_regMmailV;
+}
+-(PassWordSecureBtnV *)xxx_regPassWord{
+    if (!_xxx_regPassWord) {
+        _xxx_regPassWord = [[PassWordSecureBtnV alloc]initWithFrame:CGRectMake(20, CGRectGetMaxY(self.xxx_regMmailV.frame)+30, KScreenWidth-40, 50+20)];
+    }
+    return _xxx_regPassWord;
+}
+
+-(UILabel *)xxx_dateLab{
+    if (!_xxx_dateLab) {
+        _xxx_dateLab = [TT_ControlTool uc_ControlToolUILabelFrame:CGRectMake(20,CGRectGetMaxY(self.xxx_regPassWord.frame)+10, KScreenWidth-40, 50)
+                                                          AndTitle:@"DATE OF BIRTH"
+                                                       AndFontSize:14
+                                                     AndTitleColor:[UIColor colorWithHexString:@"#999999"]
+                                                     Numberoflines:1
+                                                     TextAlignment:NSTextAlignmentCenter
+                                          adjustesFontSizesTowidth:NO
+                                                     masksToBounds:YES
+                                                     conrenrRadius:4
+                                            userInteractionEnabled:YES
+                                                     tap_selector:@selector(action_dateOfBirth)
+                                                           object:self];
+        _xxx_dateLab.layer.borderColor = [UIColor colorWithHexString:@"#000000"].CGColor;
+        _xxx_dateLab.layer.borderWidth = 1;
+        _xxx_dateLab.text = @"DATE OF BIRTH";
+        
+    }
+    return _xxx_dateLab;
+}
+
+- (UIButton *)xxx_creatBtn {
+    if (!_xxx_creatBtn) {
+        _xxx_creatBtn = [TT_ControlTool FTT_ControlToolUIButtonFrame:CGRectMake(20,CGRectGetMaxY(self.xxx_dateLab.frame)+30 ,KScreenWidth-40,50)
+                                                                 taeget:self
+                                                                    sel:@selector(action_creatClick)
+                                                                    tag:0
+                                                               AntTitle:@"CREATE ACCOUNT"
+                                                              titleFont:17
+                                                             titleColor:[UIColor whiteColor]
+                                                               andImage:nil
+                                                           AndBackColor:nil
+                                                adjustsFontSizesTowidth:NO
+                                                          masksToBounds:YES
+                                                           conrenRadius:5
+                                                            BorderColor:nil
+                                                            BorderWidth:0
+                                              ContentHorizontalAligment:0];
+        _xxx_creatBtn.titleLabel.font = [UIFont fontWithName:Rob_Bold size:16];
+        _xxx_creatBtn.backgroundColor = ThemeColor;
+    }
+    return _xxx_creatBtn;
+}
+
+-(UIButton *)xxx_subscribedBtn{
+    if (!_xxx_subscribedBtn) {
+        _xxx_subscribedBtn = [TT_ControlTool FTT_ControlToolUIButtonFrame:CGRectMake(20,CGRectGetMaxY(self.xxx_creatBtn.frame)+20, 40, 40)
+                                                               taeget:self
+                                                                  sel:@selector(action_xxx_subscribedBtnClick:)
+                                                                  tag:0
+                                                             AntTitle:nil
+                                                            titleFont:0
+                                                           titleColor:nil
+                                                             andImage:@"login_selectRido"
+                                                         AndBackColor:[UIColor clearColor]
+                                              adjustsFontSizesTowidth:NO
+                                                        masksToBounds:NO
+                                                         conrenRadius:0
+                                                          BorderColor:nil
+                                                          BorderWidth:0
+                                            ContentHorizontalAligment:0];
+        [_xxx_subscribedBtn setImage:[UIImage imageNamed:@"login_selectRido_select"] forState:UIControlStateSelected];
+        _xxx_subscribedBtn.selected = YES;
+    }
+    return _xxx_subscribedBtn;
+}
+
+-(QMUILabel *)xxx_subscribedLab{
+    if (!_xxx_subscribedLab) {
+        _xxx_subscribedLab = [[QMUILabel alloc]init];
+        _xxx_subscribedLab.frame = CGRectMake(60,  CGRectGetMaxY(self.xxx_creatBtn.frame)+20, KScreenWidth - 20-20-40, 40);
+        NSString *string = @"I’d Like To Receive Emails Or Sms With Exclusive Discounts And News From Asteriahair";
+        _xxx_subscribedLab.text = string;
+        _xxx_subscribedLab.font = [UIFont fontWithName:Rob_Regular size:12];
+        _xxx_subscribedLab.textColor = [UIColor colorWithHexString:@"#000000"];
+    }
+    return _xxx_subscribedLab;
+}
+
+
+-(UIButton *)xxx_selectBtn{
+    if (!_xxx_selectBtn) {
+        _xxx_selectBtn = [TT_ControlTool FTT_ControlToolUIButtonFrame:CGRectMake(20,CGRectGetMaxY(self.xxx_subscribedBtn.frame)+10, 40, 40)
+                                                               taeget:self
+                                                                  sel:@selector(action_selectClick:)
+                                                                  tag:1
+                                                             AntTitle:nil
+                                                            titleFont:0
+                                                           titleColor:nil
+                                                             andImage:@"login_selectRido"
+                                                         AndBackColor:[UIColor clearColor]
+                                              adjustsFontSizesTowidth:NO
+                                                        masksToBounds:NO
+                                                         conrenRadius:0
+                                                          BorderColor:nil
+                                                          BorderWidth:0
+                                            ContentHorizontalAligment:0];
+        [_xxx_selectBtn setImage:[UIImage imageNamed:@"login_selectRido_select"] forState:UIControlStateSelected];
+    }
+    return _xxx_selectBtn;
+}
+-(YYLabel *)xxx_ClickLab{
+    if (!_xxx_ClickLab) {
+        _xxx_ClickLab = [YYLabel new];
+        _xxx_ClickLab.numberOfLines          = 0;
+        _xxx_ClickLab.textVerticalAlignment  = YYTextVerticalAlignmentCenter;
+        _xxx_ClickLab.frame = CGRectMake(60,  CGRectGetMaxY(self.xxx_subscribedBtn.frame)+10, KScreenWidth - 20-20-40, 40);
+        NSString *string = @"I Agree To Asteriahair Terms & Conditions And Privacy Policy.";
+        NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc] initWithString:string];
+
+        YYTextHighlight *protocolHightlight = [[YYTextHighlight alloc] init];
+        [attributed yy_setTextHighlight:protocolHightlight range:[string rangeOfString:@"Terms & Conditions"]];
+        [attributed yy_setTextUnderline:[YYTextDecoration decorationWithStyle:YYTextLineStyleSingle] range:[string rangeOfString:@"Terms & Conditions"]];
+        
+            
+        YYTextHighlight *layHightlight = [[YYTextHighlight alloc] init];
+        [attributed yy_setTextHighlight:layHightlight range:[string rangeOfString:@"Privacy Policy"]];
+        [attributed yy_setTextUnderline:[YYTextDecoration decorationWithStyle:YYTextLineStyleSingle] range:[string rangeOfString:@"Privacy Policy"]];
+        
+        [attributed yy_setColor:ThemeColor range:[string rangeOfString:@"Terms & Conditions"]];
+        [attributed yy_setColor:ThemeColor range:[string rangeOfString:@"Privacy Policy"]];
+        @weakify(self)
+        [attributed yy_setTextHighlightRange:[string rangeOfString:@"Terms & Conditions"] color:ThemeColor backgroundColor:[UIColor clearColor] tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
+            NSLog(@"----");
+        }];
+        [attributed yy_setTextHighlightRange:[string rangeOfString:@"Privacy Policy"] color:ThemeColor backgroundColor:[UIColor clearColor] tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
+            NSLog(@"----");
+        }];
+        _xxx_ClickLab.attributedText = attributed;
+        _xxx_ClickLab.font = [UIFont systemFontOfSize:12];
+    }
+    return _xxx_ClickLab;
+}
+
+
+@end

+ 3 - 1
Asteria/Fuction/Login/V/LoginThirdAuthV.m

@@ -63,7 +63,9 @@
     CGSize imageSize = authBtn.imageView.frame.size;
     CGSize titleSize = authBtn.titleLabel.frame.size;
     
-    authBtn.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 132-imageSize.width-titleSize.width-20);
+    authBtn.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 132-imageSize.width-titleSize.width-20-10);
+    authBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
+
     return authBtn;
 }
 

Asteria/Fuction/Login/AS_LoginC.h → Asteria/Fuction/Login/VC/AS_LoginC.h


+ 64 - 4
Asteria/Fuction/Login/AS_LoginC.m

@@ -11,6 +11,7 @@
 #import "LoginThirdAuthV.h"
 
 #import <AFNetworking/AFNetworking.h>
+#import "AS_SignUpC.h"
 
 
 
@@ -23,7 +24,6 @@
 
 
 
-
 @end
 
 @implementation AS_LoginC
@@ -43,7 +43,7 @@
     UIImageView *Hi_imgV = [[UIImageView alloc]init];
     UIImage *hiImg = [UIImage imageNamed:@"login_HI"];
     Hi_imgV.image = hiImg;
-    Hi_imgV.frame = CGRectMake(20, CGRectGetMaxY(logNav.frame)+60, KScreenWidth-40, hiImg.size.height/hiImg.size.width*(KScreenWidth-40));
+    Hi_imgV.frame = CGRectMake(20, CGRectGetMaxY(logNav.frame)+30, KScreenWidth-40, hiImg.size.height/hiImg.size.width*(KScreenWidth-40));
     [self.scrollview addSubview:Hi_imgV];
     
     [self.scrollview addSubview:self.xxx_emailTFV];
@@ -51,15 +51,21 @@
     [self.scrollview bringSubviewToFront:self.xxx_emailTFV];
     [self.scrollview addSubview:self.xxx_logInBtn];
     [self.scrollview addSubview:self.xxx_authV];
+    UIView *bottomV = [self load_bottom_v];
+    [self.scrollview addSubview:bottomV];
+    
+    
     
     self.xxx_emailTFV.mj_y = CGRectGetMaxY(Hi_imgV.frame)+35;
     self.xxx_passwordV.frame = CGRectFlatMake(20, CGRectGetMaxY(self.xxx_emailTFV.frame)+30, KScreenWidth-40, 50+20);
     self.xxx_logInBtn.frame = CGRectMake(20, CGRectGetMaxY(self.xxx_passwordV.frame)+10, KScreenWidth-40, 45);
     self.xxx_authV.mj_y = CGRectGetMaxY(self.xxx_logInBtn.frame)+30;
+    bottomV.mj_y = CGRectGetMaxY(self.xxx_authV.frame)+30;
 }
 
+
 -(void)handle_closeEvent:(UIButton *)btn{
-    [self dismissViewControllerAnimated:YES completion:nil];
+    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
 }
 -(void)handle_xxx_logInBtnEvent:(UIButton *)btn{//进行登录操作
     ///登录的跳转
@@ -99,8 +105,14 @@
     } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
          
     }];
- 
+}
+//注册页面
+-(void)handle_signUpEvent:(UIButton *)btn{
+    AS_SignUpC *upVC = [[AS_SignUpC alloc]init];
+    [self.navigationController pushViewController:upVC animated:YES];
     
+}
+-(void)handle_forgetBtnEvent:(UIButton *)btn{
     
 }
 
@@ -118,6 +130,8 @@
     headImg.image = bannerImg ;
     headImg.frame = CGRectMake((KScreenWidth- bannerImg.size.width)/2, (IPHONEX ? 44 : 20)+20 , bannerImg.size.width, bannerImg.size.height);
     [topView addSubview:headImg];
+    closeBtn.centerY = topView.centerY;
+    headImg.centerY = topView.centerY;
     return topView;
 }
 - (UIScrollView *)scrollview {
@@ -164,4 +178,50 @@
     return _xxx_authV;
 }
 
+
+-(UIView *)load_bottom_v{
+    UIView *bottomV = [[UIView alloc]initWithFrame:CGRectMake(20, 0, KScreenWidth-40, 32)];
+    QMUILabel *disLab = [[QMUILabel alloc]init];
+    disLab.text = @"Don't Have An Account?";
+    disLab.font = [UIFont fontWithName:Rob_Regular size:12];
+    [bottomV addSubview:disLab];
+    
+    UIButton *signUpBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+    signUpBtn.backgroundColor = [UIColor clearColor];
+    NSMutableAttributedString *sinAtr = [[NSMutableAttributedString alloc]initWithString:@"Sign Up" attributes:@{NSUnderlineStyleAttributeName: [NSNumber numberWithInteger:NSUnderlineStyleSingle]}];
+    [signUpBtn setAttributedTitle:sinAtr forState:UIControlStateNormal];
+    [signUpBtn addTarget:self action:@selector(handle_signUpEvent:) forControlEvents:UIControlEventTouchUpInside];
+    [signUpBtn setTitleColor:ThemeColor forState:UIControlStateNormal];
+    signUpBtn.titleLabel.font = [UIFont fontWithName:Rob_Regular size:12];
+    [bottomV addSubview:signUpBtn];
+    
+    UIButton *forgetBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+    forgetBtn.backgroundColor = [UIColor clearColor];
+    NSMutableAttributedString *forgotAtr = [[NSMutableAttributedString alloc]initWithString:@"Forgot Your Password" attributes:@{NSUnderlineStyleAttributeName: [NSNumber numberWithInteger:NSUnderlineStyleSingle]}];
+    [forgetBtn setAttributedTitle:forgotAtr forState:UIControlStateNormal];
+    [forgetBtn setTitleColor:ThemeColor forState:UIControlStateNormal];
+    forgetBtn.titleLabel.font = [UIFont fontWithName:Rob_Regular size:12];
+    [forgetBtn addTarget:self action:@selector(handle_forgetBtnEvent:) forControlEvents:UIControlEventTouchUpInside];
+    [bottomV addSubview:forgetBtn];
+    
+    [disLab mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.left.mas_equalTo(0);
+        make.height.mas_equalTo(16);
+    }];
+    [signUpBtn mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.centerY.equalTo(disLab);
+        make.left.equalTo(disLab.mas_right).offset(3);
+        make.height.mas_equalTo(20);
+        make.width.mas_equalTo(45);
+    }];
+    [forgetBtn mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.mas_equalTo(0);
+        make.top.equalTo(disLab.mas_bottom).offset(10);
+        make.height.mas_equalTo(15);
+        make.width.mas_equalTo(120);
+    }];
+    
+    return bottomV;
+}
+
 @end

+ 16 - 0
Asteria/Fuction/Login/VC/AS_SignUpC.h

@@ -0,0 +1,16 @@
+//
+//  AS_SignUpC.h
+//  Asteria
+//
+//  Created by 王猛 on 2023/5/17.
+//
+
+#import <WMBase/WMBase.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AS_SignUpC : UCMBaseC
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 97 - 0
Asteria/Fuction/Login/VC/AS_SignUpC.m

@@ -0,0 +1,97 @@
+//
+//  AS_SignUpC.m
+//  Asteria
+//
+//  Created by 王猛 on 2023/5/17.
+//
+
+#import "AS_SignUpC.h"
+#import "LoginSignUpV.h"
+
+
+@interface AS_SignUpC () <UIScrollViewDelegate>
+@property (nonatomic, strong) UIScrollView *scrollview;
+@property (nonatomic, strong) LoginSignUpV *xxx_signUpV;
+@end
+
+@implementation AS_SignUpC
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    self.customNavBar.hidden = YES;
+    self.navigationController.navigationBar.hidden = YES;
+    [self sub_veiwTapBlock];
+}
+
+- (void)initSubviews{
+    [super initSubviews];
+    [self.view addSubview:self.scrollview];
+    UIView *logNav = [self logNavView];
+    [self.scrollview addSubview:logNav];
+    UIImageView *Hi_imgV = [[UIImageView alloc]init];
+    UIImage *hiImg = [UIImage imageNamed:@"login_signup"];
+    Hi_imgV.image = hiImg;
+    [self.scrollview addSubview:Hi_imgV];
+    [self.scrollview addSubview:self.xxx_signUpV];
+    Hi_imgV.frame = CGRectMake(20, CGRectGetMaxY(logNav.frame)+30, KScreenWidth-40, hiImg.size.height/hiImg.size.width*(KScreenWidth-40));
+    self.xxx_signUpV.frame = CGRectMake(0, CGRectGetMaxY(Hi_imgV.frame)+30, KScreenWidth, 500);
+    [self.xxx_signUpV sizeToFit];
+    NSLog(@"------%@",self.xxx_signUpV);
+}
+- (void)sub_veiwTapBlock{
+    @weakify(self)
+    self.xxx_signUpV.ViewtapClose = ^(NSInteger num, id  _Nonnull data) {
+        @strongify(self)
+        [self reqNet_singup:(NSDictionary *)data];
+    };
+}
+//wm_todo 注册请求
+-(void)reqNet_singup:(NSDictionary *)dic{
+    
+}
+
+
+
+-(void)handle_closeEvent:(UIButton *)btn{
+    [self.navigationController popViewControllerAnimated:YES];
+}
+
+
+- (UIScrollView *)scrollview {
+    if (!_scrollview) {
+        _scrollview = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
+    }
+    return _scrollview;
+}
+
+
+
+-(UIView *)logNavView{
+    IPhoneXHeigh
+    UIView *topView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, KScreenWidth, securitytop_Y)];
+    UIButton *closeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+    [closeBtn setImage:[UIImage imageNamed:@"common_close"] forState:UIControlStateNormal];
+    [closeBtn addTarget:self action:@selector(handle_closeEvent:) forControlEvents:UIControlEventTouchUpInside];
+    closeBtn.frame = CGRectMake(20, 44, 44, 44);
+    [topView addSubview:closeBtn];
+    UIImageView *headImg = [[UIImageView alloc]init];
+    UIImage *bannerImg = [UIImage imageNamed:@"common_headLogo"];
+    headImg.image = bannerImg ;
+    headImg.frame = CGRectMake((KScreenWidth- bannerImg.size.width)/2, 20 , bannerImg.size.width, bannerImg.size.height);
+    [topView addSubview:headImg];
+    
+    closeBtn.centerY = topView.centerY;
+    headImg.centerY = topView.centerY;
+    
+    return topView;
+}
+
+- (LoginSignUpV *)xxx_signUpV {
+    if (!_xxx_signUpV) {
+        _xxx_signUpV = [[LoginSignUpV alloc] init];
+    }
+    return _xxx_signUpV;
+}
+
+@end

+ 1 - 1
Asteria/Fuction/UserCenter/Target_userCenter.h

@@ -10,7 +10,7 @@
 NS_ASSUME_NONNULL_BEGIN
 
 @interface Target_userCenter : NSObject
-
+- (UIViewController *)Action_getUserCenterVc:(NSDictionary *)params;
 @end
 
 NS_ASSUME_NONNULL_END

+ 10 - 1
Asteria/PreFixHeader.h

@@ -8,20 +8,29 @@
 #ifndef PreFixHeader_h
 #define PreFixHeader_h
 
-#import "ProjectConfig.h"
+
+
 #import "UIView+PublicInit.h"
 #import "UIColor+AS.h"
 #import "ColorDefine.h"
 #import "SizeDefine.h"
+
+//所有功能模块需要依赖的 项目(需变化)特定内容,相关内容和不变化的Base无关
+#import "ProjectConfigDefine.h"
 #import "CTMediator+ASTargerts.h"
+//当功能模块变成Pod后,需要的依赖
+//#import <Product/ProjectConfigDefine.h>
+//#import <WMBase/CTMediator+ASTargerts.h>
 
 ///基础库的导入内容
 #import <WMBase/WMBase.h>
+///Base库的依赖,放项目中加快build
 #import <MJExtension/MJExtension.h>
 #import <QMUIKit/QMUIKit.h>
 #import <SDWebImage/SDWebImage.h>
 #import <Masonry/Masonry.h>
 #import <Toast/Toast.h>
+#import <YYText/YYText.h>
 
 //#import <CTMediator/CTMediator.h>
 

+ 8 - 0
Asteria/CTMediatoaTargets/CTMediator+ASTargerts.h

@@ -5,12 +5,16 @@
 //  Created by 王猛 on 2023/5/17.
 //
 
+
+///wm_tips: 本质上只是一个方便方法,它对任何的 模块不存在任何依赖,项目在确定用的模块的时候,再次拿出来需要使用的方法
+///如果某个模块功能变化,只需要在它外面包一个Target-Action,就可以直接拿来用了。而且包Target-Action的过程中,不会对现有项目产生任何侵入性的影响。
 #import <CTMediator/CTMediator.h>
 #import <UIKit/UIKit.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
 @interface CTMediator (ASTargerts)
+
 -(UIViewController *)B_viewControllerWithContentText:(NSDictionary *)params;
 
 ///商品详情页面
@@ -18,7 +22,11 @@ NS_ASSUME_NONNULL_BEGIN
 
 ///登录页面
 -(UIViewController *)Login_LoginC:(NSDictionary *)params;
+
+
 -(UIViewController *)getUserCenterVc:(NSDictionary *)params;
+
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 1 - 0
Asteria/CTMediatoaTargets/CTMediator+ASTargerts.m

@@ -23,6 +23,7 @@
 }
 
 
+
 -(UIViewController *)getUserCenterVc:(NSDictionary *)params{
     return [self performTarget:@"userCenter" action:@"getUserCenterVc" params:params shouldCacheTarget:NO];
 }

Asteria/ASUI/Font/Roboto/LICENSE.txt → Asteria/Product/Config/Font/Roboto/LICENSE.txt


Asteria/ASUI/Font/Roboto/Roboto-Black.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Black.ttf


Asteria/ASUI/Font/Roboto/Roboto-BlackItalic.ttf → Asteria/Product/Config/Font/Roboto/Roboto-BlackItalic.ttf


Asteria/ASUI/Font/Roboto/Roboto-Bold.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Bold.ttf


Asteria/ASUI/Font/Roboto/Roboto-BoldItalic.ttf → Asteria/Product/Config/Font/Roboto/Roboto-BoldItalic.ttf


Asteria/ASUI/Font/Roboto/Roboto-Italic.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Italic.ttf


Asteria/ASUI/Font/Roboto/Roboto-Light.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Light.ttf


Asteria/ASUI/Font/Roboto/Roboto-LightItalic.ttf → Asteria/Product/Config/Font/Roboto/Roboto-LightItalic.ttf


Asteria/ASUI/Font/Roboto/Roboto-Medium.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Medium.ttf


Asteria/ASUI/Font/Roboto/Roboto-MediumItalic.ttf → Asteria/Product/Config/Font/Roboto/Roboto-MediumItalic.ttf


Asteria/ASUI/Font/Roboto/Roboto-Regular.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Regular.ttf


Asteria/ASUI/Font/Roboto/Roboto-Thin.ttf → Asteria/Product/Config/Font/Roboto/Roboto-Thin.ttf


Asteria/ASUI/Font/Roboto/Roboto-ThinItalic.ttf → Asteria/Product/Config/Font/Roboto/Roboto-ThinItalic.ttf


+ 7 - 5
Asteria/Config/ProjectConfig.h

@@ -1,19 +1,21 @@
 //
-//  ProjectConfig.h
+//  ProjectConfigDefine.h
 //  Asteria
 //
 //  Created by 王猛 on 2023/5/8.
 //
 
-#ifndef ProjectConfig_h
-#define ProjectConfig_h
+#ifndef ProjectConfigDefine_h
+#define ProjectConfigDefine_h
 
+///wm_tips 所有的pod模块的特定化依赖,每个Project修改,额、
 ///////正式服务器
 #define WebBase_Server @"https://app.westkiss.com/"
 #define Formal_Server @"https://app.westkiss.com/app-api/"
 
 ///AS 服务器
-#define  AS_Server @"http://zyp.hnwmzp.cn/rest/"
+#define AS_WebSever @"http://zyp.hnwmzp.cn/"
+#define AS_Server @"http://zyp.hnwmzp.cn/rest/"
 
 
 ///开发服务器
@@ -35,4 +37,4 @@
 
 
 
-#endif /* ProjectConfig_h */
+#endif /* ProjectConfigDefine_h */

+ 16 - 0
Asteria/ThirdPartService.h

@@ -0,0 +1,16 @@
+//
+//  ThirdPartService.h
+//  westkissMob
+//
+//  Created by 王猛 on 2022/9/5.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ThirdPartService : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 84 - 0
Asteria/ThirdPartService.m

@@ -0,0 +1,84 @@
+//
+//  ThirdPartService.m
+//  westkissMob
+//
+//  Created by 王猛 on 2022/9/5.
+//
+
+#import "ThirdPartService.h"
+#import <IQKeyboardManager/IQKeyboardManager.h>
+// 检测网络状态
+#import <Reachability/Reachability.h>
+@interface ThirdPartService()
+@property (strong, nonatomic) Reachability *internetReachability;
+@end
+
+@implementation ThirdPartService
++ (instancetype)sharedInstance {
+    static id sharedInstance = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        sharedInstance = [[self alloc] init];
+    });
+    return sharedInstance;
+}
++ (void)load{
+    [[ThirdPartService sharedInstance] setupKeyboardManager];
+    [[ThirdPartService sharedInstance] setupReachability];
+
+}
+#pragma mark - 设置全局键盘
+- (void)setupKeyboardManager {
+    // 设置键盘监听管理
+    IQKeyboardManager *manager = [IQKeyboardManager sharedManager];
+    manager.toolbarDoneBarButtonItemText =@"Done";
+    manager.enable=YES;
+    manager.toolbarManageBehaviour =IQAutoToolbarByTag;
+    manager.shouldResignOnTouchOutside=NO;
+    manager.shouldToolbarUsesTextFieldTintColor=NO;
+    manager.enableAutoToolbar=YES;
+    manager.shouldShowToolbarPlaceholder = NO;
+    manager.shouldResignOnTouchOutside = YES; // 控制点击背景是否收起键盘
+}
+
+
+#pragma mark - 检测网络状态
+- (void)setupReachability {
+    //添加一个系统通知
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
+    //初始化
+    self.internetReachability=[Reachability reachabilityForInternetConnection];
+    //通知添加到Run Loop
+    [self.internetReachability startNotifier];
+    [self updateInterfaceWithReachability:_internetReachability];
+}
+- (void)reachabilityChanged:(NSNotification *)note {
+    Reachability* curReach = [note object];
+    if ([curReach isKindOfClass:[Reachability class]]) {
+        NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
+        [self updateInterfaceWithReachability: curReach];
+    } else {
+        UIViewController *topVc = topViewController();
+        [topVc.view makeToast:@"Network status has been switched."];
+    }
+}
+
+- (void)updateInterfaceWithReachability:(Reachability *)reachability {
+    NetworkStatus netStatus = [reachability currentReachabilityStatus];
+    UIViewController *topVc = topViewController();
+    switch (netStatus) {
+        case NotReachable:
+            NSLog(@"====当前网络状态不可达=======");
+            [topVc.view makeToast:@"Current network status is unavailable"];
+            break;
+        case ReachableViaWiFi:
+            NSLog(@"====当前网络状态为Wifi=======");
+            [topVc.view makeToast:@"The current network status is WiFi."];
+            break;
+        case ReachableViaWWAN:
+            NSLog(@"====当前网络状态为蜂窝网络=======");
+            [topVc.view makeToast:@"The current status is cellular network."];
+            break;
+    }
+}
+@end

+ 20 - 1
Podfile.lock

@@ -623,6 +623,18 @@ PODS:
   - BoringSSL-GRPC/Implementation (0.0.24):
     - BoringSSL-GRPC/Interface (= 0.0.24)
   - BoringSSL-GRPC/Interface (0.0.24)
+  - BRPickerView (2.8.1):
+    - BRPickerView/AddressPickerView (= 2.8.1)
+    - BRPickerView/Base (= 2.8.1)
+    - BRPickerView/DatePickerView (= 2.8.1)
+    - BRPickerView/StringPickerView (= 2.8.1)
+  - BRPickerView/AddressPickerView (2.8.1):
+    - BRPickerView/Base
+  - BRPickerView/Base (2.8.1)
+  - BRPickerView/DatePickerView (2.8.1):
+    - BRPickerView/Base
+  - BRPickerView/StringPickerView (2.8.1):
+    - BRPickerView/Base
   - Bugly (2.5.93)
   - CTMediator (48)
   - FBAEMKit (16.1.0):
@@ -1120,6 +1132,7 @@ PODS:
   - Toast (4.0.0)
   - WMBase (1.0.9):
     - AFNetworking
+    - BRPickerView
     - CTMediator
     - Masonry
     - MBProgressHUD
@@ -1130,9 +1143,11 @@ PODS:
     - Toast
     - YTKNetwork
     - YYCache
+    - YYText
   - YTKNetwork (3.0.6):
     - AFNetworking/NSURLSession (~> 4.0)
   - YYCache (1.0.4)
+  - YYText (1.0.7)
 
 DEPENDENCIES:
   - AFNetworking
@@ -1164,6 +1179,7 @@ SPEC REPOS:
     - AFNetworking
     - AppAuth
     - BoringSSL-GRPC
+    - BRPickerView
     - Bugly
     - CTMediator
     - FBAEMKit
@@ -1203,6 +1219,7 @@ SPEC REPOS:
     - Toast
     - YTKNetwork
     - YYCache
+    - YYText
 
 EXTERNAL SOURCES:
   WMBase:
@@ -1213,6 +1230,7 @@ SPEC CHECKSUMS:
   AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
   AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
   BoringSSL-GRPC: 3175b25143e648463a56daeaaa499c6cb86dad33
+  BRPickerView: 2531a2d4d0fea0b57a1c738de215af0f88863a2f
   Bugly: b8715e6ec4004b7f7fbffab0643ba80545aee3da
   CTMediator: 3f3578b525b3a46a7a2f92a99922ec40363f4269
   FBAEMKit: c7efe06720a8b15b1d25b68921ba46dee20996e0
@@ -1250,9 +1268,10 @@ SPEC CHECKSUMS:
   Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
   SDWebImage: cb032eba469c54e0000e78bcb0a13cdde0a52798
   Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
-  WMBase: eb93e38dff7d9be4edb267acef5b3bdc1bc4d3a8
+  WMBase: a0c4b37b0af79598c62864d8580991b7d4f651f2
   YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04
   YYCache: 8105b6638f5e849296c71f331ff83891a4942952
+  YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
 
 PODFILE CHECKSUM: 9e16269a21fd5c9c1688e530bba69cffe563a650
 

+ 51 - 0
Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressModel.h

@@ -0,0 +1,51 @@
+//
+//  BRAddressModel.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// 省
+@interface BRProvinceModel : NSObject
+/** 省对应的code或id */
+@property (nullable, nonatomic, copy) NSString *code;
+/** 省的名称 */
+@property (nullable, nonatomic, copy) NSString *name;
+/** 城市数组 */
+@property (nullable, nonatomic, copy) NSArray *citylist;
+/** 记录省选择的索引位置 */
+@property (nonatomic, assign) NSInteger index;
+
+@end
+
+/// 市
+@interface BRCityModel : NSObject
+/** 市对应的code或id */
+@property (nullable, nonatomic, copy) NSString *code;
+/** 市的名称 */
+@property (nullable, nonatomic, copy) NSString *name;
+/** 地区数组 */
+@property (nullable, nonatomic, copy) NSArray *arealist;
+/** 记录市选择的索引位置 */
+@property (nonatomic, assign) NSInteger index;
+
+@end
+
+/// 区
+@interface BRAreaModel : NSObject
+/** 区对应的code或id */
+@property (nullable, nonatomic, copy) NSString *code;
+/** 区的名称 */
+@property (nullable, nonatomic, copy) NSString *name;
+/** 记录区选择的索引位置 */
+@property (nonatomic, assign) NSInteger index;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 24 - 0
Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressModel.m

@@ -0,0 +1,24 @@
+//
+//  BRAddressModel.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRAddressModel.h"
+
+@implementation BRProvinceModel
+
+@end
+
+
+@implementation BRCityModel
+
+@end
+
+
+@implementation BRAreaModel
+
+@end

File diff ditekan karena terlalu besar
+ 13634 - 0
Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressPickerView.bundle/BRCity.json


+ 127 - 0
Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressPickerView.h

@@ -0,0 +1,127 @@
+//
+//  BRAddressPickerView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRBaseView.h"
+#import "BRAddressModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// 地址选择器类型
+typedef NS_ENUM(NSInteger, BRAddressPickerMode) {
+    /** 显示【省市区】(默认) */
+    BRAddressPickerModeArea,
+    /** 显示【省市】 */
+    BRAddressPickerModeCity,
+    /** 显示【省】 */
+    BRAddressPickerModeProvince
+};
+
+typedef void(^BRAddressResultBlock)(BRProvinceModel * _Nullable province, BRCityModel * _Nullable city, BRAreaModel * _Nullable area);
+
+@interface BRAddressPickerView : BRBaseView
+
+/**
+ //////////////////////////////////////////////////////////////////////////
+ ///
+ ///   【用法一】
+ ///    特点:灵活,扩展性强(推荐使用!)
+ ///
+ ////////////////////////////////////////////////////////////////////////*/
+
+/** 地址选择器显示类型 */
+@property (nonatomic, assign) BRAddressPickerMode pickerMode;
+
+/** 默认选中的位置(1.传索引数组,如:@[@10, @0, @4]) */
+@property (nullable, nonatomic, copy) NSArray <NSNumber *> *selectIndexs;
+/** 默认选中的位置(2.传值数组,如:@[@"浙江省", @"杭州市", @"西湖区"]) */
+@property (nullable, nonatomic, copy) NSArray <NSString *> *selectValues;
+
+/** 选择结果的回调 */
+@property (nullable, nonatomic, copy) BRAddressResultBlock resultBlock;
+
+/** 滚动选择时触发的回调 */
+@property (nullable, nonatomic, copy) BRAddressResultBlock changeBlock;
+
+/**
+ *  地区数据源(不传或为nil,默认就获取本地 BRCity.json 文件的数据)
+ *  1.可以传 JSON数组,要注意 层级结构 和 key 要与 BRCity.json 保持一致
+ *  2.可以传 模型数组(NSArray <BRProvinceModel *> * 类型),自己解析数据源 只需要注意层级结构就行
+ */
+@property (nullable, nonatomic, copy) NSArray *dataSourceArr;
+
+/// 初始化地址选择器
+/// @param pickerMode 地址选择器显示类型
+- (instancetype)initWithPickerMode:(BRAddressPickerMode)pickerMode;
+
+/// 弹出选择器视图
+- (void)show;
+
+/// 关闭选择器视图
+- (void)dismiss;
+
+
+
+
+//================================================= 华丽的分割线 =================================================
+
+
+
+
+/**
+ //////////////////////////////////////////////////////////////////////////
+ ///
+ ///   【用法二】:快捷使用,直接选择下面其中的一个方法进行使用
+ ///    特点:快捷,方便
+ ///
+ ////////////////////////////////////////////////////////////////////////*/
+
+/**
+ *  1.显示地址选择器
+ *
+ *  @param selectIndexs             默认选中的值(传索引数组,如:@[@10, @0, @4])
+ *  @param resultBlock              选择后的回调
+ *
+ */
++ (void)showAddressPickerWithSelectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                              resultBlock:(nullable BRAddressResultBlock)resultBlock;
+
+/**
+ *  2.显示地址选择器
+ *
+ *  @param mode                     地址选择器显示类型
+ *  @param selectIndexs             默认选中的值(传索引数组,如:@[@10, @0, @4])
+ *  @param isAutoSelect             是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock              选择后的回调
+ *
+ */
++ (void)showAddressPickerWithMode:(BRAddressPickerMode)mode
+                     selectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                     isAutoSelect:(BOOL)isAutoSelect
+                      resultBlock:(nullable BRAddressResultBlock)resultBlock;
+
+/**
+ *  3.显示地址选择器
+ *
+ *  @param mode                     地址选择器显示类型
+ *  @param dataSource               地区数据源
+ *  @param selectIndexs             默认选中的值(传索引数组,如:@[@10, @0, @4])
+ *  @param isAutoSelect             是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock              选择后的回调
+ *
+ */
++ (void)showAddressPickerWithMode:(BRAddressPickerMode)mode
+                       dataSource:(nullable NSArray *)dataSource
+                     selectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                     isAutoSelect:(BOOL)isAutoSelect
+                      resultBlock:(nullable BRAddressResultBlock)resultBlock;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 562 - 0
Pods/BRPickerView/BRPickerView/AddressPickerView/BRAddressPickerView.m

@@ -0,0 +1,562 @@
+//
+//  BRAddressPickerView.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRAddressPickerView.h"
+#import "NSBundle+BRPickerView.h"
+
+@interface BRAddressPickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
+// 地址选择器
+@property (nonatomic, strong) UIPickerView *pickerView;
+// 省模型数组
+@property(nonatomic, copy) NSArray *provinceModelArr;
+// 市模型数组
+@property(nonatomic, copy) NSArray *cityModelArr;
+// 区模型数组
+@property(nonatomic, copy) NSArray *areaModelArr;
+// 选中的省
+@property(nonatomic, strong) BRProvinceModel *selectProvinceModel;
+// 选中的市
+@property(nonatomic, strong) BRCityModel *selectCityModel;
+// 选中的区
+@property(nonatomic, strong) BRAreaModel *selectAreaModel;
+// 记录省选中的位置
+@property(nonatomic, assign) NSInteger provinceIndex;
+// 记录市选中的位置
+@property(nonatomic, assign) NSInteger cityIndex;
+// 记录区选中的位置
+@property(nonatomic, assign) NSInteger areaIndex;
+
+@property (nonatomic, copy) NSArray <NSString *>* mSelectValues;
+
+@end
+
+@implementation BRAddressPickerView
+
+#pragma mark - 1.显示地址选择器
++ (void)showAddressPickerWithSelectIndexs:(NSArray <NSNumber *>*)selectIndexs
+                              resultBlock:(BRAddressResultBlock)resultBlock {
+    [self showAddressPickerWithMode:BRAddressPickerModeArea dataSource:nil selectIndexs:selectIndexs isAutoSelect:NO resultBlock:resultBlock];
+}
+
+#pragma mark - 2.显示地址选择器
++ (void)showAddressPickerWithMode:(BRAddressPickerMode)mode
+                     selectIndexs:(NSArray <NSNumber *>*)selectIndexs
+                     isAutoSelect:(BOOL)isAutoSelect
+                      resultBlock:(BRAddressResultBlock)resultBlock {
+    [self showAddressPickerWithMode:mode dataSource:nil selectIndexs:selectIndexs isAutoSelect:isAutoSelect resultBlock:resultBlock];
+}
+
+
+#pragma mark - 3.显示地址选择器
++ (void)showAddressPickerWithMode:(BRAddressPickerMode)mode
+                       dataSource:(NSArray *)dataSource
+                     selectIndexs:(NSArray <NSNumber *>*)selectIndexs
+                     isAutoSelect:(BOOL)isAutoSelect
+                      resultBlock:(BRAddressResultBlock)resultBlock {
+    // 创建地址选择器
+    BRAddressPickerView *addressPickerView = [[BRAddressPickerView alloc] initWithPickerMode:mode];
+    addressPickerView.dataSourceArr = dataSource;
+    addressPickerView.selectIndexs = selectIndexs;
+    addressPickerView.isAutoSelect = isAutoSelect;
+    addressPickerView.resultBlock = resultBlock;
+    // 显示
+    [addressPickerView show];
+}
+
+#pragma mark - 初始化地址选择器
+- (instancetype)initWithPickerMode:(BRAddressPickerMode)pickerMode {
+    if (self = [super init]) {
+        self.pickerMode = pickerMode;
+    }
+    return self;
+}
+
+#pragma mark - 处理选择器数据
+- (void)handlerPickerData {
+    if (self.dataSourceArr && self.dataSourceArr.count > 0) {
+        id item = [self.dataSourceArr firstObject];
+        // 如果传的值是解析好的模型数组
+        if ([item isKindOfClass:[BRProvinceModel class]]) {
+            self.provinceModelArr = self.dataSourceArr;
+        } else {
+            self.provinceModelArr = [self getProvinceModelArr:self.dataSourceArr];
+        }
+    } else {
+        // 如果外部没有传入地区数据源,就使用本地的数据源
+        NSArray *dataSource = [self br_addressJsonArray];
+        
+        if (!dataSource || dataSource.count == 0) {
+            return;
+        }
+        self.dataSourceArr = dataSource;
+        self.provinceModelArr = [self getProvinceModelArr:self.dataSourceArr];
+    }
+    
+    // 设置默认值
+    [self handlerDefaultSelectValue];
+}
+
+#pragma mark - 获取城市JSON数据
+- (NSArray *)br_addressJsonArray {
+    static NSArray *cityArray = nil;
+    if (!cityArray) {
+        // 获取 BRAddressPickerView.bundle
+        NSBundle *containnerBundle = [NSBundle bundleForClass:[BRAddressPickerView class]];
+        NSString *bundlePath = [containnerBundle pathForResource:@"BRAddressPickerView" ofType:@"bundle"];
+        NSBundle *addressPickerBundle = [NSBundle bundleWithPath:bundlePath];
+        
+        // 获取bundle中的JSON文件
+        NSString *filePath = [addressPickerBundle pathForResource:@"BRCity" ofType:@"json"];
+        NSData *data = [NSData dataWithContentsOfFile:filePath];
+        cityArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
+    }
+    return cityArray;
+}
+
+#pragma mark - 获取模型数组
+- (NSArray <BRProvinceModel *>*)getProvinceModelArr:(NSArray *)dataSourceArr {
+    NSMutableArray *tempArr1 = [NSMutableArray array];
+    for (NSDictionary *proviceDic in dataSourceArr) {
+        BRProvinceModel *proviceModel = [[BRProvinceModel alloc]init];
+        proviceModel.code = [proviceDic objectForKey:@"code"];
+        proviceModel.name = [proviceDic objectForKey:@"name"];
+        proviceModel.index = [dataSourceArr indexOfObject:proviceDic];
+        NSArray *cityList = [proviceDic.allKeys containsObject:@"cityList"] ? [proviceDic objectForKey:@"cityList"] : [proviceDic objectForKey:@"citylist"];
+        NSMutableArray *tempArr2 = [NSMutableArray array];
+        for (NSDictionary *cityDic in cityList) {
+            BRCityModel *cityModel = [[BRCityModel alloc]init];
+            cityModel.code = [cityDic objectForKey:@"code"];
+            cityModel.name = [cityDic objectForKey:@"name"];
+            cityModel.index = [cityList indexOfObject:cityDic];
+            NSArray *areaList = [cityDic.allKeys containsObject:@"areaList"] ? [cityDic objectForKey:@"areaList"] : [cityDic objectForKey:@"arealist"];
+            NSMutableArray *tempArr3 = [NSMutableArray array];
+            for (NSDictionary *areaDic in areaList) {
+                BRAreaModel *areaModel = [[BRAreaModel alloc]init];
+                areaModel.code = [areaDic objectForKey:@"code"];
+                areaModel.name = [areaDic objectForKey:@"name"];
+                areaModel.index = [areaList indexOfObject:areaDic];
+                [tempArr3 addObject:areaModel];
+            }
+            cityModel.arealist = [tempArr3 copy];
+            [tempArr2 addObject:cityModel];
+        }
+        proviceModel.citylist = [tempArr2 copy];
+        [tempArr1 addObject:proviceModel];
+    }
+    return [tempArr1 copy];
+}
+
+#pragma mark - 设置默认选择的值
+- (void)handlerDefaultSelectValue {
+    __block NSString *selectProvinceName = nil;
+    __block NSString *selectCityName = nil;
+    __block NSString *selectAreaName = nil;
+    
+    if (self.mSelectValues.count > 0) {
+        selectProvinceName = self.mSelectValues.count > 0 ? self.mSelectValues[0] : nil;
+        selectCityName = self.mSelectValues.count > 1 ? self.mSelectValues[1] : nil;
+        selectAreaName = self.mSelectValues.count > 2 ? self.mSelectValues[2] : nil;
+    }
+    
+    __weak typeof(self) weakSelf = self;
+    
+    if (self.pickerMode == BRAddressPickerModeProvince || self.pickerMode == BRAddressPickerModeCity || self.pickerMode == BRAddressPickerModeArea) {
+        if (self.selectIndexs.count > 0) {
+            NSInteger provinceIndex = [self.selectIndexs[0] integerValue];
+            self.provinceIndex = (provinceIndex > 0 && provinceIndex < self.provinceModelArr.count) ? provinceIndex : 0;
+            self.selectProvinceModel = self.provinceModelArr.count > self.provinceIndex ? self.provinceModelArr[self.provinceIndex] : nil;
+        } else {
+            self.provinceIndex = 0;
+            self.selectProvinceModel = self.provinceModelArr.count > 0 ? self.provinceModelArr[0] : nil;
+            [self.provinceModelArr enumerateObjectsUsingBlock:^(BRProvinceModel *  _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
+                if (selectProvinceName && [model.name isEqualToString:selectProvinceName]) {
+                    weakSelf.provinceIndex = idx;
+                    weakSelf.selectProvinceModel = model;
+                    *stop = YES;
+                }
+            }];
+        }
+    }
+    
+    if (self.pickerMode == BRAddressPickerModeCity || self.pickerMode == BRAddressPickerModeArea) {
+        self.cityModelArr = [self getCityModelArray:self.provinceIndex];
+        if (self.selectIndexs.count > 0) {
+            NSInteger cityIndex = self.selectIndexs.count > 1 ? [self.selectIndexs[1] integerValue] : 0;
+            self.cityIndex = (cityIndex > 0 && cityIndex < self.cityModelArr.count) ? cityIndex : 0;
+            self.selectCityModel = self.cityModelArr.count > self.cityIndex ? self.cityModelArr[self.cityIndex] : nil;
+        } else {
+            self.cityIndex = 0;
+            self.selectCityModel = self.cityModelArr.count > 0 ? self.cityModelArr[0] : nil;
+            [self.cityModelArr enumerateObjectsUsingBlock:^(BRCityModel *  _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
+                if (selectCityName && [model.name isEqualToString:selectCityName]) {
+                    weakSelf.cityIndex = idx;
+                    weakSelf.selectCityModel = model;
+                    *stop = YES;
+                }
+            }];
+        }
+    }
+    
+    if (self.pickerMode == BRAddressPickerModeArea) {
+        self.areaModelArr = [self getAreaModelArray:self.provinceIndex cityIndex:self.cityIndex];
+        if (self.selectIndexs.count > 0) {
+            NSInteger areaIndex = self.selectIndexs.count > 2 ? [self.selectIndexs[2] integerValue] : 0;
+            self.areaIndex = (areaIndex > 0 && areaIndex < self.areaModelArr.count) ? areaIndex : 0;
+            self.selectAreaModel = self.areaModelArr.count > self.areaIndex ? self.areaModelArr[self.areaIndex] : nil;
+        } else {
+            self.areaIndex = 0;
+            self.selectAreaModel = self.areaModelArr.count > 0 ? self.areaModelArr[0] : nil;
+            [self.areaModelArr enumerateObjectsUsingBlock:^(BRAreaModel *  _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
+                if (selectAreaName && [model.name isEqualToString:selectAreaName]) {
+                    weakSelf.areaIndex = idx;
+                    weakSelf.selectAreaModel = model;
+                    *stop = YES;
+                }
+            }];
+        }
+    }
+}
+
+// 根据 省索引 获取 城市模型数组
+- (NSArray *)getCityModelArray:(NSInteger)provinceIndex {
+    BRProvinceModel *provinceModel = self.provinceModelArr[provinceIndex];
+    // 返回城市模型数组
+    return provinceModel.citylist;
+}
+
+// 根据 省索引和城市索引 获取 区域模型数组
+- (NSArray *)getAreaModelArray:(NSInteger)provinceIndex cityIndex:(NSInteger)cityIndex {
+    BRProvinceModel *provinceModel = self.provinceModelArr[provinceIndex];
+    if (provinceModel.citylist && provinceModel.citylist.count > 0) {
+        BRCityModel *cityModel = provinceModel.citylist[cityIndex];
+        // 返回地区模型数组
+        return cityModel.arealist;
+    } else {
+        return nil;
+    }
+}
+
+#pragma mark - 地址选择器
+- (UIPickerView *)pickerView {
+    if (!_pickerView) {
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        _pickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, self.pickerStyle.titleBarHeight + pickerHeaderViewHeight, self.keyView.bounds.size.width, self.pickerStyle.pickerHeight)];
+        _pickerView.backgroundColor = self.pickerStyle.pickerColor;
+        _pickerView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
+        _pickerView.dataSource = self;
+        _pickerView.delegate = self;
+    }
+    return _pickerView;
+}
+
+#pragma mark - UIPickerViewDataSource
+// 1.设置 pickerView 的列数
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
+    switch (self.pickerMode) {
+        case BRAddressPickerModeProvince:
+            return 1;
+            break;
+        case BRAddressPickerModeCity:
+            return 2;
+            break;
+        case BRAddressPickerModeArea:
+            return 3;
+            break;
+            
+        default:
+            break;
+    }
+}
+
+// 2.设置 pickerView 每列的行数
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
+    if (component == 0) {
+        // 返回省个数
+        return self.provinceModelArr.count;
+    }
+    if (component == 1) {
+        // 返回市个数
+        return self.cityModelArr.count;
+    }
+    if (component == 2) {
+        // 返回区个数
+        return self.areaModelArr.count;
+    }
+    return 0;
+}
+
+#pragma mark - UIPickerViewDelegate
+// 3.设置 pickerView 的显示内容
+- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view {
+    // 1.自定义 row 的内容视图
+    UILabel *label = (UILabel *)view;
+    if (!label) {
+        label = [[UILabel alloc]init];
+        label.backgroundColor = [UIColor clearColor];
+        label.textAlignment = NSTextAlignmentCenter;
+        label.font = self.pickerStyle.pickerTextFont;
+        label.textColor = self.pickerStyle.pickerTextColor;
+        // 字体自适应属性
+        label.adjustsFontSizeToFitWidth = YES;
+        // 自适应最小字体缩放比例
+        label.minimumScaleFactor = 0.5f;
+    }
+    if (component == 0) {
+        BRProvinceModel *model = self.provinceModelArr[row];
+        label.text = model.name;
+    } else if (component == 1) {
+        BRCityModel *model = self.cityModelArr[row];
+        label.text = model.name;
+    } else if (component == 2) {
+        BRAreaModel *model = self.areaModelArr[row];
+        label.text = model.name;
+    }
+    
+    // 2.设置选择器中间选中行的样式
+    [self.pickerStyle setupPickerSelectRowStyle:pickerView titleForRow:row forComponent:component];
+    
+    return label;
+}
+
+// 4.滚动 pickerView 执行的回调方法
+- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
+    if (component == 0) { // 选择省
+        // 保存选择的省份的索引
+        self.provinceIndex = row;
+        switch (self.pickerMode) {
+            case BRAddressPickerModeProvince:
+            {
+                self.selectProvinceModel = self.provinceModelArr.count > self.provinceIndex ? self.provinceModelArr[self.provinceIndex] : nil;
+                self.selectCityModel = nil;
+                self.selectAreaModel = nil;
+            }
+                break;
+            case BRAddressPickerModeCity:
+            {
+                self.cityModelArr = [self getCityModelArray:self.provinceIndex];
+                [self.pickerView reloadComponent:1];
+                [self.pickerView selectRow:0 inComponent:1 animated:YES];
+                self.selectProvinceModel = self.provinceModelArr.count > self.provinceIndex ? self.provinceModelArr[self.provinceIndex] : nil;
+                self.selectCityModel = self.cityModelArr.count > 0 ? self.cityModelArr[0] : nil;
+                self.selectAreaModel = nil;
+            }
+                break;
+            case BRAddressPickerModeArea:
+            {
+                self.cityModelArr = [self getCityModelArray:self.provinceIndex];
+                self.areaModelArr = [self getAreaModelArray:self.provinceIndex cityIndex:0];
+                [self.pickerView reloadComponent:1];
+                [self.pickerView selectRow:0 inComponent:1 animated:YES];
+                [self.pickerView reloadComponent:2];
+                [self.pickerView selectRow:0 inComponent:2 animated:YES];
+                self.selectProvinceModel = self.provinceModelArr.count > self.provinceIndex ? self.provinceModelArr[self.provinceIndex] : nil;
+                self.selectCityModel = self.cityModelArr.count > 0 ? self.cityModelArr[0] : nil;
+                self.selectAreaModel = self.areaModelArr.count > 0 ? self.areaModelArr[0] : nil;
+            }
+                break;
+            default:
+                break;
+        }
+    }
+    if (component == 1) { // 选择市
+        // 保存选择的城市的索引
+        self.cityIndex = row;
+        switch (self.pickerMode) {
+            case BRAddressPickerModeCity:
+            {
+                self.selectCityModel = self.cityModelArr.count > self.cityIndex ? self.cityModelArr[self.cityIndex] : nil;
+                self.selectAreaModel = nil;
+            }
+                break;
+            case BRAddressPickerModeArea:
+            {
+                self.areaModelArr = [self getAreaModelArray:self.provinceIndex cityIndex:self.cityIndex];
+                [self.pickerView reloadComponent:2];
+                [self.pickerView selectRow:0 inComponent:2 animated:YES];
+                self.selectCityModel = self.cityModelArr.count > self.cityIndex ? self.cityModelArr[self.cityIndex] : nil;
+                self.selectAreaModel = self.areaModelArr.count > 0 ? self.areaModelArr[0] : nil;
+            }
+                break;
+            default:
+                break;
+        }
+    }
+    if (component == 2) { // 选择区
+        // 保存选择的地区的索引
+        self.areaIndex = row;
+        if (self.pickerMode == BRAddressPickerModeArea) {
+            self.selectAreaModel = self.areaModelArr.count > self.areaIndex ? self.areaModelArr[self.areaIndex] : nil;
+        }
+    }
+    
+    // 滚动选择时执行 changeBlock
+    if (self.changeBlock) {
+        self.changeBlock(self.selectProvinceModel, self.selectCityModel, self.selectAreaModel);
+    }
+    
+    // 设置自动选择时,滚动选择时就执行 resultBlock
+    if (self.isAutoSelect) {
+        if (self.resultBlock) {
+            self.resultBlock(self.selectProvinceModel, self.selectCityModel, self.selectAreaModel);
+        }
+    }
+}
+
+// 设置行高
+- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
+    return self.pickerStyle.rowHeight;
+}
+
+#pragma mark - 重写父类方法
+- (void)reloadData {
+    // 1.处理数据源
+    [self handlerPickerData];
+    // 2.刷新选择器
+    [self.pickerView reloadAllComponents];
+    // 3.滚动到选择的地区
+    if (self.pickerMode == BRAddressPickerModeProvince) {
+        [self.pickerView selectRow:self.provinceIndex inComponent:0 animated:YES];
+    } else if (self.pickerMode == BRAddressPickerModeCity) {
+        [self.pickerView selectRow:self.provinceIndex inComponent:0 animated:YES];
+        [self.pickerView selectRow:self.cityIndex inComponent:1 animated:YES];
+    } else if (self.pickerMode == BRAddressPickerModeArea) {
+        [self.pickerView selectRow:self.provinceIndex inComponent:0 animated:YES];
+        [self.pickerView selectRow:self.cityIndex inComponent:1 animated:YES];
+        [self.pickerView selectRow:self.areaIndex inComponent:2 animated:YES];
+    }
+}
+
+- (void)addPickerToView:(UIView *)view {
+    // 1.添加地址选择器
+    if (view) {
+        // 立即刷新容器视图 view 的布局(防止 view 使用自动布局时,选择器视图无法正常显示)
+        [view setNeedsLayout];
+        [view layoutIfNeeded];
+        
+        self.frame = view.bounds;
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        CGFloat pickerFooterViewHeight = self.pickerFooterView ? self.pickerFooterView.bounds.size.height : 0;
+        self.pickerView.frame = CGRectMake(0, pickerHeaderViewHeight, view.bounds.size.width, view.bounds.size.height - pickerHeaderViewHeight - pickerFooterViewHeight);
+        [self addSubview:self.pickerView];
+    } else {
+        // iOS16:重新设置 pickerView 高度(解决懒加载设置frame不生效问题)
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        self.pickerView.frame = CGRectMake(0, self.pickerStyle.titleBarHeight + pickerHeaderViewHeight, self.keyView.bounds.size.width, self.pickerStyle.pickerHeight);
+        
+        [self.alertView addSubview:self.pickerView];
+    }
+    
+    // ③添加中间选择行的两条分割线
+    if (self.pickerStyle.clearPickerNewStyle) {
+        [self.pickerStyle addSeparatorLineView:self.pickerView];
+    }
+    
+    // 2.绑定数据
+    [self reloadData];
+    
+    __weak typeof(self) weakSelf = self;
+    self.doneBlock = ^{
+        // 点击确定按钮后,执行block回调
+        if (weakSelf.resultBlock) {
+            weakSelf.resultBlock(weakSelf.selectProvinceModel, weakSelf.selectCityModel, weakSelf.selectAreaModel);
+        }
+    };
+    
+    [super addPickerToView:view];
+}
+
+#pragma mark - 重写父类方法
+- (void)addSubViewToPicker:(UIView *)customView {
+    [self.pickerView addSubview:customView];
+}
+
+#pragma mark - 弹出选择器视图
+- (void)show {
+    [self addPickerToView:nil];
+}
+
+#pragma mark - 关闭选择器视图
+- (void)dismiss {
+    [self removePickerFromView:nil];
+}
+
+#pragma mark - setter方法
+- (void)setSelectValues:(NSArray<NSString *> *)selectValues {
+    self.mSelectValues = selectValues;
+}
+
+#pragma mark - getter方法
+- (NSArray *)provinceModelArr {
+    if (!_provinceModelArr) {
+        _provinceModelArr = [NSArray array];
+    }
+    return _provinceModelArr;
+}
+
+- (NSArray *)cityModelArr {
+    if (!_cityModelArr) {
+        _cityModelArr = [NSArray array];
+    }
+    return _cityModelArr;
+}
+
+- (NSArray *)areaModelArr {
+    if (!_areaModelArr) {
+        _areaModelArr = [NSArray array];
+    }
+    return _areaModelArr;
+}
+
+- (BRProvinceModel *)selectProvinceModel {
+    if (!_selectProvinceModel) {
+        _selectProvinceModel = [[BRProvinceModel alloc]init];
+    }
+    return _selectProvinceModel;
+}
+
+- (BRCityModel *)selectCityModel {
+    if (!_selectCityModel) {
+        _selectCityModel = [[BRCityModel alloc]init];
+        _selectCityModel.code = @"";
+        _selectCityModel.name = @"";
+    }
+    return _selectCityModel;
+}
+
+- (BRAreaModel *)selectAreaModel {
+    if (!_selectAreaModel) {
+        _selectAreaModel = [[BRAreaModel alloc]init];
+        _selectAreaModel.code = @"";
+        _selectAreaModel.name = @"";
+    }
+    return _selectAreaModel;
+}
+
+- (NSArray *)dataSourceArr {
+    if (!_dataSourceArr) {
+        _dataSourceArr = [NSArray array];
+    }
+    return _dataSourceArr;
+}
+
+- (NSArray<NSString *> *)mSelectValues {
+    if (!_mSelectValues) {
+        _mSelectValues = [NSArray array];
+    }
+    return _mSelectValues;
+}
+
+- (NSArray<NSNumber *> *)selectIndexs {
+    if (!_selectIndexs) {
+        _selectIndexs = [NSArray array];
+    }
+    return _selectIndexs;
+}
+
+@end

+ 17 - 0
Pods/BRPickerView/BRPickerView/BRPickerView.h

@@ -0,0 +1,17 @@
+//
+//  BRPickerView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#ifndef BRPickerView_h
+#define BRPickerView_h
+
+#import "BRDatePickerView.h"
+#import "BRAddressPickerView.h"
+#import "BRStringPickerView.h"
+
+#endif /* BRPickerView_h */

+ 76 - 0
Pods/BRPickerView/BRPickerView/Base/BRBaseView.h

@@ -0,0 +1,76 @@
+//
+//  BaseView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import <UIKit/UIKit.h>
+#import "BRPickerStyle.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^BRCancelBlock)(void);
+typedef void(^BRDoneClickBlock)(void);
+
+@interface BRBaseView : UIView
+
+/** 选择器标题 */
+@property (nullable, nonatomic, copy) NSString *title;
+
+/** 是否自动选择,即滚动选择器后就执行结果回调,默认为 NO */
+@property (nonatomic, assign) BOOL isAutoSelect;
+
+/** 自定义UI样式(不传或为nil时,是默认样式) */
+@property (nullable, nonatomic, strong) BRPickerStyle *pickerStyle;
+
+/** 取消选择的回调 */
+@property (nullable, nonatomic, copy) BRCancelBlock cancelBlock;
+
+/** accessory view for above picker view. default is nil */
+@property (nullable, nonatomic, strong) UIView *pickerHeaderView;
+
+/** accessory view below picker view. default is nil */
+@property (nullable, nonatomic, strong) UIView *pickerFooterView;
+
+/// 确定按钮点击事件的回调
+/// 应用场景:如果是自定义确定按钮,需要在该按钮点击事件方法里,执行一下 doneBlock 回调。目的是触发组件内部执行 resultBlock 回调,回调选择的值
+@property (nullable, nonatomic, copy) BRDoneClickBlock doneBlock;
+
+/** 弹框视图(使用场景:可以在 alertView 上添加选择器的自定义背景视图) */
+@property (nullable, nonatomic, strong) UIView *alertView;
+
+/** 组件的父视图:可以传 自己获取的 keyWindow,或页面的 view */
+@property (nullable, nonatomic, strong) UIView *keyView;
+
+
+/// 刷新选择器数据
+/// 应用场景:动态更新数据源、动态更新选择的值、选择器类型切换等
+- (void)reloadData;
+
+/// 扩展一:添加选择器到指定容器视图上
+/// 应用场景:可将中间的滚轮选择器 pickerView 视图(不包含蒙层及标题栏)添加到任何自定义视图上(会自动填满容器视图),也方便自定义更多的弹框样式
+/// 补充说明:如果是自定义确定按钮,需要回调默认选择的值:只需在自定义确定按钮的点击事件方法里执行一下 doneBlock 回调(目的是去触发组件内部执行 resultBlock 回调,进而回调默认选择的值)
+/// @param view 容器视图
+- (void)addPickerToView:(nullable UIView *)view NS_REQUIRES_SUPER;
+
+/// 从指定容器视图上移除选择器
+/// @param view 容器视图
+- (void)removePickerFromView:(nullable UIView *)view;
+
+/// 扩展二:添加自定义视图到选择器(pickerView)上
+/// 应用场景:可以添加一些固定的标题、单位等到选择器中间
+/// @param customView 自定义视图
+- (void)addSubViewToPicker:(UIView *)customView;
+
+/// 扩展三:添加自定义视图到标题栏(titleBarView)上
+/// 应用场景:可以添加一些子控件到标题栏
+/// @param customView 自定义视图
+- (void)addSubViewToTitleBar:(UIView *)customView;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 398 - 0
Pods/BRPickerView/BRPickerView/Base/BRBaseView.m

@@ -0,0 +1,398 @@
+//
+//  BaseView.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRBaseView.h"
+
+@interface BRBaseView ()
+// 蒙层视图
+@property (nonatomic, strong) UIView *maskView;
+// 标题栏背景视图
+@property (nonatomic, strong) UIView *titleBarView;
+// 左边取消按钮
+@property (nonatomic, strong) UIButton *cancelBtn;
+// 右边确定按钮
+@property (nonatomic, strong) UIButton *doneBtn;
+// 中间标题
+@property (nonatomic, strong) UILabel *titleLabel;
+
+// 取消按钮离屏幕边缘的距离
+@property (nonatomic, assign) CGFloat cancelBtnMargin;
+// 确定按钮离屏幕边缘的距离
+@property (nonatomic, assign) CGFloat doneBtnMargin;
+
+@end
+
+@implementation BRBaseView
+
+- (void)initUI {
+    self.frame = self.keyView.bounds;
+    // 设置子视图的宽度随着父视图变化
+    self.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+    
+    if (!self.pickerStyle.hiddenMaskView) {
+        [self addSubview:self.maskView];
+    }
+    
+    [self addSubview:self.alertView];
+    
+    // 是否隐藏标题栏
+    if (!self.pickerStyle.hiddenTitleBarView) {
+        [self.alertView addSubview:self.titleBarView];
+        [self.alertView sendSubviewToBack:self.titleBarView];
+
+        if (!self.pickerStyle.hiddenTitleLabel) {
+            [self.titleBarView addSubview:self.titleLabel];
+        }
+        if (!self.pickerStyle.hiddenCancelBtn) {
+            [self.titleBarView addSubview:self.cancelBtn];
+            // 获取边距
+            if (self.pickerStyle.cancelBtnFrame.origin.x < self.bounds.size.width / 2) {
+                self.cancelBtnMargin = self.pickerStyle.cancelBtnFrame.origin.x;
+            } else {
+                self.cancelBtnMargin = self.bounds.size.width - self.pickerStyle.cancelBtnFrame.origin.x - self.pickerStyle.cancelBtnFrame.size.width;
+            }
+        }
+        if (!self.pickerStyle.hiddenDoneBtn) {
+            [self.titleBarView addSubview:self.doneBtn];
+            // 获取边距
+            if (self.pickerStyle.doneBtnFrame.origin.x < self.bounds.size.width / 2) {
+                self.doneBtnMargin = self.pickerStyle.doneBtnFrame.origin.x;
+            } else {
+                self.doneBtnMargin = self.bounds.size.width - self.pickerStyle.doneBtnFrame.origin.x - self.pickerStyle.doneBtnFrame.size.width;
+            }
+        }
+    }
+}
+
+#pragma mark - 适配横屏安全区域,更新子视图布局
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    if (_cancelBtn || _doneBtn) {
+        if (@available(iOS 11.0, *)) {
+            UIEdgeInsets safeInsets = self.safeAreaInsets;
+            if (_cancelBtn) {
+                CGRect cancelBtnFrame = self.pickerStyle.cancelBtnFrame;
+                if (cancelBtnFrame.origin.x < MIN(self.bounds.size.width / 2, self.bounds.size.height / 2)) {
+                    cancelBtnFrame.origin.x += safeInsets.left;
+                } else {
+                    cancelBtnFrame.origin.x = self.bounds.size.width - cancelBtnFrame.size.width - safeInsets.right - self.cancelBtnMargin;
+                }
+                self.cancelBtn.frame = cancelBtnFrame;
+            }
+            if (_doneBtn) {
+                CGRect doneBtnFrame = self.pickerStyle.doneBtnFrame;
+                if (doneBtnFrame.origin.x < MIN(self.bounds.size.width / 2, self.bounds.size.height / 2)) {
+                    doneBtnFrame.origin.x += safeInsets.left;
+                } else {
+                    doneBtnFrame.origin.x = self.bounds.size.width - doneBtnFrame.size.width - safeInsets.right - self.doneBtnMargin;
+                }
+                self.doneBtn.frame = doneBtnFrame;
+            }
+        }
+    }
+    
+    if (_alertView && self.pickerStyle.topCornerRadius > 0) {
+        // 设置顶部圆角
+        [BRPickerStyle br_setView:_alertView roundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight withRadius:self.pickerStyle.topCornerRadius];
+    }
+}
+
+#pragma mark - 蒙层视图
+- (UIView *)maskView {
+    if (!_maskView) {
+        _maskView = [[UIView alloc]initWithFrame:self.keyView.bounds];
+        _maskView.backgroundColor = self.pickerStyle.maskColor;
+        // 设置子视图的大小随着父视图变化
+        _maskView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+        _maskView.userInteractionEnabled = YES;
+        UITapGestureRecognizer *myTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didTapMaskView:)];
+        [_maskView addGestureRecognizer:myTap];
+    }
+    return _maskView;
+}
+
+#pragma mark - 弹框视图
+- (UIView *)alertView {
+    if (!_alertView) {
+        CGFloat accessoryViewHeight = 0;
+        if (self.pickerHeaderView) {
+            accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
+        }
+        if (self.pickerFooterView) {
+            accessoryViewHeight += self.pickerFooterView.bounds.size.height;
+        }
+        CGFloat height = self.pickerStyle.titleBarHeight + self.pickerStyle.pickerHeight + self.pickerStyle.paddingBottom + accessoryViewHeight;
+        _alertView = [[UIView alloc]initWithFrame:CGRectMake(0, self.keyView.bounds.size.height - height, self.keyView.bounds.size.width, height)];
+        _alertView.backgroundColor = self.pickerStyle.alertViewColor ? self.pickerStyle.alertViewColor : self.pickerStyle.pickerColor;
+        if (!self.pickerStyle.topCornerRadius && !self.pickerStyle.hiddenShadowLine) {
+            // 设置弹框视图顶部边框线
+            UIView *shadowLineView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _alertView.frame.size.width, self.pickerStyle.shadowLineHeight)];
+            shadowLineView.backgroundColor = self.pickerStyle.shadowLineColor;
+            shadowLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+            [_alertView addSubview:shadowLineView];
+        }
+        _alertView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
+    }
+    return _alertView;
+}
+
+#pragma mark - 标题栏视图
+- (UIView *)titleBarView {
+    if (!_titleBarView) {
+        _titleBarView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.keyView.bounds.size.width, self.pickerStyle.titleBarHeight)];
+        _titleBarView.backgroundColor = self.pickerStyle.titleBarColor;
+        _titleBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+        if (!self.pickerStyle.hiddenTitleLine) {
+            // 设置标题栏底部分割线
+            UIView *titleLineView = [[UIView alloc]initWithFrame:CGRectMake(0, _titleBarView.frame.size.height - 0.5f, _titleBarView.frame.size.width, 0.5f)];
+            titleLineView.backgroundColor = self.pickerStyle.titleLineColor;
+            titleLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+            [_titleBarView addSubview:titleLineView];
+        }
+    }
+    return _titleBarView;
+}
+
+#pragma mark - 取消按钮
+- (UIButton *)cancelBtn {
+    if (!_cancelBtn) {
+        _cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+        _cancelBtn.frame = self.pickerStyle.cancelBtnFrame;
+        _cancelBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
+        _cancelBtn.backgroundColor = self.pickerStyle.cancelColor;;
+        _cancelBtn.titleLabel.font = self.pickerStyle.cancelTextFont;
+        [_cancelBtn setTitleColor:self.pickerStyle.cancelTextColor forState:UIControlStateNormal];
+        if (self.pickerStyle.cancelBtnImage) {
+            [_cancelBtn setImage:self.pickerStyle.cancelBtnImage forState:UIControlStateNormal];
+        }
+        if (self.pickerStyle.cancelBtnTitle) {
+            [_cancelBtn setTitle:self.pickerStyle.cancelBtnTitle forState:UIControlStateNormal];
+        }
+        [_cancelBtn addTarget:self action:@selector(clickCancelBtn) forControlEvents:UIControlEventTouchUpInside];
+        // 设置按钮圆角或边框
+        if (self.pickerStyle.cancelBorderStyle == BRBorderStyleSolid) {
+            _cancelBtn.layer.cornerRadius = self.pickerStyle.cancelCornerRadius > 0 ? self.pickerStyle.cancelCornerRadius : 6.0f;
+            _cancelBtn.layer.borderColor = self.pickerStyle.cancelTextColor.CGColor;
+            _cancelBtn.layer.borderWidth = self.pickerStyle.cancelBorderWidth > 0 ? self.pickerStyle.cancelBorderWidth : 1.0f;
+            _cancelBtn.layer.masksToBounds = YES;
+        } else if (self.pickerStyle.cancelBorderStyle == BRBorderStyleFill) {
+            _cancelBtn.layer.cornerRadius = self.pickerStyle.cancelCornerRadius > 0 ? self.pickerStyle.cancelCornerRadius : 6.0f;
+            _cancelBtn.layer.masksToBounds = YES;
+        }
+    }
+    return _cancelBtn;
+}
+
+#pragma mark - 确定按钮
+- (UIButton *)doneBtn {
+    if (!_doneBtn) {
+        _doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+        _doneBtn.frame = self.pickerStyle.doneBtnFrame;
+        _doneBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
+        _doneBtn.backgroundColor = self.pickerStyle.doneColor;
+        if (self.pickerStyle.doneBtnImage) {
+            [_doneBtn setImage:self.pickerStyle.doneBtnImage forState:UIControlStateNormal];
+        }
+        if (self.pickerStyle.doneBtnTitle) {
+            _doneBtn.titleLabel.font = self.pickerStyle.doneTextFont;
+            [_doneBtn setTitleColor:self.pickerStyle.doneTextColor forState:UIControlStateNormal];
+            [_doneBtn setTitle:self.pickerStyle.doneBtnTitle forState:UIControlStateNormal];
+        }
+        [_doneBtn addTarget:self action:@selector(clickDoneBtn) forControlEvents:UIControlEventTouchUpInside];
+        // 设置按钮圆角或边框
+        if (self.pickerStyle.doneBorderStyle == BRBorderStyleSolid) {
+            _doneBtn.layer.cornerRadius = self.pickerStyle.doneCornerRadius > 0 ? self.pickerStyle.doneCornerRadius : 6.0f;
+            _doneBtn.layer.borderColor = self.pickerStyle.doneTextColor.CGColor;
+            _doneBtn.layer.borderWidth = self.pickerStyle.doneBorderWidth > 0 ? self.pickerStyle.doneBorderWidth : 1.0f;
+            _doneBtn.layer.masksToBounds = YES;
+        } else if (self.pickerStyle.doneBorderStyle == BRBorderStyleFill) {
+            _doneBtn.layer.cornerRadius = self.pickerStyle.doneCornerRadius > 0 ? self.pickerStyle.doneCornerRadius : 6.0f;
+            _doneBtn.layer.masksToBounds = YES;
+        }
+    }
+    return _doneBtn;
+}
+
+#pragma mark - 中间标题label
+- (UILabel *)titleLabel {
+    if (!_titleLabel) {
+        _titleLabel = [[UILabel alloc]initWithFrame:self.pickerStyle.titleLabelFrame];
+        _titleLabel.backgroundColor = self.pickerStyle.titleLabelColor;
+        _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
+        _titleLabel.textAlignment = NSTextAlignmentCenter;
+        _titleLabel.font = self.pickerStyle.titleTextFont;
+        _titleLabel.textColor = self.pickerStyle.titleTextColor;
+        _titleLabel.text = self.title;
+    }
+    return _titleLabel;
+}
+
+#pragma mark - 点击蒙层视图事件
+- (void)didTapMaskView:(UITapGestureRecognizer *)sender {
+    [self removePickerFromView:nil];
+    if (self.cancelBlock) {
+        self.cancelBlock();
+    }
+}
+
+#pragma mark - 取消按钮的点击事件
+- (void)clickCancelBtn {
+    [self removePickerFromView:nil];
+    if (self.cancelBlock) {
+        self.cancelBlock();
+    }
+}
+
+#pragma mark - 确定按钮的点击事件
+- (void)clickDoneBtn {
+    [self removePickerFromView:nil];
+    if (self.doneBlock) {
+        self.doneBlock();
+    }
+}
+
+#pragma mark - 添加视图方法
+- (void)addPickerToView:(UIView *)view {
+    if (view) {
+        self.frame = view.bounds;
+        self.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+        
+        CGFloat accessoryViewHeight = 0;
+        if (self.pickerHeaderView) {
+            CGRect rect = self.pickerHeaderView.frame;
+            self.pickerHeaderView.frame = CGRectMake(0, 0, view.bounds.size.width, rect.size.height);
+            self.pickerHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+            [self addSubview:self.pickerHeaderView];
+            
+            accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
+        }
+        if (self.pickerFooterView) {
+            CGRect rect = self.pickerFooterView.frame;
+            self.pickerFooterView.frame = CGRectMake(0, view.bounds.size.height - rect.size.height, view.bounds.size.width, rect.size.height);
+            self.pickerFooterView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+            [self addSubview:self.pickerFooterView];
+            
+            accessoryViewHeight += self.pickerFooterView.bounds.size.height;
+        }
+        
+        [view addSubview:self];
+    } else {
+        [self initUI];
+        
+        if (self.pickerHeaderView) {
+            CGRect rect = self.pickerHeaderView.frame;
+            CGFloat titleBarHeight = self.pickerStyle.hiddenTitleBarView ? 0 : self.pickerStyle.titleBarHeight;
+            self.pickerHeaderView.frame = CGRectMake(0, titleBarHeight, self.alertView.bounds.size.width, rect.size.height);
+            self.pickerHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+            [self.alertView addSubview:self.pickerHeaderView];
+        }
+        if (self.pickerFooterView) {
+            CGRect rect = self.pickerFooterView.frame;
+            self.pickerFooterView.frame = CGRectMake(0, self.alertView.bounds.size.height - self.pickerStyle.paddingBottom - rect.size.height, self.alertView.bounds.size.width, rect.size.height);
+            self.pickerFooterView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+            [self.alertView addSubview:self.pickerFooterView];
+        }
+    
+        [self.keyView addSubview:self];
+        
+        // iOS16:重新设置 alertView 高度(解决懒加载设置frame不生效问题)
+        CGFloat accessoryViewHeight = 0;
+        if (self.pickerHeaderView) {
+            accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
+        }
+        if (self.pickerFooterView) {
+            accessoryViewHeight += self.pickerFooterView.bounds.size.height;
+        }
+        CGFloat height = self.pickerStyle.titleBarHeight + self.pickerStyle.pickerHeight + self.pickerStyle.paddingBottom + accessoryViewHeight;
+        self.alertView.frame = CGRectMake(0, self.keyView.bounds.size.height - height, self.keyView.bounds.size.width, height);
+        
+        // 动画前初始位置
+        CGRect rect = self.alertView.frame;
+        rect.origin.y = self.bounds.size.height;
+        self.alertView.frame = rect;
+        // 弹出动画
+        if (!self.pickerStyle.hiddenMaskView) {
+            self.maskView.alpha = 0;
+        }
+        [UIView animateWithDuration:0.3f animations:^{
+            if (!self.pickerStyle.hiddenMaskView) {
+                self.maskView.alpha = 1;
+            }
+            CGFloat alertViewHeight = self.alertView.bounds.size.height;
+            CGRect rect = self.alertView.frame;
+            rect.origin.y -= alertViewHeight;
+            self.alertView.frame = rect;
+        }];
+    }
+}
+
+#pragma mark - 移除视图方法
+- (void)removePickerFromView:(UIView *)view {
+    if (view) {
+        [self removeFromSuperview];
+    } else {
+        // 关闭动画
+        [UIView animateWithDuration:0.2f animations:^{
+            CGFloat alertViewHeight = self.alertView.bounds.size.height;
+            CGRect rect = self.alertView.frame;
+            rect.origin.y += alertViewHeight;
+            self.alertView.frame = rect;
+            if (!self.pickerStyle.hiddenMaskView) {
+                self.maskView.alpha = 0;
+            }
+        } completion:^(BOOL finished) {
+            [self removeFromSuperview];
+        }];
+    }
+}
+
+#pragma mark - 刷新选择器数据
+- (void)reloadData {
+    
+}
+
+#pragma mark - 添加自定义视图到选择器(picker)上
+- (void)addSubViewToPicker:(UIView *)customView {
+    
+}
+
+#pragma mark - 添加自定义视图到标题栏(titleBar)上
+- (void)addSubViewToTitleBar:(UIView *)customView {
+    if (!self.pickerStyle.hiddenTitleBarView) {
+        [self.titleBarView addSubview:customView];
+    }
+}
+
+- (BRPickerStyle *)pickerStyle {
+    if (!_pickerStyle) {
+        _pickerStyle = [[BRPickerStyle alloc]init];
+    }
+    return _pickerStyle;
+}
+
+- (UIView *)keyView {
+    if (!_keyView) {
+        _keyView = BRGetKeyWindow();
+    }
+    return _keyView;
+}
+
+#pragma mark - setter 方法(支持动态设置标题)
+- (void)setTitle:(NSString *)title {
+    _title = title;
+    if (_titleLabel) {
+        _titleLabel.text = title;
+    }
+}
+
+- (void)dealloc {
+    NSLog(@"%@ dealloc", NSStringFromClass([self class]));
+}
+
+@end

+ 251 - 0
Pods/BRPickerView/BRPickerView/Base/BRPickerStyle.h

@@ -0,0 +1,251 @@
+//
+//  BRPickerStyle.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2019/10/2.
+//  Copyright © 2019 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "BRPickerViewMacro.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+// 边框样式(左边取消按钮/右边确定按钮)
+typedef NS_ENUM(NSInteger, BRBorderStyle) {
+    /** 无边框(默认) */
+    BRBorderStyleNone = 0,
+    /** 有圆角和边框 */
+    BRBorderStyleSolid,
+    /** 仅有圆角 */
+    BRBorderStyleFill
+};
+
+@interface BRPickerStyle : NSObject
+
+
+/////////////////////////////// 蒙层视图(maskView)///////////////////////////////
+
+/** 设置背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *maskColor;
+
+/** 隐藏 maskView,默认为 NO */
+@property (nonatomic, assign) BOOL hiddenMaskView;
+
+
+////////////////////////////// 弹框视图(alertView)///////////////////////////////
+
+/** 设置 alertView 弹框视图的背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *alertViewColor;
+
+/** 设置 alertView 弹框视图左上和右上的圆角半径  */
+@property (nonatomic, assign) NSInteger topCornerRadius;
+
+/** 设置 alertView 弹框视图顶部边框线颜色  */
+@property (nullable, nonatomic, strong) UIColor *shadowLineColor;
+
+/** 设置 alertView 弹框视图顶部边框线高度  */
+@property (nonatomic, assign) CGFloat shadowLineHeight;
+
+/** 隐藏 alertView 弹框视图顶部边框线,默认为 NO */
+@property (nonatomic, assign) BOOL hiddenShadowLine;
+
+/** 设置 alertView 弹框视图底部内边距,默认为安全区域底部距屏幕底部的高度  */
+@property (nonatomic, assign) CGFloat paddingBottom;
+
+
+//////////////////////////// 标题栏视图(titleBarView) ////////////////////////////
+
+/** 设置 titleBarView 标题栏的背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *titleBarColor;
+
+/** 设置 titleBarView 标题栏的高度 */
+@property (nonatomic, assign) CGFloat titleBarHeight;
+
+/** 设置 titleBarView 标题栏底部分割线颜色 */
+@property (nullable, nonatomic, strong) UIColor *titleLineColor;
+
+/** 隐藏 titleBarView 标题栏底部分割线,默认为 NO  */
+@property (nonatomic, assign) BOOL hiddenTitleLine;
+
+/** 隐藏 titleBarView,默认为 NO */
+@property (nonatomic, assign) BOOL hiddenTitleBarView;
+
+
+////////////////////////// 标题栏中间label(titleLabel)///////////////////////////
+
+/** 设置 titleLabel 的背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *titleLabelColor;
+
+/** 设置 titleLabel 文本颜色 */
+@property (nullable, nonatomic, strong) UIColor *titleTextColor;
+
+/** 设置 titleLabel 字体大小 */
+@property (nullable, nonatomic, strong) UIFont *titleTextFont;
+
+/** 设置 titleLabel 的 frame */
+@property (nonatomic, assign) CGRect titleLabelFrame;
+
+/** 隐藏 titleLabel,默认为 NO */
+@property (nonatomic, assign) BOOL hiddenTitleLabel;
+
+
+/////////////////////////////// 取消按钮(cancelBtn)//////////////////////////////
+
+/** 设置 cancelBtn 的背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *cancelColor;
+
+/** 设置 cancelBtn 标题的颜色 */
+@property (nullable, nonatomic, strong) UIColor *cancelTextColor;
+
+/** 设置 cancelBtn 标题的字体 */
+@property (nullable, nonatomic, strong) UIFont *cancelTextFont;
+
+/** 设置 cancelBtn 的 frame */
+@property (nonatomic, assign) CGRect cancelBtnFrame;
+
+/** 设置 cancelBtn 的边框样式 */
+@property (nonatomic, assign) BRBorderStyle cancelBorderStyle;
+
+/** 设置 cancelBtn 的圆角大小 */
+@property (nonatomic, assign) CGFloat cancelCornerRadius;
+
+/** 设置 cancelBtn 的边框宽度 */
+@property (nonatomic, assign) CGFloat cancelBorderWidth;
+
+/** 设置 cancelBtn 的 image */
+@property (nullable, nonatomic, strong) UIImage *cancelBtnImage;
+
+/** 设置 cancelBtn 的 title */
+@property (nullable, nonatomic, copy) NSString *cancelBtnTitle;
+
+/** 隐藏 cancelBtn,默认为 NO */
+@property (nonatomic, assign) BOOL hiddenCancelBtn;
+
+
+/////////////////////////////// 确定按钮(doneBtn)////////////////////////////////
+
+/** 设置 doneBtn 的背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *doneColor;
+
+/** 设置 doneBtn 标题的颜色 */
+@property (nullable, nonatomic, strong) UIColor *doneTextColor;
+
+/** 设置 doneBtn 标题的字体 */
+@property (nullable, nonatomic, strong) UIFont *doneTextFont;
+
+/** 设置 doneBtn 的 frame */
+@property (nonatomic, assign) CGRect doneBtnFrame;
+
+/** 设置 doneBtn 的边框样式 */
+@property (nonatomic, assign) BRBorderStyle doneBorderStyle;
+
+/** 设置 doneBtn 的圆角大小 */
+@property (nonatomic, assign) CGFloat doneCornerRadius;
+
+/** 设置 doneBtn 的边框宽度 */
+@property (nonatomic, assign) CGFloat doneBorderWidth;
+
+/** 设置 doneBtn 的 image */
+@property (nullable, nonatomic, strong) UIImage *doneBtnImage;
+
+/** 设置 doneBtn 的 title */
+@property (nullable, nonatomic, copy) NSString *doneBtnTitle;
+
+/** 隐藏 doneBtn,默认为 NO */
+@property (nonatomic, assign) BOOL hiddenDoneBtn;
+
+
+/////////////////////////////// 选择器(pickerView)///////////////////////////////
+
+/** 设置 picker 的背景颜色 */
+@property (nullable, nonatomic, strong) UIColor *pickerColor;
+
+/** 设置 picker 中间两条分割线的背景颜色。暂不支持日期选择器前4种类型 */
+@property (nullable, nonatomic, strong) UIColor *separatorColor;
+
+/** 设置 picker 中间两条分割线的高度。暂不支持日期选择器前4种类型 */
+@property (nonatomic, assign) CGFloat separatorHeight;
+
+/** 设置 picker 文本的颜色。暂不支持日期选择器前4种类型 */
+@property (nullable, nonatomic, strong) UIColor *pickerTextColor;
+
+/** 设置 picker 文本的字体。暂不支持日期选择器前4种类型 */
+@property (nullable, nonatomic, strong) UIFont *pickerTextFont;
+
+/** 设置 picker 中间选中行的背景颜色。暂不支持日期选择器前4种类型 */
+@property (nullable, nonatomic, strong) UIColor *selectRowColor;
+
+/** 设置 picker 中间选中行文本的颜色。暂不支持日期选择器前4种类型 */
+@property (nullable, nonatomic, strong) UIColor *selectRowTextColor;
+
+/** 设置 picker 中间选中行文本的字体。暂不支持日期选择器前4种类型 */
+@property (nullable, nonatomic, strong) UIFont *selectRowTextFont;
+
+/** 设置 picker 的高度,系统默认高度为 216 */
+@property (nonatomic, assign) CGFloat pickerHeight;
+
+/** 设置 picker 的行高。暂不支持日期选择器前4种类型 */
+@property (nonatomic, assign) CGFloat rowHeight;
+
+/**
+ *  清除iOS14之后选择器默认自带的新样式。暂不支持日期选择器前4种类型
+ *  主要是:①隐藏中间选择行的背景样式,②清除默认的内边距,③新增中间选择行的两条分割线;与iOS14之前的样式保持一致),默认为 YES
+ */
+@property (nonatomic, assign) BOOL clearPickerNewStyle;
+
+
+/**
+ *  设置语言(不设置或为nil时,将随系统的语言自动改变)
+ *  language: zh-Hans(简体中文)、zh-Hant(繁体中文)、en(英语 )
+ */
+@property(nullable, nonatomic, copy) NSString *language;
+
+
+/////// 日期选择器单位样式(showUnitType == BRShowUnitTypeOnlyCenter 时生效。暂不支持日期选择器前4种类型 )///////
+
+/** 设置日期选择器单位文本的颜色 */
+@property (nullable, nonatomic, strong) UIColor *dateUnitTextColor;
+
+/** 设置日期选择器单位文本的字体 */
+@property (nullable, nonatomic, strong) UIFont *dateUnitTextFont;
+
+/** 设置日期选择器单位 label 的水平方向偏移量 */
+@property (nonatomic, assign) CGFloat dateUnitOffsetX;
+
+/** 设置日期选择器单位 label 的竖直方向偏移量 */
+@property (nonatomic, assign) CGFloat dateUnitOffsetY;
+
+
+//////////////////////////////// 常用的几种模板样式 ////////////////////////////////
+
+/// 弹框模板样式1 - 取消/确定按钮圆角样式
+/// @param themeColor 主题颜色
++ (instancetype)pickerStyleWithThemeColor:(nullable UIColor *)themeColor;
+
+/// 弹框模板样式2 - 顶部圆角样式 + 完成按钮
+/// @param doneTextColor 完成按钮标题的颜色
++ (instancetype)pickerStyleWithDoneTextColor:(nullable UIColor *)doneTextColor;
+
+/// 弹框模板样式3 - 顶部圆角样式 + 图标按钮
+/// @param doneBtnImage 完成按钮的 image
++ (instancetype)pickerStyleWithDoneBtnImage:(nullable UIImage *)doneBtnImage;
+
+
+//////////////////////////////// 以下是组件内部使用的几个封装方法 ////////////////////////////////
+
+/** 设置选择器中间选中行的样式 */
+- (void)setupPickerSelectRowStyle:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
+
+/** 添加选择器中间行上下两条分割线(iOS14之后系统默认去掉,需要手动添加)*/
+- (void)addSeparatorLineView:(UIView *)pickerView;
+
+/** 设置 view 的部分圆角 */
+// corners(枚举类型,可组合使用):UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerAllCorners
++ (void)br_setView:(UIView *)view roundingCorners:(UIRectCorner)corners withRadius:(CGFloat)radius;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 494 - 0
Pods/BRPickerView/BRPickerView/Base/BRPickerStyle.m

@@ -0,0 +1,494 @@
+//
+//  BRPickerStyle.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2019/10/2.
+//  Copyright © 2019 irenb. All dones reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRPickerStyle.h"
+#import "NSBundle+BRPickerView.h"
+
+// 标题颜色
+#define kBRDefaultTextColor BR_RGB_HEX(0x333333, 1.0f)
+
+@implementation BRPickerStyle
+
+- (instancetype)init {
+    if (self = [super init]) {
+        self.clearPickerNewStyle = YES;
+    }
+    return self;
+}
+
+/// 设置默认样式
+
+- (UIColor *)maskColor {
+    if (!_maskColor) {
+        _maskColor = [self br_colorWithLightColor:BR_RGB_HEX(0x000000, 0.3f) darkColor:BR_RGB_HEX(0x666666, 0.3f)];
+    }
+    return _maskColor;
+}
+
+- (UIColor *)shadowLineColor {
+    if (!_shadowLineColor) {
+        if (@available(iOS 13.0, *)) {
+            // 边框线颜色,有透明度
+            _shadowLineColor = [UIColor separatorColor];
+        } else {
+            _shadowLineColor = BR_RGB_HEX(0xc6c6c8, 1.0f);
+        }
+    }
+    return _shadowLineColor;
+}
+
+- (CGFloat)shadowLineHeight {
+    if (_shadowLineHeight <= 0 || _shadowLineHeight > 5.0f) {
+        _shadowLineHeight = 0.5f;
+    }
+    return _shadowLineHeight;
+}
+
+- (CGFloat)paddingBottom {
+    if (_paddingBottom <= 0) {
+        _paddingBottom = BR_BOTTOM_MARGIN;
+    }
+    return _paddingBottom;
+}
+
+- (UIColor *)titleBarColor {
+    if (!_titleBarColor) {
+        if (@available(iOS 13.0, *)) {
+            // #ffffff(正常)、#1c1c1e(深色)
+            _titleBarColor = [UIColor secondarySystemGroupedBackgroundColor];
+        } else {
+            _titleBarColor = [UIColor whiteColor];
+        }
+    }
+    return _titleBarColor;
+}
+
+- (CGFloat)titleBarHeight {
+    if (!self.hiddenTitleBarView) {
+        if (_titleBarHeight < 44.0f && (!self.hiddenCancelBtn || !self.hiddenDoneBtn || !self.hiddenTitleLabel)) {
+            _titleBarHeight = 44.0f;
+        }
+    } else {
+        _titleBarHeight = 0;
+    }
+    return _titleBarHeight;
+}
+
+- (UIColor *)titleLineColor {
+    if (!_titleLineColor) {
+        _titleLineColor = [self br_colorWithLightColor:BR_RGB_HEX(0xededee, 1.0f) darkColor:BR_RGB_HEX(0x18181c, 1.0f)];
+    }
+    return _titleLineColor;
+}
+
+- (UIColor *)cancelColor {
+    if (!_cancelColor) {
+        _cancelColor = [UIColor clearColor];
+    }
+    return _cancelColor;
+}
+
+- (UIColor *)cancelTextColor {
+    if (!_cancelTextColor) {
+        if (@available(iOS 13.0, *)) {
+            _cancelTextColor = [UIColor labelColor];
+        } else {
+            _cancelTextColor = kBRDefaultTextColor;
+        }
+    }
+    return _cancelTextColor;
+}
+
+- (UIFont *)cancelTextFont {
+    if (!_cancelTextFont) {
+        _cancelTextFont = [UIFont systemFontOfSize:16.0f];
+    }
+    return _cancelTextFont;
+}
+
+- (NSString *)cancelBtnTitle {
+    if (!_cancelBtnTitle && !_cancelBtnImage) {
+        _cancelBtnTitle = [NSBundle br_localizedStringForKey:@"取消" language:self.language];
+    }
+    return _cancelBtnTitle;
+}
+
+- (CGRect)cancelBtnFrame {
+    if (CGRectEqualToRect(_cancelBtnFrame, CGRectZero) || _cancelBtnFrame.size.height == 0) {
+        _cancelBtnFrame = CGRectMake(5, 8, 60, 28);
+    }
+    return _cancelBtnFrame;
+}
+
+- (UIColor *)titleLabelColor {
+    if (!_titleLabelColor) {
+        _titleLabelColor = [UIColor clearColor];
+    }
+    return _titleLabelColor;
+}
+
+- (UIColor *)titleTextColor {
+    if (!_titleTextColor) {
+        if (@available(iOS 13.0, *)) {
+            _titleTextColor = [UIColor secondaryLabelColor];
+        } else {
+            _titleTextColor = BR_RGB_HEX(0x999999, 1.0f);
+        }
+    }
+    return _titleTextColor;
+}
+
+- (UIFont *)titleTextFont {
+    if (!_titleTextFont) {
+        _titleTextFont = [UIFont systemFontOfSize:15.0f];
+    }
+    return _titleTextFont;
+}
+
+- (CGRect)titleLabelFrame {
+    if (CGRectEqualToRect(_titleLabelFrame, CGRectZero) || _titleLabelFrame.size.height == 0) {
+        _titleLabelFrame = CGRectMake(5 + 60 + 2, 0, BRGetKeyWindow().bounds.size.width - 2 * (5 + 60 + 2), 44);
+    }
+    return _titleLabelFrame;
+}
+
+- (UIColor *)doneColor {
+    if (!_doneColor) {
+        _doneColor = [UIColor clearColor];
+    }
+    return _doneColor;
+}
+
+- (UIColor *)doneTextColor {
+    if (!_doneTextColor) {
+        if (@available(iOS 13.0, *)) {
+            _doneTextColor = [UIColor labelColor];
+        } else {
+            _doneTextColor = kBRDefaultTextColor;
+        }
+    }
+    return _doneTextColor;
+}
+
+- (UIFont *)doneTextFont {
+    if (!_doneTextFont) {
+        _doneTextFont = [UIFont systemFontOfSize:16.0f];
+    }
+    return _doneTextFont;
+}
+
+- (NSString *)doneBtnTitle {
+    if (!_doneBtnTitle && !_doneBtnImage) {
+        _doneBtnTitle = [NSBundle br_localizedStringForKey:@"确定" language:self.language];
+    }
+    return _doneBtnTitle;
+}
+
+- (CGRect)doneBtnFrame {
+    if (CGRectEqualToRect(_doneBtnFrame, CGRectZero) || _doneBtnFrame.size.height == 0) {
+        _doneBtnFrame = CGRectMake(BRGetKeyWindow().bounds.size.width - 60 - 5, 8, 60, 28);
+    }
+    return _doneBtnFrame;
+}
+
+- (UIColor *)pickerColor {
+    if (!_pickerColor) {
+        if (@available(iOS 13.0, *)) {
+            // #ffffff(正常)、#1c1c1e(深色)
+            _pickerColor = [UIColor secondarySystemGroupedBackgroundColor];
+        } else {
+            _pickerColor = [UIColor whiteColor];
+        }
+    }
+    return _pickerColor;
+}
+
+- (UIColor *)separatorColor {
+    if (!_separatorColor) {
+        if (@available(iOS 13.0, *)) {
+            // 分割线颜色,无透明度
+            _separatorColor = [UIColor opaqueSeparatorColor];
+        } else {
+            _separatorColor = BR_RGB_HEX(0xc6c6c8, 1.0f);
+        }
+    }
+    return _separatorColor;
+}
+
+- (UIColor *)pickerTextColor {
+    if (!_pickerTextColor) {
+        if (@available(iOS 13.0, *)) {
+            _pickerTextColor = [UIColor labelColor];
+        } else {
+            _pickerTextColor = kBRDefaultTextColor;
+        }
+    }
+    return _pickerTextColor;
+}
+
+- (UIFont *)pickerTextFont {
+    if (!_pickerTextFont) {
+        _pickerTextFont = [UIFont systemFontOfSize:18.0f];
+    }
+    return _pickerTextFont;
+}
+
+- (CGFloat)pickerHeight {
+    if (_pickerHeight < 40) {
+        _pickerHeight = 216.0f;
+    }
+    return _pickerHeight;
+}
+
+- (CGFloat)rowHeight {
+    if (_rowHeight < 20) {
+        _rowHeight = 35.0f;
+    }
+    return _rowHeight;
+}
+
+- (NSString *)language {
+    if (!_language) {
+        // 跟随系统的首选语言自动改变
+        // zh-Hans-CN(简体中文)、zh-Hant-CN(繁体中文)、en-CN(美式英语)、en-GB(英式英语)
+        // 其中`CN`是iOS9以后新增的地区代码,如:CN 代表中国,US 代表美国
+        _language = [NSLocale preferredLanguages].firstObject;
+    }
+    return _language;
+}
+
+- (UIColor *)dateUnitTextColor {
+    if (!_dateUnitTextColor) {
+        if (@available(iOS 13.0, *)) {
+            _dateUnitTextColor = [UIColor labelColor];
+        } else {
+            _dateUnitTextColor = kBRDefaultTextColor;
+        }
+    }
+    return _dateUnitTextColor;
+}
+
+- (UIFont *)dateUnitTextFont {
+    if (!_dateUnitTextFont) {
+        _dateUnitTextFont = [UIFont systemFontOfSize:18.0f];
+    }
+    return _dateUnitTextFont;
+}
+
+#pragma mark - 创建自定义动态颜色(适配深色模式)
+- (UIColor *)br_colorWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor {
+    if (@available(iOS 13.0, *)) {
+        UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
+            if ([traitCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
+                return lightColor;
+            } else {
+                return darkColor;
+            }
+        }];
+        return dyColor;
+    } else {
+        return lightColor;
+    }
+}
+
+#pragma mark - 弹框模板样式1 - 取消/确定按钮圆角样式
++ (instancetype)pickerStyleWithThemeColor:(UIColor *)themeColor {
+    BRPickerStyle *customStyle = [[self alloc]init];
+    if (themeColor) {
+        customStyle.cancelTextColor = themeColor;
+        customStyle.cancelBorderStyle = BRBorderStyleSolid;
+        customStyle.doneColor = themeColor;
+        customStyle.doneTextColor = [UIColor whiteColor];
+        customStyle.doneBorderStyle = BRBorderStyleFill;
+    }
+    return customStyle;
+}
+
+#pragma mark - 弹框模板样式2 - 顶部圆角样式 + 完成按钮
++ (instancetype)pickerStyleWithDoneTextColor:(UIColor *)doneTextColor {
+    BRPickerStyle *customStyle = [[self alloc]init];
+    if (doneTextColor) {
+        customStyle.topCornerRadius = 16.0f;
+        customStyle.hiddenCancelBtn = YES;
+        customStyle.hiddenTitleLine = YES;
+        customStyle.titleLabelFrame = CGRectMake(20, 4, 100, 40);
+        customStyle.doneTextColor = doneTextColor;
+        customStyle.doneTextFont = [UIFont boldSystemFontOfSize:18.0f];
+        customStyle.doneBtnFrame = CGRectMake(BRGetKeyWindow().bounds.size.width - 60, 4, 60, 40);
+        customStyle.doneBtnTitle = [NSBundle br_localizedStringForKey:@"完成" language:customStyle.language];
+        customStyle.selectRowTextColor = doneTextColor;
+        customStyle.selectRowTextFont = [UIFont boldSystemFontOfSize:20.0f];
+    }
+    return customStyle;
+}
+
+#pragma mark - 弹框模板样式3 - 顶部圆角样式 + 图标按钮
++ (instancetype)pickerStyleWithDoneBtnImage:(UIImage *)doneBtnImage {
+    BRPickerStyle *customStyle = [[self alloc]init];
+    if (doneBtnImage) {
+        customStyle.topCornerRadius = 16.0f;
+        customStyle.hiddenTitleLine = YES;
+        customStyle.hiddenCancelBtn = YES;
+        customStyle.titleLabelFrame = CGRectMake(20, 4, 100, 40);
+        customStyle.doneBtnImage = doneBtnImage;
+        customStyle.doneBtnFrame = CGRectMake(BRGetKeyWindow().bounds.size.width - 44, 4, 40, 40);
+    }
+    return customStyle;
+}
+
+
+#pragma mark - 设置选择器中间选中行的样式
+- (void)setupPickerSelectRowStyle:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
+    // 1.设置分割线的颜色
+    NSString *systemVersion = [UIDevice currentDevice].systemVersion;
+    if (systemVersion.doubleValue < 14.0) {
+        for (UIView *subView in pickerView.subviews) {
+            if (subView && [subView isKindOfClass:[UIView class]] && subView.frame.size.height <= 1) {
+                subView.backgroundColor = self.separatorColor;
+                // 设置分割线高度
+                if (self.separatorHeight > 0) {
+                    CGRect rect = subView.frame;
+                    rect.size.height = self.separatorHeight;
+                    subView.frame = rect;
+                }
+            }
+        }
+    }
+    
+    // 2.设置选择器中间选中行的背景颜色
+    UIView *contentView = nil;
+    NSArray *subviews = pickerView.subviews;
+    if (subviews.count > 0) {
+        id firstView = subviews.firstObject;
+        if (firstView && [firstView isKindOfClass:[UIView class]]) {
+            contentView = (UIView *)firstView;
+        }
+    }
+    if (self.selectRowColor) {
+        UIView *columnView = nil;
+        if (contentView) {
+            id obj = [contentView valueForKey:@"subviewCache"];
+            if (obj && [obj isKindOfClass:[NSArray class]]) {
+                NSArray *columnViews = (NSArray *)obj;
+                if (columnViews.count > 0) {
+                    id columnObj = columnViews.firstObject;
+                    if (columnObj && [columnObj isKindOfClass:[UIView class]]) {
+                        columnView = (UIView *)columnObj;
+                    }
+                }
+            }
+        }
+        if (columnView) {
+            id obj = [columnView valueForKey:@"middleContainerView"];
+            if (obj && [obj isKindOfClass:[UIView class]]) {
+                UIView *selectRowView = (UIView *)obj;
+                // 中间选中行的背景颜色
+                selectRowView.backgroundColor = self.selectRowColor;
+            }
+        }
+    }
+    
+    if (contentView && self.clearPickerNewStyle) {
+        if (systemVersion.doubleValue >= 14.0) {
+            // ①隐藏中间选择行的背景样式
+            id lastView = subviews.lastObject;
+            if (lastView && [lastView isKindOfClass:[UIView class]]) {
+                UIView *rectBgView = (UIView *)lastView;
+                rectBgView.hidden = YES;
+            }
+            
+            // ②清除iOS14上选择器默认的内边距
+            if (systemVersion.doubleValue < 15.0f) {
+                [self setPickerAllSubViewsStyle:contentView];
+            }
+        }
+    }
+    
+    // 3.设置选择器中间选中行的字体颜色/字体大小
+    if (self.selectRowTextColor || self.selectRowTextFont) {
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+            // 当前选中的 label
+            UILabel *selectLabel = (UILabel *)[pickerView viewForRow:row forComponent:component];
+            if (selectLabel) {
+                if (self.selectRowTextColor) {
+                    selectLabel.textColor = self.selectRowTextColor;
+                }
+                if (self.selectRowTextFont) {
+                    selectLabel.font = self.selectRowTextFont;
+                }
+            }
+        });
+    }
+}
+
+// 遍历子视图,重新设置 frame(清空在 iOS14 上 UIPickerView 出现的内边距)
+- (void)setPickerAllSubViewsStyle:(UIView *)view {
+    NSArray *subViews = view.subviews;
+    if (subViews.count == 0 || [view isKindOfClass:[UILabel class]]) return;
+    for (UIView *subView in subViews) {
+        NSString *className = NSStringFromClass([subView class]);
+        if ([className isEqualToString:@"UIPickerColumnView"]) {
+            CGRect rect = subView.frame;
+            rect.origin.x = 0;
+            rect.size.width = view.bounds.size.width;
+            subView.frame = rect;
+        }
+        NSString *superClassName = NSStringFromClass([view class]);
+        if ([superClassName isEqualToString:@"UIPickerColumnView"]) {
+            CGRect rect = subView.frame;
+            rect.size.width = view.bounds.size.width;
+            subView.frame = rect;
+        }
+        if ([subView isKindOfClass:[UILabel class]]) {
+            CGRect rect = subView.frame;
+            rect.origin.x = 10;
+            subView.frame = rect;
+        }
+        
+        [self setPickerAllSubViewsStyle:subView];
+    }
+}
+
+#pragma mark - 添加选择器中间行上下两条分割线(iOS14之后系统默认去掉,需要手动添加)
+- (void)addSeparatorLineView:(UIView *)pickerView {
+    if ([UIDevice currentDevice].systemVersion.doubleValue >= 14.0) {
+        UIView *topLineView = [[UIView alloc]initWithFrame:CGRectMake(0, pickerView.bounds.size.height / 2 - self.rowHeight / 2, pickerView.bounds.size.width, 0.5f)];
+        topLineView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
+        topLineView.backgroundColor = self.separatorColor;
+        // 设置分割线高度
+        if (self.separatorHeight > 0) {
+            CGRect topRect = topLineView.frame;
+            topRect.size.height = self.separatorHeight;
+            topLineView.frame = topRect;
+        }
+        [pickerView addSubview:topLineView];
+        
+        UIView *bottomLineView = [[UIView alloc]initWithFrame:CGRectMake(0, pickerView.bounds.size.height / 2 + self.rowHeight / 2, pickerView.bounds.size.width, 0.5f)];
+        bottomLineView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
+        bottomLineView.backgroundColor = self.separatorColor;
+        // 设置分割线高度
+        if (self.separatorHeight > 0) {
+            CGRect bottomRect = bottomLineView.frame;
+            bottomRect.size.height = self.separatorHeight;
+            bottomLineView.frame = bottomRect;
+        }
+        [pickerView addSubview:bottomLineView];
+    }
+}
+
+#pragma mark - 设置 view 的部分圆角
+// corners(枚举类型,可组合使用):UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerAllCorners
++ (void)br_setView:(UIView *)view roundingCorners:(UIRectCorner)corners withRadius:(CGFloat)radius {
+    UIBezierPath *rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
+    CAShapeLayer *shape = [[CAShapeLayer alloc]init];
+    [shape setPath:rounded.CGPath];
+    view.layer.mask = shape;
+}
+
+@end

+ 35 - 0
Pods/BRPickerView/BRPickerView/Base/BRPickerView.bundle/en.lproj/Localizable.strings

@@ -0,0 +1,35 @@
+/* 
+  Localizable.strings
+  BRPickerViewDemo
+
+  Created by renbo on 2019/10/30.
+  Copyright © 2019 irenb. All rights reserved.
+*/
+
+"确定" = "OK";
+"取消" = "Cancel";
+"完成" = "Done";
+
+"年" = " ";
+"月" = " ";
+"日" = " ";
+"时" = " ";
+"分" = " ";
+"秒" = " ";
+
+"周" = " ";
+"季度" = " ";
+
+"上午" = "AM";
+"下午" = "PM";
+
+"至今" = " Now";
+"今天" = " Today";
+
+"周一" = " Mon";
+"周二" = " Tue";
+"周三" = " Wed";
+"周四" = " Thu";
+"周五" = " Fri";
+"周六" = " Sat";
+"周日" = " Sun";

+ 35 - 0
Pods/BRPickerView/BRPickerView/Base/BRPickerView.bundle/zh-Hans.lproj/Localizable.strings

@@ -0,0 +1,35 @@
+/* 
+  Localizable.strings
+  BRPickerViewDemo
+
+  Created by renbo on 2019/10/30.
+  Copyright © 2019 irenb. All rights reserved.
+*/
+
+"确定" = "确定";
+"取消" = "取消";
+"完成" = "完成";
+
+"年" = "年";
+"月" = "月";
+"日" = "日";
+"时" = "时";
+"分" = "分";
+"秒" = "秒";
+
+"周" = "周";
+"季度" = "季度";
+
+"上午" = "上午";
+"下午" = "下午";
+
+"至今" = "至今";
+"今天" = "今天";
+
+"周一" = "周一";
+"周二" = "周二";
+"周三" = "周三";
+"周四" = "周四";
+"周五" = "周五";
+"周六" = "周六";
+"周日" = "周日";

+ 35 - 0
Pods/BRPickerView/BRPickerView/Base/BRPickerView.bundle/zh-Hant.lproj/Localizable.strings

@@ -0,0 +1,35 @@
+/* 
+  Localizable.strings
+  BRPickerViewDemo
+
+  Created by renbo on 2019/10/30.
+  Copyright © 2019 irenb. All rights reserved.
+*/
+
+"确定" = "確定";
+"取消" = "取消";
+"完成" = "完成";
+
+"年" = "年";
+"月" = "月";
+"日" = "日";
+"时" = "時";
+"分" = "分";
+"秒" = "秒";
+
+"周" = "周";
+"季度" = "季度";
+
+"上午" = "上午";
+"下午" = "下午";
+
+"至今" = "至今";
+"今天" = "今天";
+
+"周一" = "周壹";
+"周二" = "周二";
+"周三" = "周三";
+"周四" = "周四";
+"周五" = "周五";
+"周六" = "周六";
+"周日" = "周日";

+ 87 - 0
Pods/BRPickerView/BRPickerView/Base/BRPickerViewMacro.h

@@ -0,0 +1,87 @@
+//
+//  BRPickerViewMacro.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2018/4/23.
+//  Copyright © 2018 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#ifndef BRPickerViewMacro_h
+#define BRPickerViewMacro_h
+
+#import <UIKit/UIKit.h>
+
+// 屏幕安全区域下边距
+#define BR_BOTTOM_MARGIN \
+({CGFloat safeBottomHeight = 0;\
+if (@available(iOS 11.0, *)) {\
+safeBottomHeight = BRGetKeyWindow().safeAreaInsets.bottom;\
+}\
+(safeBottomHeight);})
+
+
+// 静态库中编写 Category 时的便利宏,用于解决 Category 方法从静态库中加载需要特别设置的问题
+#ifndef BRSYNTH_DUMMY_CLASS
+
+#define BRSYNTH_DUMMY_CLASS(_name_) \
+@interface BRSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
+@implementation BRSYNTH_DUMMY_CLASS_ ## _name_ @end
+
+#endif
+
+
+// 打印错误日志
+#ifdef DEBUG
+    #define BRErrorLog(...) NSLog(@"reason: %@", [NSString stringWithFormat:__VA_ARGS__])
+#else
+    #define BRErrorLog(...)
+#endif
+
+
+/** RGB颜色(16进制) */
+static inline UIColor *BR_RGB_HEX(uint32_t rgbValue, CGFloat alpha) {
+    return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255.0
+                           green:((CGFloat)((rgbValue & 0xFF00) >> 8)) / 255.0
+                            blue:((CGFloat)(rgbValue & 0xFF)) / 255.0
+                           alpha:(alpha)];
+}
+
+
+/** 获取 keyWindow */
+static inline UIWindow *BRGetKeyWindow(void) {
+    UIWindow *keyWindow = nil;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 // 编译时检查SDK版本(兼容不同版本的Xcode,防止编译报错)
+    if (@available(iOS 13.0, *)) { // 运行时检查系统版本(兼容不同版本的系统,防止运行报错)
+        NSSet<UIScene *> *connectedScenes = [UIApplication sharedApplication].connectedScenes;
+        for (UIScene *scene in connectedScenes) {
+            if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
+                UIWindowScene *windowScene = (UIWindowScene *)scene;
+                for (UIWindow *window in windowScene.windows) {
+                    if (window.isKeyWindow) {
+                        keyWindow = window;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+#endif
+        
+    if (!keyWindow) {
+        keyWindow = [UIApplication sharedApplication].windows.firstObject;
+        if (!keyWindow.isKeyWindow) {
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
+            UIWindow *window = [UIApplication sharedApplication].keyWindow;
+            if (CGRectEqualToRect(window.bounds, UIScreen.mainScreen.bounds)) {
+                keyWindow = window;
+            }
+#endif
+        }
+    }
+    
+    return keyWindow;
+}
+
+
+#endif /* BRPickerViewMacro_h */

+ 26 - 0
Pods/BRPickerView/BRPickerView/Base/NSBundle+BRPickerView.h

@@ -0,0 +1,26 @@
+//
+//  NSBundle+BRPickerView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2019/10/30.
+//  Copyright © 2019 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NSBundle (BRPickerView)
+
+/// 获取 BRPickerView.bundle
++ (instancetype)br_pickerBundle;
+
+/// 获取国际化后的文本
+/// @param key 代表 Localizable.strings 文件中 key-value 中的 key。
+/// @param language 设置语言(可为空,为nil时将随系统的语言自动改变)
++ (NSString *)br_localizedStringForKey:(NSString *)key language:(NSString *)language;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 68 - 0
Pods/BRPickerView/BRPickerView/Base/NSBundle+BRPickerView.m

@@ -0,0 +1,68 @@
+//
+//  NSBundle+BRPickerView.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2019/10/30.
+//  Copyright © 2019 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "NSBundle+BRPickerView.h"
+#import "BRBaseView.h"
+
+BRSYNTH_DUMMY_CLASS(NSBundle_BRPickerView)
+
+@implementation NSBundle (BRPickerView)
+
+#pragma mark - 获取 BRPickerView.bundle
++ (instancetype)br_pickerBundle {
+    static NSBundle *pickerBundle = nil;
+    if (!pickerBundle) {
+        /*
+            先拿到最外面的 bundle。
+            对 framework 链接方式来说就是 framework 的 bundle 根目录,
+            对静态库链接方式来说就是 target client 的 main bundle,
+            然后再去找下面名为 BRPickerView 的 bundle 对象。
+         */
+        NSBundle *bundle = [NSBundle bundleForClass:[BRBaseView class]];
+        NSURL *url = [bundle URLForResource:@"BRPickerView" withExtension:@"bundle"];
+        pickerBundle = [NSBundle bundleWithURL:url];
+    }
+    return pickerBundle;
+}
+
+#pragma mark - 获取国际化后的文本
++ (NSString *)br_localizedStringForKey:(NSString *)key language:(NSString *)language {
+    return [self br_localizedStringForKey:key value:nil language:language];
+}
+
++ (NSString *)br_localizedStringForKey:(NSString *)key value:(NSString *)value language:(NSString *)language {
+    static NSBundle *bundle = nil;
+    if (!bundle) {
+        // 如果没有手动设置语言,将随系统的语言自动改变
+        if (!language) {
+            // 系统首选语言
+            language = [NSLocale preferredLanguages].firstObject;
+        }
+        
+        if ([language hasPrefix:@"en"]) {
+            language = @"en";
+        } else if ([language hasPrefix:@"zh"]) {
+            if ([language rangeOfString:@"Hans"].location != NSNotFound) {
+                language = @"zh-Hans"; // 简体中文
+            } else { // zh-Hant、zh-HK、zh-TW
+                language = @"zh-Hant"; // 繁體中文
+            }
+        } else {
+            language = @"en";
+        }
+        
+        // 从 BRPickerView.bundle 中查找资源
+        bundle = [NSBundle bundleWithPath:[[self br_pickerBundle] pathForResource:language ofType:@"lproj"]];
+    }
+    value = [bundle localizedStringForKey:key value:value table:nil];
+    
+    return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
+}
+
+@end

+ 111 - 0
Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView+BR.h

@@ -0,0 +1,111 @@
+//
+//  BRDatePickerView+BR.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2020/6/16.
+//  Copyright © 2020 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRDatePickerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface BRDatePickerView (BR)
+
+/** 最小日期 */
+- (NSDate *)handlerMinDate:(nullable NSDate *)minDate;
+
+/** 最大日期 */
+- (NSDate *)handlerMaxDate:(nullable NSDate *)maxDate;
+
+/** 默认选中的日期 */
+- (NSDate *)handlerSelectDate:(nullable NSDate *)selectDate dateFormat:(NSString *)dateFormat;
+
+/** NSDate 转 NSString */
+- (NSString *)br_stringFromDate:(NSDate *)date dateFormat:(NSString *)dateFormat;
+
+/** NSString 转 NSDate */
+- (NSDate *)br_dateFromString:(NSString *)dateString dateFormat:(NSString *)dateFormat;
+
+/** 比较两个日期大小(可以指定比较级数,即按指定格式进行比较) */
+- (NSComparisonResult)br_compareDate:(NSDate *)date targetDate:(NSDate *)targetDate dateFormat:(NSString *)dateFormat;
+
+/** 获取 yearArr 数组 */
+- (NSArray *)getYearArr;
+
+/** 获取 monthArr 数组 */
+- (NSArray *)getMonthArr:(NSInteger)year;
+
+/** 获取 dayArr 数组 */
+- (NSArray *)getDayArr:(NSInteger)year month:(NSInteger)month;
+
+/** 获取 hourArr 数组 */
+- (NSArray *)getHourArr:(NSInteger)year month:(NSInteger)month day:(NSInteger)day;
+
+/** 获取 minuteArr 数组 */
+- (NSArray *)getMinuteArr:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour;
+
+/** 获取 secondArr 数组 */
+- (NSArray *)getSecondArr:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute;
+
+/**  获取 monthWeekArr 数组 */
+- (NSArray *)getMonthWeekArr:(NSInteger)year month:(NSInteger)month;
+
+/**  获取 yearWeekArr 数组 */
+- (NSArray *)getYearWeekArr:(NSInteger)year;
+
+ /**  获取 quarterArr 数组 */
+- (NSArray *)getQuarterArr:(NSInteger)year;
+
+/** 添加 pickerView */
+- (void)setupPickerView:(UIView *)pickerView toView:(UIView *)view;
+
+/** 设置日期单位 */
+- (NSArray *)setupPickerUnitLabel:(UIPickerView *)pickerView unitArr:(NSArray *)unitArr;
+
+- (NSString *)getYearNumber:(NSInteger)year;
+
+- (NSString *)getMDHMSNumber:(NSInteger)number;
+
+- (NSString *)getYearText:(NSArray *)yearArr row:(NSInteger)row;
+
+- (NSString *)getMonthText:(NSArray *)monthArr row:(NSInteger)row;
+
+- (NSString *)getDayText:(NSArray *)dayArr row:(NSInteger)row mSelectDate:(NSDate *)mSelectDate;
+
+- (NSString *)getHourText:(NSArray *)hourArr row:(NSInteger)row;
+
+- (NSString *)getMinuteText:(NSArray *)minuteArr row:(NSInteger)row;
+
+- (NSString *)getSecondText:(NSArray *)secondArr row:(NSInteger)row;
+
+- (NSString *)getWeekText:(NSArray *)weekArr row:(NSInteger)row;
+
+- (NSString *)getQuarterText:(NSArray *)quarterArr row:(NSInteger)row;
+
+- (NSString *)getAMText;
+
+- (NSString *)getPMText;
+
+- (NSString *)getYearUnit;
+
+- (NSString *)getMonthUnit;
+
+- (NSString *)getDayUnit;
+
+- (NSString *)getHourUnit;
+
+- (NSString *)getMinuteUnit;
+
+- (NSString *)getSecondUnit;
+
+- (NSString *)getWeekUnit;
+
+- (NSString *)getQuarterUnit;
+
+- (NSInteger)getIndexWithArray:(NSArray *)array object:(NSString *)obj;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 755 - 0
Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView+BR.m

@@ -0,0 +1,755 @@
+//
+//  BRDatePickerView+BR.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2020/6/16.
+//  Copyright © 2020 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRDatePickerView+BR.h"
+#import "NSBundle+BRPickerView.h"
+
+BRSYNTH_DUMMY_CLASS(BRDatePickerView_BR)
+
+//////////////////////////////////////////
+/// 本分类主要是给 BRDatePickerView 文件瘦身
+//////////////////////////////////////////
+
+@implementation BRDatePickerView (BR)
+
+#pragma mark - 最小日期
+- (NSDate *)handlerMinDate:(NSDate *)minDate {
+    if (!minDate) {
+        if (self.pickerMode == BRDatePickerModeMDHM) {
+            minDate = [NSDate br_setMonth:1 day:1 hour:0 minute:0];
+        } else if (self.pickerMode == BRDatePickerModeMD) {
+            minDate = [NSDate br_setMonth:1 day:1];
+        } else if (self.pickerMode == BRDatePickerModeTime || self.pickerMode == BRDatePickerModeCountDownTimer || self.pickerMode == BRDatePickerModeHM) {
+            minDate = [NSDate br_setHour:0 minute:0];
+        } else if (self.pickerMode == BRDatePickerModeHMS) {
+            minDate = [NSDate br_setHour:0 minute:0 second:0];
+        } else if (self.pickerMode == BRDatePickerModeMS) {
+            minDate = [NSDate br_setMinute:0 second:0];
+        } else {
+            minDate = [NSDate distantPast]; // 遥远的过去的一个时间点
+        }
+    }
+    return minDate;
+}
+
+#pragma mark - 最大日期
+- (NSDate *)handlerMaxDate:(NSDate *)maxDate {
+    if (!maxDate) {
+        if (self.pickerMode == BRDatePickerModeMDHM) {
+            maxDate = [NSDate br_setMonth:12 day:31 hour:23 minute:59];
+        } else if (self.pickerMode == BRDatePickerModeMD) {
+            maxDate = [NSDate br_setMonth:12 day:31];
+        } else if (self.pickerMode == BRDatePickerModeTime || self.pickerMode == BRDatePickerModeCountDownTimer || self.pickerMode == BRDatePickerModeHM) {
+            maxDate = [NSDate br_setHour:23 minute:59];
+        } else if (self.pickerMode == BRDatePickerModeHMS) {
+            maxDate = [NSDate br_setHour:23 minute:59 second:59];
+        } else if (self.pickerMode == BRDatePickerModeMS) {
+            maxDate = [NSDate br_setMinute:59 second:59];
+        } else {
+            maxDate = [NSDate distantFuture]; // 遥远的未来的一个时间点
+        }
+    }
+    return maxDate;
+}
+
+#pragma mark - 默认选中的日期
+- (NSDate *)handlerSelectDate:(NSDate *)selectDate dateFormat:(NSString *)dateFormat {
+    // selectDate 优先级高于 selectValue(推荐使用 selectDate 设置默认选中的日期)
+    if (!selectDate) {
+        if (self.selectValue && self.selectValue.length > 0) {
+            if (self.pickerMode == BRDatePickerModeYMDH && self.isShowAMAndPM) {
+                NSString *firstString = [[self.selectValue componentsSeparatedByString:@" "] firstObject];
+                NSString *lastString = [[self.selectValue componentsSeparatedByString:@" "] lastObject];
+                if ([lastString isEqualToString:[self getAMText]]) {
+                    self.selectValue = [NSString stringWithFormat:@"%@ 00", firstString];
+                }
+                if ([lastString isEqualToString:[self getPMText]]) {
+                    self.selectValue = [NSString stringWithFormat:@"%@ 12", firstString];
+                }
+            }
+            
+            NSDate *date = nil;
+            if ([self.selectValue isEqualToString:self.lastRowContent]) {
+                date = self.addToNow ? [NSDate date] : nil;
+            } else if ([self.selectValue isEqualToString:self.firstRowContent]) {
+                date = nil;
+            } else {
+                date = [self br_dateFromString:self.selectValue dateFormat:dateFormat];
+                if (!date) {
+                    BRErrorLog(@"参数异常!字符串 selectValue 的正确格式是:%@", dateFormat);
+                    NSAssert(date, @"参数异常!请检查字符串 selectValue 的格式");
+                    date = [NSDate date]; // 默认值参数格式错误时,重置/忽略默认值,防止在 Release 环境下崩溃!
+                }
+                if (self.pickerMode == BRDatePickerModeMDHM) {
+                    selectDate = [NSDate br_setMonth:date.br_month day:date.br_day hour:date.br_hour minute:date.br_minute];
+                } else if (self.pickerMode == BRDatePickerModeMD) {
+                    selectDate = [NSDate br_setMonth:date.br_month day:date.br_day];
+                } else if (self.pickerMode == BRDatePickerModeTime || self.pickerMode == BRDatePickerModeCountDownTimer || self.pickerMode == BRDatePickerModeHM) {
+                    selectDate = [NSDate br_setHour:date.br_hour minute:date.br_minute];
+                } else if (self.pickerMode == BRDatePickerModeHMS) {
+                    selectDate = [NSDate br_setHour:date.br_hour minute:date.br_minute second:date.br_second];
+                } else if (self.pickerMode == BRDatePickerModeMS) {
+                    selectDate = [NSDate br_setMinute:date.br_minute second:date.br_second];
+                } else {
+                    selectDate = date;
+                }
+            }
+        } else {
+            // 不设置默认日期
+            if (self.pickerMode == BRDatePickerModeTime ||
+                self.pickerMode == BRDatePickerModeCountDownTimer ||
+                self.pickerMode == BRDatePickerModeHM ||
+                self.pickerMode == BRDatePickerModeHMS ||
+                self.pickerMode == BRDatePickerModeMS) {
+                // 默认选中最小日期
+                selectDate = self.minDate;
+            } else {
+                if (self.minuteInterval > 1 || self.secondInterval > 1) {
+                    NSDate *date = [NSDate date];
+                    NSInteger minute = self.minDate.br_minute % self.minuteInterval == 0 ? self.minDate.br_minute : 0;
+                    NSInteger second = self.minDate.br_second % self.secondInterval == 0 ? self.minDate.br_second : 0;
+                    selectDate = [NSDate br_setYear:date.br_year month:date.br_month day:date.br_day hour:date.br_hour minute:minute second:second];
+                } else {
+                    // 默认选中今天的日期
+                    selectDate = [NSDate date];
+                }
+            }
+        }
+    }
+    
+    // 判断日期是否超过边界限制
+    BOOL selectLessThanMin = [self br_compareDate:selectDate targetDate:self.minDate dateFormat:dateFormat] == NSOrderedAscending;
+    BOOL selectMoreThanMax = [self br_compareDate:selectDate targetDate:self.maxDate dateFormat:dateFormat] == NSOrderedDescending;
+    if (selectLessThanMin) {
+        BRErrorLog(@"默认选择的日期不能小于最小日期!");
+        selectDate = self.minDate;
+    }
+    if (selectMoreThanMax) {
+        BRErrorLog(@"默认选择的日期不能大于最大日期!");
+        selectDate = self.maxDate;
+    }
+    
+    return selectDate;
+}
+
+#pragma mark - NSDate 转 NSString
+- (NSString *)br_stringFromDate:(NSDate *)date dateFormat:(NSString *)dateFormat {
+    return [NSDate br_stringFromDate:date dateFormat:dateFormat timeZone:self.timeZone language:self.pickerStyle.language];
+}
+
+#pragma mark - NSString 转 NSDate
+- (NSDate *)br_dateFromString:(NSString *)dateString dateFormat:(NSString *)dateFormat {
+    return [NSDate br_dateFromString:dateString dateFormat:dateFormat timeZone:self.timeZone language:self.pickerStyle.language];
+}
+
+#pragma mark - 比较两个日期大小(可以指定比较级数,即按指定格式进行比较)
+- (NSComparisonResult)br_compareDate:(NSDate *)date targetDate:(NSDate *)targetDate dateFormat:(NSString *)dateFormat {
+    NSString *dateString1 = [self br_stringFromDate:date dateFormat:dateFormat];
+    NSString *dateString2 = [self br_stringFromDate:targetDate dateFormat:dateFormat];
+    NSDate *date1 = [self br_dateFromString:dateString1 dateFormat:dateFormat];
+    NSDate *date2 = [self br_dateFromString:dateString2 dateFormat:dateFormat];
+    if ([date1 compare:date2] == NSOrderedDescending) {
+        return 1; // 大于
+    } else if ([date1 compare:date2] == NSOrderedAscending) {
+        return -1; // 小于
+    } else {
+        return 0; // 等于
+    }
+}
+
+#pragma mark - 获取 yearArr 数组
+- (NSArray *)getYearArr {
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = self.minDate.br_year; i <= self.maxDate.br_year; i++) {
+        [tempArr addObject:[self getYearNumber:i]];
+    }
+    if (self.isDescending) {
+        NSArray *reversedArr = [[tempArr reverseObjectEnumerator] allObjects];
+        tempArr = [reversedArr mutableCopy];
+    }
+    // 判断是否需要添加【自定义字符串】
+    if (self.lastRowContent || self.firstRowContent) {
+        switch (self.pickerMode) {
+            case BRDatePickerModeYMDHMS:
+            case BRDatePickerModeYMDHM:
+            case BRDatePickerModeYMDH:
+            case BRDatePickerModeYMD:
+            case BRDatePickerModeYM:
+            case BRDatePickerModeY:
+            {
+                if (self.lastRowContent) {
+                    [tempArr addObject:self.lastRowContent];
+                }
+                if (self.firstRowContent) {
+                    [tempArr insertObject:self.firstRowContent atIndex:0];
+                }
+            }
+                break;
+                
+            default:
+                break;
+        }
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 monthArr 数组
+- (NSArray *)getMonthArr:(NSInteger)year {
+    NSInteger startMonth = 1;
+    NSInteger endMonth = 12;
+    if (year == self.minDate.br_year) {
+        startMonth = self.minDate.br_month;
+    }
+    if (year == self.maxDate.br_year) {
+        endMonth = self.maxDate.br_month;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startMonth; i <= endMonth; i++) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        NSArray *reversedArr = [[tempArr reverseObjectEnumerator] allObjects];
+        tempArr = [reversedArr mutableCopy];
+    }
+    // 判断是否需要添加【自定义字符串】
+    if (self.lastRowContent || self.firstRowContent) {
+        switch (self.pickerMode) {
+            case BRDatePickerModeMDHM:
+            case BRDatePickerModeMD:
+            {
+                if (self.lastRowContent) {
+                    [tempArr addObject:self.lastRowContent];
+                }
+                if (self.firstRowContent) {
+                    [tempArr insertObject:self.firstRowContent atIndex:0];
+                }
+            }
+                break;
+                
+            default:
+                break;
+        }
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 dayArr 数组
+- (NSArray *)getDayArr:(NSInteger)year month:(NSInteger)month {
+    NSInteger startDay = 1;
+    NSInteger endDay = [NSDate br_getDaysInYear:year month:month];
+    if (year == self.minDate.br_year && month == self.minDate.br_month) {
+        startDay = self.minDate.br_day;
+    }
+    if (year == self.maxDate.br_year && month == self.maxDate.br_month) {
+        endDay = self.maxDate.br_day;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startDay; i <= endDay; i++) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        return [[tempArr reverseObjectEnumerator] allObjects];
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 hourArr 数组
+- (NSArray *)getHourArr:(NSInteger)year month:(NSInteger)month day:(NSInteger)day {
+    if (self.pickerMode == BRDatePickerModeYMDH && self.isShowAMAndPM) {
+        return @[[self getAMText], [self getPMText]];
+    }
+    
+    NSInteger startHour = 0;
+    NSInteger endHour = 23;
+    if (year == self.minDate.br_year && month == self.minDate.br_month && day == self.minDate.br_day) {
+        startHour = self.minDate.br_hour;
+    }
+    if (year == self.maxDate.br_year && month == self.maxDate.br_month && day == self.maxDate.br_day) {
+        endHour = self.maxDate.br_hour;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startHour; i <= endHour; i++) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        NSArray *reversedArr = [[tempArr reverseObjectEnumerator] allObjects];
+        tempArr = [reversedArr mutableCopy];
+    }
+    // 判断是否需要添加【自定义字符串】
+    if (self.lastRowContent || self.firstRowContent) {
+        switch (self.pickerMode) {
+            case BRDatePickerModeHMS:
+            case BRDatePickerModeHM:
+            {
+                if (self.lastRowContent) {
+                    [tempArr addObject:self.lastRowContent];
+                }
+                if (self.firstRowContent) {
+                    [tempArr insertObject:self.firstRowContent atIndex:0];
+                }
+            }
+                break;
+                
+            default:
+                break;
+        }
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 minuteArr 数组
+- (NSArray *)getMinuteArr:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour {
+    NSInteger startMinute = 0;
+    NSInteger endMinute = 59;
+    if (year == self.minDate.br_year && month == self.minDate.br_month && day == self.minDate.br_day && hour == self.minDate.br_hour) {
+        startMinute = self.minDate.br_minute;
+    }
+    if (year == self.maxDate.br_year && month == self.maxDate.br_month && day == self.maxDate.br_day && hour == self.maxDate.br_hour) {
+        endMinute = self.maxDate.br_minute;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startMinute; i <= endMinute; i += self.minuteInterval) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        NSArray *reversedArr = [[tempArr reverseObjectEnumerator] allObjects];
+        tempArr = [reversedArr mutableCopy];
+    }
+    // 判断是否需要添加【自定义字符串】
+    if (self.lastRowContent || self.firstRowContent) {
+        switch (self.pickerMode) {
+            case BRDatePickerModeMS:
+            {
+                if (self.lastRowContent) {
+                    [tempArr addObject:self.lastRowContent];
+                }
+                if (self.firstRowContent) {
+                    [tempArr insertObject:self.firstRowContent atIndex:0];
+                }
+            }
+                break;
+                
+            default:
+                break;
+        }
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 secondArr 数组
+- (NSArray *)getSecondArr:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute {
+    NSInteger startSecond = 0;
+    NSInteger endSecond = 59;
+    if (year == self.minDate.br_year && month == self.minDate.br_month && day == self.minDate.br_day && hour == self.minDate.br_hour && minute == self.minDate.br_minute) {
+        startSecond = self.minDate.br_second;
+    }
+    if (year == self.maxDate.br_year && month == self.maxDate.br_month && day == self.maxDate.br_day && hour == self.maxDate.br_hour && minute == self.maxDate.br_minute) {
+        endSecond = self.maxDate.br_second;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startSecond; i <= endSecond; i += self.secondInterval) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        return [[tempArr reverseObjectEnumerator] allObjects];
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 monthWeekArr 数组
+- (NSArray *)getMonthWeekArr:(NSInteger)year month:(NSInteger)month {
+    NSInteger startWeek = 1;
+    NSInteger endWeek = [NSDate br_getWeeksOfMonthInYear:year month:month];
+    if (year == self.minDate.br_year && month == self.minDate.br_month) {
+        startWeek = self.minDate.br_monthWeek;
+    }
+    if (year == self.maxDate.br_year && month == self.maxDate.br_month) {
+        endWeek = self.maxDate.br_monthWeek;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startWeek; i <= endWeek; i++) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        return [[tempArr reverseObjectEnumerator] allObjects];
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 yearWeekArr 数组
+- (NSArray *)getYearWeekArr:(NSInteger)year {
+    NSInteger startWeek = 1;
+    NSInteger endWeek = [NSDate br_getWeeksOfYearInYear:year];
+    if (year == self.minDate.br_year) {
+        startWeek = self.minDate.br_yearWeek;
+    }
+    if (year == self.maxDate.br_year) {
+        endWeek = self.maxDate.br_yearWeek;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startWeek; i <= endWeek; i++) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        return [[tempArr reverseObjectEnumerator] allObjects];
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 获取 quarterArr 数组
+- (NSArray *)getQuarterArr:(NSInteger)year {
+    NSInteger startQuarter = 1;
+    NSInteger endQuarter = [NSDate br_getQuartersInYear:year];
+    if (year == self.minDate.br_year) {
+        startQuarter = self.minDate.br_quarter;
+    }
+    if (year == self.maxDate.br_year) {
+        endQuarter = self.maxDate.br_quarter;
+    }
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = startQuarter; i <= endQuarter; i++) {
+        [tempArr addObject:[self getMDHMSNumber:i]];
+    }
+    if (self.isDescending) {
+        return [[tempArr reverseObjectEnumerator] allObjects];
+    }
+    
+    return [tempArr copy];
+}
+
+#pragma mark - 添加 pickerView
+- (void)setupPickerView:(UIView *)pickerView toView:(UIView *)view {
+    if (view) {
+        // 立即刷新容器视图 view 的布局(防止 view 使用自动布局时,选择器视图无法正常显示)
+        [view setNeedsLayout];
+        [view layoutIfNeeded];
+        
+        self.frame = view.bounds;
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        CGFloat pickerFooterViewHeight = self.pickerFooterView ? self.pickerFooterView.bounds.size.height : 0;
+        pickerView.frame = CGRectMake(0, pickerHeaderViewHeight, view.bounds.size.width, view.bounds.size.height - pickerHeaderViewHeight - pickerFooterViewHeight);
+        [self addSubview:pickerView];
+    } else {
+        // iOS16:重新设置 pickerView 高度(解决懒加载设置frame不生效问题)
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        pickerView.frame = CGRectMake(0, self.pickerStyle.titleBarHeight + pickerHeaderViewHeight, self.keyView.bounds.size.width, self.pickerStyle.pickerHeight);
+
+        [self.alertView addSubview:pickerView];
+    }
+}
+
+#pragma mark - 获取日期单位
+- (NSArray *)setupPickerUnitLabel:(UIPickerView *)pickerView unitArr:(NSArray *)unitArr {
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = 0; i < pickerView.numberOfComponents; i++) {
+        // label宽度
+        CGFloat labelWidth = pickerView.bounds.size.width / pickerView.numberOfComponents;
+        // 根据占位文本长度去计算宽度
+        NSString *tempText = @"00";
+        if (i == 0) {
+            switch (self.pickerMode) {
+                case BRDatePickerModeYMDHMS:
+                case BRDatePickerModeYMDHM:
+                case BRDatePickerModeYMDH:
+                case BRDatePickerModeYMD:
+                case BRDatePickerModeYM:
+                case BRDatePickerModeY:
+                {
+                    tempText = @"0123";
+                }
+                    break;
+                    
+                default:
+                    break;
+            }
+        }
+        // 文本宽度
+        CGFloat labelTextWidth = [tempText boundingRectWithSize:CGSizeMake(MAXFLOAT, self.pickerStyle.rowHeight)
+                                                        options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
+                                                     attributes:@{NSFontAttributeName: self.pickerStyle.pickerTextFont}
+                                                        context:nil].size.width;
+        // 单位label
+        UILabel *unitLabel = [[UILabel alloc]init];
+        unitLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
+        unitLabel.backgroundColor = [UIColor clearColor];
+        if (self.pickerMode != BRDatePickerModeYMDHMS) {
+            unitLabel.textAlignment = NSTextAlignmentCenter;
+        }
+        unitLabel.font = self.pickerStyle.dateUnitTextFont;
+        unitLabel.textColor = self.pickerStyle.dateUnitTextColor;
+        // 字体自适应属性
+        unitLabel.adjustsFontSizeToFitWidth = YES;
+        // 自适应最小字体缩放比例
+        unitLabel.minimumScaleFactor = 0.5f;
+        unitLabel.text = (unitArr.count > 0 && i < unitArr.count) ? unitArr[i] : nil;
+        
+        CGFloat originX = i * labelWidth + labelWidth / 2.0 + labelTextWidth / 2.0 + self.pickerStyle.dateUnitOffsetX;
+        CGFloat originY = (pickerView.frame.size.height - self.pickerStyle.rowHeight) / 2 + self.pickerStyle.dateUnitOffsetY;
+        unitLabel.frame = CGRectMake(originX, originY, MAX(self.pickerStyle.rowHeight, labelTextWidth), self.pickerStyle.rowHeight);
+        
+        [tempArr addObject:unitLabel];
+        
+        [pickerView addSubview:unitLabel];
+    }
+    
+    return [tempArr copy];
+}
+
+- (NSString *)getYearNumber:(NSInteger)year {
+    NSString *yearString = [NSString stringWithFormat:@"%@", @(year)];
+    if (self.isNumberFullName) {
+        yearString = [NSString stringWithFormat:@"%04d", [yearString intValue]];
+    }
+    return yearString;
+}
+
+- (NSString *)getMDHMSNumber:(NSInteger)number {
+    NSString *string = [NSString stringWithFormat:@"%@", @(number)];
+    if (self.isNumberFullName) {
+        string = [NSString stringWithFormat:@"%02d", [string intValue]];
+    }
+    return string;
+}
+
+- (NSString *)getYearText:(NSArray *)yearArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, yearArr.count - 1);
+    }
+    NSString *yearString = [yearArr objectAtIndex:index];
+    if ((self.lastRowContent && [yearString isEqualToString:self.lastRowContent]) || (self.firstRowContent && [yearString isEqualToString:self.firstRowContent])) {
+        return yearString;
+    }
+    NSString *yearUnit = self.showUnitType == BRShowUnitTypeAll ? [self getYearUnit] : @"";
+    return [NSString stringWithFormat:@"%@%@", yearString, yearUnit];
+}
+
+- (NSString *)getMonthText:(NSArray *)monthArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, monthArr.count - 1);
+    }
+    NSString *monthString = [monthArr objectAtIndex:index];
+    // 首行/末行是自定义字符串,直接返回
+    if ((self.firstRowContent && [monthString isEqualToString:self.firstRowContent]) || (self.lastRowContent && [monthString isEqualToString:self.lastRowContent])) {
+        return monthString;
+    }
+    
+    // 自定义月份数据源
+    if (self.monthNames && self.monthNames.count > 0) {
+        NSInteger index = [monthString integerValue] - 1;
+        monthString = (index >= 0 && index < self.monthNames.count) ? self.monthNames[index] : @"";
+    } else {
+        if (![self.pickerStyle.language hasPrefix:@"zh"] && (self.pickerMode == BRDatePickerModeYMD || self.pickerMode == BRDatePickerModeYM || self.pickerMode == BRDatePickerModeYMW)) {
+            // 非中文环境:月份使用系统的月份名称
+            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+            dateFormatter.locale = [[NSLocale alloc]initWithLocaleIdentifier:self.pickerStyle.language];
+            // monthSymbols: @[@"January", @"February", @"March", @"April", @"May", @"June", @"July", @"August", @"September", @"October", @"November", @"December"];
+            // shortMonthSymbols: @[@"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec"];
+            NSArray *monthNames = self.isShortMonthName ? dateFormatter.shortMonthSymbols : dateFormatter.monthSymbols;
+            NSInteger index = [monthString integerValue] - 1;
+            monthString = (index >= 0 && index < monthNames.count) ? monthNames[index] : @"";
+        } else {
+            // 中文环境:月份显示数字
+            NSString *monthUnit = self.showUnitType == BRShowUnitTypeAll ? [self getMonthUnit] : @"";
+            monthString = [NSString stringWithFormat:@"%@%@", monthString, monthUnit];
+        }
+    }
+    
+    return monthString;
+}
+
+- (NSString *)getDayText:(NSArray *)dayArr row:(NSInteger)row mSelectDate:(NSDate *)mSelectDate {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, dayArr.count - 1);
+    }
+    NSString *dayString = [dayArr objectAtIndex:index];
+    if (self.isShowToday && mSelectDate.br_year == [NSDate date].br_year && mSelectDate.br_month == [NSDate date].br_month && [dayString integerValue] == [NSDate date].br_day) {
+        return [NSBundle br_localizedStringForKey:@"今天" language:self.pickerStyle.language];
+    }
+    NSString *dayUnit = self.showUnitType == BRShowUnitTypeAll ? [self getDayUnit] : @"";
+    dayString = [NSString stringWithFormat:@"%@%@", dayString, dayUnit];
+    if (self.isShowWeek) {
+        NSDate *date = [NSDate br_setYear:mSelectDate.br_year month:mSelectDate.br_month day:[dayString integerValue]];
+        NSString *weekdayString = [NSBundle br_localizedStringForKey:[date br_weekdayString] language:self.pickerStyle.language];
+        dayString = [NSString stringWithFormat:@"%@%@", dayString, weekdayString];
+    }
+    return dayString;
+}
+
+- (NSString *)getHourText:(NSArray *)hourArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, hourArr.count - 1);
+    }
+    NSString *hourString = [hourArr objectAtIndex:index];
+    if ((self.lastRowContent && [hourString isEqualToString:self.lastRowContent]) || (self.firstRowContent && [hourString isEqualToString:self.firstRowContent])) {
+        return hourString;
+    }
+    NSString *hourUnit = self.showUnitType == BRShowUnitTypeAll ? [self getHourUnit] : @"";
+    return [NSString stringWithFormat:@"%@%@", hourString, hourUnit];
+}
+
+- (NSString *)getMinuteText:(NSArray *)minuteArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, minuteArr.count - 1);
+    }
+    NSString *minuteString = [minuteArr objectAtIndex:index];
+    NSString *minuteUnit = self.showUnitType == BRShowUnitTypeAll ? [self getMinuteUnit] : @"";
+    return [NSString stringWithFormat:@"%@%@", minuteString, minuteUnit];
+}
+
+- (NSString *)getSecondText:(NSArray *)secondArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, secondArr.count - 1);
+    }
+    NSString *secondString = [secondArr objectAtIndex:index];
+    NSString *secondUnit = self.showUnitType == BRShowUnitTypeAll ? [self getSecondUnit] : @"";
+    return [NSString stringWithFormat:@"%@%@", secondString, secondUnit];
+}
+
+- (NSString *)getWeekText:(NSArray *)weekArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, weekArr.count - 1);
+    }
+    NSString *weekString = [weekArr objectAtIndex:index];
+    if ((self.lastRowContent && [weekString isEqualToString:self.lastRowContent]) || (self.firstRowContent && [weekString isEqualToString:self.firstRowContent])) {
+        return weekString;
+    }
+    NSString *weekUnit = self.showUnitType == BRShowUnitTypeAll ? [self getWeekUnit] : @"";
+    return [NSString stringWithFormat:@"%@%@", weekString, weekUnit];
+}
+
+- (NSString *)getQuarterText:(NSArray *)quarterArr row:(NSInteger)row {
+    NSInteger index = 0;
+    if (row >= 0) {
+        index = MIN(row, quarterArr.count - 1);
+    }
+    NSString *quarterString = [quarterArr objectAtIndex:index];
+    if ((self.lastRowContent && [quarterString isEqualToString:self.lastRowContent]) || (self.firstRowContent && [quarterString isEqualToString:self.firstRowContent])) {
+        return quarterString;
+    }
+    NSString *quarterUnit = self.showUnitType == BRShowUnitTypeAll ? [self getQuarterUnit] : @"";
+    return [NSString stringWithFormat:@"%@%@", quarterString, quarterUnit];
+}
+
+- (NSString *)getAMText {
+    return [NSBundle br_localizedStringForKey:@"上午" language:self.pickerStyle.language];
+}
+
+- (NSString *)getPMText {
+    return [NSBundle br_localizedStringForKey:@"下午" language:self.pickerStyle.language];
+}
+
+- (NSString *)getYearUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"year"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"年" language:self.pickerStyle.language];
+}
+
+- (NSString *)getMonthUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"month"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"月" language:self.pickerStyle.language];
+}
+
+- (NSString *)getDayUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"day"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"日" language:self.pickerStyle.language];
+}
+
+- (NSString *)getHourUnit {
+    if (self.pickerMode == BRDatePickerModeYMDH && self.isShowAMAndPM) {
+        return @"";
+    }
+    if (self.customUnit) {
+        return self.customUnit[@"hour"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"时" language:self.pickerStyle.language];
+}
+
+- (NSString *)getMinuteUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"minute"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"分" language:self.pickerStyle.language];
+}
+
+- (NSString *)getSecondUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"second"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"秒" language:self.pickerStyle.language];
+}
+
+- (NSString *)getWeekUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"week"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"周" language:self.pickerStyle.language];
+}
+
+- (NSString *)getQuarterUnit {
+    if (self.customUnit) {
+        return self.customUnit[@"quarter"] ? : @"";
+    }
+    if (![self.pickerStyle.language hasPrefix:@"zh"]) {
+        return @"";
+    }
+    return [NSBundle br_localizedStringForKey:@"季度" language:self.pickerStyle.language];
+}
+
+- (NSInteger)getIndexWithArray:(NSArray *)array object:(NSString *)obj {
+    if (!array || array.count == 0 || !obj) {
+        return 0;
+    }
+    if ([array containsObject:obj]) {
+        return [array indexOfObject:obj];
+    }
+    return 0;
+}
+
+@end

+ 274 - 0
Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView.h

@@ -0,0 +1,274 @@
+//
+//  BRDatePickerView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRBaseView.h"
+#import "NSDate+BRPickerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// 日期选择器格式
+typedef NS_ENUM(NSInteger, BRDatePickerMode) {
+    // ----- 以下4种是系统样式(兼容国际化日期格式) -----
+    /** 【yyyy-MM-dd】UIDatePickerModeDate(美式日期:MM-dd-yyyy;英式日期:dd-MM-yyyy)*/
+    BRDatePickerModeDate,
+    /** 【yyyy-MM-dd HH:mm】 UIDatePickerModeDateAndTime */
+    BRDatePickerModeDateAndTime,
+    /** 【HH:mm】UIDatePickerModeTime */
+    BRDatePickerModeTime,
+    /** 【HH:mm】UIDatePickerModeCountDownTimer */
+    BRDatePickerModeCountDownTimer,
+    
+    // ----- 以下14种是自定义样式 -----
+    /** 【yyyy-MM-dd HH:mm:ss】年月日时分秒 */
+    BRDatePickerModeYMDHMS,
+    /** 【yyyy-MM-dd HH:mm】年月日时分 */
+    BRDatePickerModeYMDHM,
+    /** 【yyyy-MM-dd HH】年月日时 */
+    BRDatePickerModeYMDH,
+    /** 【MM-dd HH:mm】月日时分 */
+    BRDatePickerModeMDHM,
+    /** 【yyyy-MM-dd】年月日(兼容国际化日期:dd-MM-yyyy)*/
+    BRDatePickerModeYMD,
+    /** 【yyyy-MM】年月(兼容国际化日期:MM-yyyy)*/
+    BRDatePickerModeYM,
+    /** 【yyyy】年 */
+    BRDatePickerModeY,
+    /** 【MM-dd】月日 */
+    BRDatePickerModeMD,
+    /** 【HH:mm:ss】时分秒 */
+    BRDatePickerModeHMS,
+    /** 【HH:mm】时分 */
+    BRDatePickerModeHM,
+    /** 【mm:ss】分秒 */
+    BRDatePickerModeMS,
+    
+    /** 【yyyy-qq】年季度 */
+    BRDatePickerModeYQ,
+    /** 【yyyy-MM-ww】年月周 */
+    BRDatePickerModeYMW,
+    /** 【yyyy-ww】年周 */
+    BRDatePickerModeYW
+};
+
+/// 日期单位显示的位置
+typedef NS_ENUM(NSInteger, BRShowUnitType) {
+    /** 日期单位显示全部行(默认)*/
+    BRShowUnitTypeAll,
+    /** 日期单位仅显示中间行 */
+    BRShowUnitTypeOnlyCenter,
+    /** 日期单位不显示(隐藏日期单位)*/
+    BRShowUnitTypeNone
+};
+
+typedef void (^BRDateResultBlock)(NSDate * _Nullable selectDate, NSString * _Nullable selectValue);
+
+typedef void (^BRDateResultRangeBlock)(NSDate * _Nullable selectStartDate, NSDate * _Nullable selectEndDate, NSString * _Nullable selectValue);
+
+@interface BRDatePickerView : BRBaseView
+
+/**
+ //////////////////////////////////////////////////////////////////////////
+ ///
+ ///   【用法一】
+ ///    特点:灵活,扩展性强(推荐使用!)
+ ///
+ ////////////////////////////////////////////////////////////////////////*/
+
+/** 日期选择器显示类型 */
+@property (nonatomic, assign) BRDatePickerMode pickerMode;
+
+/** 设置选中的日期(推荐使用 selectDate) */
+@property (nullable, nonatomic, strong) NSDate *selectDate;
+@property (nullable, nonatomic, copy) NSString *selectValue;
+
+/** 最小日期(可使用 NSDate+BRPickerView 分类中对应的方法进行创建)*/
+@property (nullable, nonatomic, strong) NSDate *minDate;
+/** 最大日期(可使用 NSDate+BRPickerView 分类中对应的方法进行创建)*/
+@property (nullable, nonatomic, strong) NSDate *maxDate;
+
+/** 选择结果的回调 */
+@property (nullable, nonatomic, copy) BRDateResultBlock resultBlock;
+/** 选择结果范围的回调:for `BRDatePickerModeYQ`、`BRDatePickerModeYMW`、`BRDatePickerModeYW`, ignored otherwise. */
+@property (nullable, nonatomic, copy) BRDateResultRangeBlock resultRangeBlock;
+
+/** 滚动选择时触发的回调 */
+@property (nullable, nonatomic, copy) BRDateResultBlock changeBlock;
+/** 滚动选择范围时触发的回调:for `BRDatePickerModeYQ`、`BRDatePickerModeYMW`、`BRDatePickerModeYW`, ignored otherwise. */
+@property (nullable, nonatomic, copy) BRDateResultRangeBlock changeRangeBlock;
+
+/** 日期单位显示类型 */
+@property (nonatomic, assign) BRShowUnitType showUnitType;
+
+/** 是否显示【星期】,默认为 NO */
+@property (nonatomic, assign, getter=isShowWeek) BOOL showWeek;
+
+/** 是否显示【今天】,默认为 NO */
+@property (nonatomic, assign, getter=isShowToday) BOOL showToday;
+
+/** 是否添加【至今】,默认为 NO */
+@property (nonatomic, assign, getter=isAddToNow) BOOL addToNow;
+
+/** 首行添加【自定义字符串】,配合 selectValue 可设置默认选中 */
+@property (nullable, nonatomic, copy) NSString *firstRowContent;
+
+/** 末行添加【自定义字符串】,配合 selectValue 可设置默认选中 */
+@property (nullable, nonatomic, copy) NSString *lastRowContent;
+
+/** 最后一行,添加【自定义字符串】 */
+@property (nullable, nonatomic, copy) NSString *addCustomString DEPRECATED_MSG_ATTRIBUTE("Use 'lastRowContent' instead");
+
+/** 滚轮上日期数据排序是否降序,默认为 NO(升序)*/
+@property (nonatomic, assign, getter=isDescending) BOOL descending;
+
+/** 选择器上数字是否带有前导零,默认为 NO(如:无前导零:2020-1-1;有前导零:2020-01-01)*/
+@property (nonatomic, assign, getter=isNumberFullName) BOOL numberFullName;
+
+/** 设置分的时间间隔,默认为1(范围:1 ~ 30)*/
+@property (nonatomic, assign) NSInteger minuteInterval;
+
+/** 设置秒的时间间隔,默认为1(范围:1 ~ 30)*/
+@property (nonatomic, assign) NSInteger secondInterval;
+
+/** 设置倒计时的时长,默认为0(范围:0 ~ 24*60*60-1,单位为秒) for `BRDatePickerModeCountDownTimer`, ignored otherwise. */
+@property (nonatomic, assign) NSTimeInterval countDownDuration;
+
+/**
+ *  自定义月份数据源
+ *  如:@[@"1月", @"2月",..., @"12月"]、 @[@"一月", @"二月",..., @"十二月"]、 @[@"Jan", @"Feb",..., @"Dec"] 等
+ */
+@property (nonatomic, copy) NSArray <NSString *> *monthNames;
+
+/**
+ *  设置国际化日期(非中文环境下)月份是否显示简称,默认为 NO。for `BRDatePickerModeYMD` and `BRDatePickerModeYM`, ignored otherwise.
+ *  如:January 的简称为:Jan
+ */
+@property (nonatomic, assign, getter=isShortMonthName) BOOL shortMonthName;
+
+/**
+ *  自定义日期单位
+ *  字典格式:@{@"year": @"年", @"month": @"月", @"day": @"日", @"hour": @"时", @"minute": @"分", @"second": @"秒"}
+ */
+@property (nonatomic, copy) NSDictionary *customUnit;
+
+/** 显示上午和下午,默认为 NO. for `BRDatePickerModeYMDH`, ignored otherwise. */
+@property (nonatomic, assign, getter=isShowAMAndPM) BOOL showAMAndPM;
+
+/** 设置时区,默认为当前时区 */
+@property (nullable, nonatomic, copy) NSTimeZone *timeZone;
+
+/** default is [NSCalendar currentCalendar]. setting nil returns to default. for `UIDatePicker` */
+@property (nonatomic, copy) NSCalendar *calendar;
+
+/** 指定不允许选择的日期 */
+@property (nullable, nonatomic, copy) NSArray <NSDate *> *nonSelectableDates;
+
+/** 不允许选择日期的回调 */
+@property (nullable, nonatomic, copy) BRDateResultBlock nonSelectableBlock;
+
+/// 初始化日期选择器
+/// @param pickerMode  日期选择器显示类型
+- (instancetype)initWithPickerMode:(BRDatePickerMode)pickerMode;
+
+/// 弹出选择器视图
+- (void)show;
+
+/// 关闭选择器视图
+- (void)dismiss;
+
+
+
+
+//================================================= 华丽的分割线 =================================================
+
+
+
+
+/**
+ //////////////////////////////////////////////////////////////////////////
+ ///
+ ///   【用法二】:快捷使用,直接选择下面其中的一个方法进行使用
+ ///    特点:快捷,方便
+ ///
+ ////////////////////////////////////////////////////////////////////////*/
+
+/**
+ *  1.显示日期选择器
+ *
+ *  @param mode             日期显示类型
+ *  @param title            选择器标题
+ *  @param selectValue      默认选中的日期(默认选中当前日期)
+ *  @param resultBlock      选择结果的回调
+ *
+ */
++ (void)showDatePickerWithMode:(BRDatePickerMode)mode
+                         title:(nullable NSString *)title
+                   selectValue:(nullable NSString *)selectValue
+                   resultBlock:(nullable BRDateResultBlock)resultBlock;
+
+/**
+ *  2.显示日期选择器
+ *
+ *  @param mode             日期显示类型
+ *  @param title            选择器标题
+ *  @param selectValue      默认选中的日期(默认选中当前日期)
+ *  @param isAutoSelect     是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock      选择结果的回调
+ *
+ */
++ (void)showDatePickerWithMode:(BRDatePickerMode)mode
+                         title:(nullable NSString *)title
+                   selectValue:(nullable NSString *)selectValue
+                  isAutoSelect:(BOOL)isAutoSelect
+                   resultBlock:(nullable BRDateResultBlock)resultBlock;
+
+/**
+ *  3.显示日期选择器
+ *
+ *  @param mode             日期显示类型
+ *  @param title            选择器标题
+ *  @param selectValue      默认选中的日期(默认选中当前日期)
+ *  @param minDate          最小日期(可使用 NSDate+BRPickerView 分类中对应的方法进行创建)
+ *  @param maxDate          最大日期(可使用 NSDate+BRPickerView 分类中对应的方法进行创建)
+ *  @param isAutoSelect     是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock      选择结果的回调
+ *
+ */
++ (void)showDatePickerWithMode:(BRDatePickerMode)mode
+                         title:(nullable NSString *)title
+                   selectValue:(nullable NSString *)selectValue
+                       minDate:(nullable NSDate *)minDate
+                       maxDate:(nullable NSDate *)maxDate
+                  isAutoSelect:(BOOL)isAutoSelect
+                   resultBlock:(nullable BRDateResultBlock)resultBlock;
+
+/**
+ * 3.显示日期选择器
+ *
+ * @param mode             日期显示类型
+ * @param title            选择器标题
+ * @param selectValue      默认选中的日期(默认选中当前日期)
+ * @param minDate          最小日期(可使用 NSDate+BRPickerView 分类中对应的方法进行创建)
+ * @param maxDate          最大日期(可使用 NSDate+BRPickerView 分类中对应的方法进行创建)
+ * @param isAutoSelect     是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ * @param resultBlock      选择结果的回调
+ * @param resultRangeBlock 范围选择结果的回调
+ *
+ */
++ (void)showDatePickerWithMode:(BRDatePickerMode)mode
+                         title:(nullable NSString *)title
+                   selectValue:(nullable NSString *)selectValue
+                       minDate:(nullable NSDate *)minDate
+                       maxDate:(nullable NSDate *)maxDate
+                  isAutoSelect:(BOOL)isAutoSelect
+                   resultBlock:(nullable BRDateResultBlock)resultBlock
+              resultRangeBlock:(nullable BRDateResultRangeBlock)resultRangeBlock;
+
+@end
+
+NS_ASSUME_NONNULL_END

File diff ditekan karena terlalu besar
+ 1965 - 0
Pods/BRPickerView/BRPickerView/DatePickerView/BRDatePickerView.m


+ 126 - 0
Pods/BRPickerView/BRPickerView/DatePickerView/NSDate+BRPickerView.h

@@ -0,0 +1,126 @@
+//
+//  NSDate+BRPickerView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2018/3/15.
+//  Copyright © 2018 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NSDate (BRPickerView)
+/// 获取指定date的详细信息
+@property (readonly) NSInteger br_year;         // 年
+@property (readonly) NSInteger br_month;        // 月
+@property (readonly) NSInteger br_day;          // 日
+@property (readonly) NSInteger br_hour;         // 时
+@property (readonly) NSInteger br_minute;       // 分
+@property (readonly) NSInteger br_second;       // 秒
+@property (readonly) NSInteger br_weekday;      // 星期
+@property (readonly) NSInteger br_monthWeek;    // 月周
+@property (readonly) NSInteger br_yearWeek;     // 年周
+@property (readonly) NSInteger br_quarter;      // 季度
+
+/** 获取中文星期字符串 */
+@property (nullable, nonatomic, readonly, copy) NSString *br_weekdayString;
+
+/** 获取日历单例对象 */
++ (NSCalendar *)br_calendar;
+
+
+/// ---------------- 创建 date ----------------
+/** 通过 NSDateComponents对象 来创建 NSDate对象(可以设置时区) */
++ (nullable NSDate *)br_setDateFromComponents:(NSDateComponents *)components timeZone:(NSTimeZone *)timeZone;
+
+/** yyyy */
++ (nullable NSDate *)br_setYear:(NSInteger)year;
+
+/** yyyy-MM */
++ (nullable NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month;
+
+/** yyyy-MM-dd */
++ (nullable NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day;
+
+/** yyyy-MM-dd HH */
++ (nullable NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour;
+
+/** yyyy-MM-dd HH:mm */
++ (nullable NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute;
+
+/** yyyy-MM-dd HH:mm:ss */
++ (nullable NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second;
+
+/** MM-dd HH:mm */
++ (nullable NSDate *)br_setMonth:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute;
+
+/** MM-dd */
++ (nullable NSDate *)br_setMonth:(NSInteger)month day:(NSInteger)day;
+
+/** HH:mm:ss */
++ (nullable NSDate *)br_setHour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second;
+
+/** HH:mm */
++ (nullable NSDate *)br_setHour:(NSInteger)hour minute:(NSInteger)minute;
+
+/** mm:ss */
++ (nullable NSDate *)br_setMinute:(NSInteger)minute second:(NSInteger)second;
+
+/** yyyy-MM-ww */
++ (nullable NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month weekOfMonth:(NSInteger)weekOfMont;
+
+/** yyyy-ww */
++ (nullable NSDate *)br_setYear:(NSInteger)year weekOfYear:(NSInteger)weekOfYear;
+
+/** yyyy-qq */
++ (nullable NSDate *)br_setYear:(NSInteger)year quarter:(NSInteger)quarter;
+
+
+/** 获取某个月的天数(通过年月求每月天数)*/
++ (NSUInteger)br_getDaysInYear:(NSInteger)year month:(NSInteger)month;
+
+/** 获取某个月的周数(通过年月求该月周数)*/
++ (NSUInteger)br_getWeeksOfMonthInYear:(NSInteger)year month:(NSInteger)month;
+
+/** 获取某一年的周数(通过年求该年周数)*/
++ (NSUInteger)br_getWeeksOfYearInYear:(NSInteger)year;
+
+/** 获取某一年的季度数(通过年求该年季度数)*/
++ (NSUInteger)br_getQuartersInYear:(NSInteger)year;
+
+/**  获取 日期加上/减去某天数后的新日期 */
+- (nullable NSDate *)br_getNewDateToDays:(NSTimeInterval)days;
+
+/**  获取 日期加上/减去某个月数后的新日期 */
+- (nullable NSDate *)br_getNewDateToMonths:(NSTimeInterval)months;
+
+/** NSDate 转 NSString */
++ (nullable NSString *)br_stringFromDate:(NSDate *)date dateFormat:(NSString *)dateFormat;
+/** NSDate 转 NSString */
++ (nullable NSString *)br_stringFromDate:(NSDate *)date
+                     dateFormat:(NSString *)dateFormat
+                       timeZone:(nullable NSTimeZone *)timeZone
+                       language:(nullable NSString *)language;
+
+
+/** NSString 转 NSDate */
++ (nullable NSDate *)br_dateFromString:(NSString *)dateString dateFormat:(NSString *)dateFormat;
+/** NSString 转 NSDate */
++ (nullable NSDate *)br_dateFromString:(NSString *)dateString
+                   dateFormat:(NSString *)dateFormat
+                     timeZone:(nullable NSTimeZone *)timeZone
+                     language:(nullable NSString *)language;
+
+
+/** NSDate 转 NSString(已弃用) */
++ (nullable NSString *)br_getDateString:(NSDate *)date format:(NSString *)format DEPRECATED_MSG_ATTRIBUTE("Use 'br_stringFromDate:dateFormat:' instead");
+
+/** NSString 转 NSDate(已弃用) */
++ (nullable NSDate *)br_getDate:(NSString *)dateString format:(NSString *)format DEPRECATED_MSG_ATTRIBUTE("Use 'br_dateFromString:dateFormat:' instead");
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 400 - 0
Pods/BRPickerView/BRPickerView/DatePickerView/NSDate+BRPickerView.m

@@ -0,0 +1,400 @@
+//
+//  NSDate+BRPickerView.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2018/3/15.
+//  Copyright © 2018 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "NSDate+BRPickerView.h"
+#import "BRPickerViewMacro.h"
+
+BRSYNTH_DUMMY_CLASS(NSDate_BRPickerView)
+
+static const NSCalendarUnit unitFlags = (NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekOfYear | NSCalendarUnitWeekOfMonth |  NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitWeekday | NSCalendarUnitWeekdayOrdinal | NSCalendarUnitQuarter);
+
+@implementation NSDate (BRPickerView)
+
+#pragma mark - 获取日历单例对象
++ (NSCalendar *)br_calendar {
+    static NSCalendar *sharedCalendar = nil;
+    if (!sharedCalendar) {
+        // 创建日历对象,指定日历的算法(公历/阳历)
+        sharedCalendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
+        // NSCalendar 设置时区
+        //sharedCalendar.timeZone = [NSTimeZone timeZoneWithName:@"America/Chicago"];
+    }
+    return sharedCalendar;
+}
+
+#pragma mark - NSDate 转 NSDateComponents
++ (NSDateComponents *)br_componentsFromDate:(NSDate *)date {
+    // 通过日历类 NSCalendar 进行转换
+    NSCalendar *calendar = [self br_calendar];
+    // NSDateComponents 可以获得日期的详细信息,即日期的组成
+    return [calendar components:unitFlags fromDate:date];
+}
+
+#pragma mark - NSDateComponents 转 NSDate
++ (NSDate *)br_dateFromComponents:(NSDateComponents *)components {
+    // 通过日历类 NSCalendar 进行转换
+    NSCalendar *calendar = [self br_calendar];
+    return [calendar dateFromComponents:components];
+}
+
+#pragma mark - 获取指定日期的年份
+- (NSInteger)br_year {
+    return [NSDate br_componentsFromDate:self].year;
+}
+
+#pragma mark - 获取指定日期的月份
+- (NSInteger)br_month {
+    return [NSDate br_componentsFromDate:self].month;
+}
+
+#pragma mark - 获取指定日期的天
+- (NSInteger)br_day {
+    return [NSDate br_componentsFromDate:self].day;
+}
+
+#pragma mark - 获取指定日期的小时
+- (NSInteger)br_hour {
+    return [NSDate br_componentsFromDate:self].hour;
+}
+
+#pragma mark - 获取指定日期的分钟
+- (NSInteger)br_minute {
+    return [NSDate br_componentsFromDate:self].minute;
+}
+
+#pragma mark - 获取指定日期的秒
+- (NSInteger)br_second {
+    return [NSDate br_componentsFromDate:self].second;
+}
+
+#pragma mark - 获取指定日期的星期
+- (NSInteger)br_weekday {
+    return [NSDate br_componentsFromDate:self].weekday;
+}
+
+#pragma mark - 获取指定日期的月周
+- (NSInteger)br_monthWeek {
+    return [NSDate br_componentsFromDate:self].weekOfMonth;
+}
+
+#pragma mark - 获取指定日期的年周
+- (NSInteger)br_yearWeek {
+    return [NSDate br_componentsFromDate:self].weekOfYear;
+}
+
+#pragma mark - 获取指定日期的季度
+- (NSInteger)br_quarter {
+//    [NSDate br_componentsFromDate:self].quarter; // 取到的季度值总是0?
+    NSInteger quarter = 1;
+    NSInteger month = self.br_month;
+    if (month > 3) quarter = 2;
+    if (month > 6) quarter = 3;
+    if (month > 9) quarter = 4;
+    
+    return quarter;
+}
+
+#pragma mark - 获取指定日期的星期
+- (NSString *)br_weekdayString {
+    switch (self.br_weekday - 1) {
+        case 0:
+        {
+            return @"周日";
+        }
+            break;
+        case 1:
+        {
+            return @"周一";
+        }
+            break;
+        case 2:
+        {
+            return @"周二";
+        }
+            break;
+        case 3:
+        {
+            return @"周三";
+        }
+            break;
+        case 4:
+        {
+            return @"周四";
+        }
+            break;
+        case 5:
+        {
+            return @"周五";
+        }
+            break;
+        case 6:
+        {
+            return @"周六";
+        }
+            break;
+            
+        default:
+            break;
+    }
+    
+    return @"";
+}
+
+/// ---------------- 创建 date ----------------
+#pragma mark - 通过 NSDateComponents对象 来创建 NSDate对象(可以设置时区)
++ (nullable NSDate *)br_setDateFromComponents:(NSDateComponents *)components timeZone:(NSTimeZone *)timeZone {
+    // 创建日历对象,指定日历的算法(公历/阳历)
+    NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
+    if (timeZone) {
+        // NSCalendar 设置时区
+        calendar.timeZone = timeZone;
+    }
+    return [calendar dateFromComponents:components];
+}
+
+#pragma mark - 创建date(通过 NSCalendar 类来创建日期)
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second {
+    return [self br_setYear:year month:month day:day hour:hour minute:minute second:second weekOfMonth:0 weekOfYear:0 quarter:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day
+                  hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second
+           weekOfMonth:(NSInteger)weekOfMonth weekOfYear:(NSInteger)weekOfYear quarter:(NSInteger)quarter {
+    NSDateComponents *components = [self br_componentsFromDate:[NSDate date]];
+    if (year > 0) {
+        // 初始化日期组件
+        components = [[NSDateComponents alloc]init];
+        components.year = year;
+    }
+    if (month > 0) {
+        components.month = month;
+    }
+    if (day > 0) {
+        components.day = day;
+    }
+    if (hour >= 0) {
+        components.hour = hour;
+    }
+    if (minute >= 0) {
+        components.minute = minute;
+    }
+    if (second >= 0) {
+        components.second = second;
+    }
+    if (weekOfMonth > 0) {
+        components.weekOfMonth = weekOfMonth;
+    }
+    if (weekOfYear > 0) {
+        components.weekOfYear = weekOfYear;
+    }
+    if (quarter > 0) {
+        components.quarter = quarter;
+    }
+    
+    return [self br_dateFromComponents:components];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute {
+    return [self br_setYear:year month:month day:day hour:hour minute:minute second:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour {
+    return [self br_setYear:year month:month day:day hour:hour minute:0 second:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day {
+    return [self br_setYear:year month:month day:day hour:0 minute:0 second:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month {
+    return [self br_setYear:year month:month day:0 hour:0 minute:0 second:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year {
+    return [self br_setYear:year month:0 day:0 hour:0 minute:0 second:0];
+}
+
++ (NSDate *)br_setMonth:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute {
+    return [self br_setYear:0 month:month day:day hour:hour minute:minute second:0];
+}
+
++ (NSDate *)br_setMonth:(NSInteger)month day:(NSInteger)day {
+    return [self br_setYear:0 month:month day:day hour:0 minute:0 second:0];
+}
+
++ (NSDate *)br_setHour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second {
+    return [self br_setYear:0 month:0 day:0 hour:hour minute:minute second:second];
+}
+
++ (NSDate *)br_setHour:(NSInteger)hour minute:(NSInteger)minute {
+    return [self br_setYear:0 month:0 day:0 hour:hour minute:minute second:0];
+}
+
++ (NSDate *)br_setMinute:(NSInteger)minute second:(NSInteger)second {
+    return [self br_setYear:0 month:0 day:0 hour:0 minute:minute second:second];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year month:(NSInteger)month weekOfMonth:(NSInteger)weekOfMonth {
+    return [self br_setYear:year month:month day:0 hour:0 minute:0 second:0 weekOfMonth:weekOfMonth weekOfYear:0 quarter:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year weekOfYear:(NSInteger)weekOfYear {
+    return [self br_setYear:year month:0 day:0 hour:0 minute:0 second:0 weekOfMonth:0 weekOfYear:weekOfYear quarter:0];
+}
+
++ (NSDate *)br_setYear:(NSInteger)year quarter:(NSInteger)quarter {
+    return [self br_setYear:year month:0 day:0 hour:0 minute:0 second:0 weekOfMonth:0 weekOfYear:0 quarter:quarter];
+}
+
+#pragma mark - 获取某个月的天数(通过年月求每月天数)
++ (NSUInteger)br_getDaysInYear:(NSInteger)year month:(NSInteger)month {
+    BOOL isLeapYear = year % 4 == 0 ? (year % 100 == 0 ? (year % 400 == 0 ? YES : NO) : YES) : NO;
+    switch (month) {
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+        case 8:
+        case 10:
+        case 12:
+        {
+            return 31;
+        }
+        case 4:
+        case 6:
+        case 9:
+        case 11:
+        {
+            return 30;
+        }
+        case 2:
+        {
+            if (isLeapYear) {
+                return 29;
+            } else {
+                return 28;
+            }
+        }
+        default:
+            break;
+    }
+    
+    return 0;
+}
+
+#pragma mark - 获取某个月的周数(通过年月求该月周数)
++ (NSUInteger)br_getWeeksOfMonthInYear:(NSInteger)year month:(NSInteger)month {
+    NSUInteger lastDayOfMonth = [self br_getDaysInYear:year month:month];
+    NSDate *endDate = [self br_setYear:year month:month day:lastDayOfMonth];
+    return endDate.br_monthWeek;
+}
+
+#pragma mark - 获取某一年的周数(通过年求该年周数)
++ (NSUInteger)br_getWeeksOfYearInYear:(NSInteger)year {
+    NSDate *endDate = [self br_setYear:year month:12 day:31];
+    NSInteger weeks = endDate.br_yearWeek;
+    if (weeks == 1) weeks = 52;
+    return weeks;
+}
+
+#pragma mark - 获取某一年的季度数(通过年求该年季度数)
++ (NSUInteger)br_getQuartersInYear:(NSInteger)year {
+    NSDate *endDate = [self br_setYear:year month:12 day:31];
+    return endDate.br_quarter;
+}
+
+#pragma mark - 获取 日期加上/减去某天数后的新日期
+- (NSDate *)br_getNewDateToDays:(NSTimeInterval)days {
+    // days 为正数时,表示几天之后的日期;负数表示几天之前的日期
+    return [self dateByAddingTimeInterval:60 * 60 * 24 * days];
+}
+
+#pragma mark - 获取 日期加上/减去某个月数后的新日期
+- (nullable NSDate *)br_getNewDateToMonths:(NSTimeInterval)months {
+    // months 为正数时,表示几个月之后的日期;负数表示几个月之前的日期
+    NSDateComponents *components = [[NSDateComponents alloc] init];
+    [components setMonth:months];
+    NSCalendar *calender = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
+    return [calender dateByAddingComponents:components toDate:self options:0];
+}
+
+#pragma mark - NSDate 转 NSString
++ (NSString *)br_stringFromDate:(NSDate *)date dateFormat:(NSString *)dateFormat {
+    return [self br_stringFromDate:date dateFormat:dateFormat timeZone:nil language:nil];
+}
+#pragma mark - NSDate 转 NSString
++ (NSString *)br_stringFromDate:(NSDate *)date
+                     dateFormat:(NSString *)dateFormat
+                       timeZone:(NSTimeZone *)timeZone
+                       language:(NSString *)language {
+    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+    // 设置日期格式
+    dateFormatter.dateFormat = dateFormat;
+    // NSDateFormatter 设置时区 ,不设置默认为系统时区
+    if (timeZone) {
+        dateFormatter.timeZone = timeZone;
+    }
+    if (!language) {
+        language = [NSLocale preferredLanguages].firstObject;
+    }
+    dateFormatter.locale = [[NSLocale alloc]initWithLocaleIdentifier:language];
+    NSString *dateString = [dateFormatter stringFromDate:date];
+
+    return dateString;
+}
+
+#pragma mark - NSString 转 NSDate
++ (NSDate *)br_dateFromString:(NSString *)dateString dateFormat:(NSString *)dateFormat {
+    return [self br_dateFromString:dateString dateFormat:dateFormat timeZone:nil language:nil];
+}
+#pragma mark - NSString 转 NSDate
++ (NSDate *)br_dateFromString:(NSString *)dateString
+                   dateFormat:(NSString *)dateFormat
+                     timeZone:(NSTimeZone *)timeZone
+                     language:(NSString *)language {
+    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+    // 设置日期格式
+    dateFormatter.dateFormat = dateFormat;
+    // 设置时区
+    if (!timeZone) {
+        timeZone = [self currentTimeZone];
+    }
+    if (!language) {
+        language = [NSLocale preferredLanguages].firstObject;
+    }
+    dateFormatter.timeZone = timeZone;
+    dateFormatter.locale = [[NSLocale alloc]initWithLocaleIdentifier:language];
+    // 如果当前时间不存在,就获取距离最近的整点时间
+    dateFormatter.lenient = YES;
+    
+    return [dateFormatter dateFromString:dateString];
+}
+
+#pragma mark - 获取当前时区(不使用夏时制)
++ (NSTimeZone *)currentTimeZone {
+    // 当前时区
+    NSTimeZone *localTimeZone = [NSTimeZone localTimeZone];
+    // 当前时区相对于GMT(零时区)的偏移秒数
+    NSInteger interval = [localTimeZone secondsFromGMTForDate:[NSDate date]];
+    // 当前时区(不使用夏时制):由偏移量获得对应的NSTimeZone对象
+    // 注意:一些夏令时时间 NSString 转 NSDate 时,默认会导致 NSDateFormatter 格式化失败,返回 null
+    return [NSTimeZone timeZoneForSecondsFromGMT:interval];
+}
+
+#pragma mark - NSDate 转 NSString(已弃用)
++ (NSString *)br_getDateString:(NSDate *)date format:(NSString *)format {
+    return [self br_stringFromDate:date dateFormat:format];
+}
+
+#pragma mark - NSString 转 NSDate(已弃用)
++ (NSDate *)br_getDate:(NSString *)dateString format:(NSString *)format {
+    return [self br_dateFromString:dateString dateFormat:format];
+}
+
+@end

+ 37 - 0
Pods/BRPickerView/BRPickerView/StringPickerView/BRResultModel.h

@@ -0,0 +1,37 @@
+//
+//  BRResultModel.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2019/10/2.
+//  Copyright © 2019 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface BRResultModel : NSObject
+
+/** key */
+@property (nullable, nonatomic, copy) NSString *key;
+/** value */
+@property (nullable, nonatomic, copy) NSString *value;
+/** 父级key(提示:联动时第一级数据,parentKey设置为:@"-1") */
+@property (nullable, nonatomic, copy) NSString *parentKey;
+/** 父级value */
+@property (nullable, nonatomic, copy) NSString *parentValue;
+/** 级别 */
+@property (nullable, nonatomic, copy) NSString *level;
+/** 子级list */
+@property (nullable, nonatomic, copy) NSArray<BRResultModel *> *children;
+/** 记录选择的索引位置 */
+@property (nonatomic, assign) NSInteger index;
+
+/// 其它扩展字段
+@property (nullable, nonatomic, strong) id extras;
+@property (nullable, nonatomic, copy) NSString *remark;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 41 - 0
Pods/BRPickerView/BRPickerView/StringPickerView/BRResultModel.m

@@ -0,0 +1,41 @@
+//
+//  BRResultModel.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2019/10/2.
+//  Copyright © 2019 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRResultModel.h"
+
+@implementation BRResultModel
+
+/// 判断两个对象是否相等
+/// @param object 目标对象
+- (BOOL)isEqual:(id)object {
+    // 1.对象的地址相同
+    if (self == object) {
+        return YES;
+    }
+    
+    if (![object isKindOfClass:[BRResultModel class]]) {
+        return NO;
+    }
+    
+    BRResultModel *model = (BRResultModel *)object;
+    if (!model) {
+        return NO;
+    }
+    // 2.对象的类型相同,且对象的各个属性相等
+    BOOL isSameKey = (!self.key && !model.key) || [self.key isEqualToString:model.key];
+    BOOL isSameValue = (!self.value && !model.value) || [self.value isEqualToString:model.value];
+    
+    return isSameKey && isSameValue;
+}
+
+- (NSUInteger)hash {
+    return [self.key hash] ^ [self.value hash];
+}
+
+@end

+ 191 - 0
Pods/BRPickerView/BRPickerView/StringPickerView/BRStringPickerView.h

@@ -0,0 +1,191 @@
+//
+//  BRStringPickerView.h
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRBaseView.h"
+#import "BRResultModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// 字符串选择器类型
+typedef NS_ENUM(NSInteger, BRStringPickerMode) {
+    /** 单列选择器 */
+    BRStringPickerComponentSingle,
+    /** 多列选择器 */
+    BRStringPickerComponentMulti,
+    /** 多级联动选择器 */
+    BRStringPickerComponentLinkage
+};
+
+typedef void(^BRStringResultModelBlock)(BRResultModel * _Nullable resultModel);
+
+typedef void(^BRStringResultModelArrayBlock)(NSArray <BRResultModel *> * _Nullable resultModelArr);
+
+@interface BRStringPickerView : BRBaseView
+
+/**
+ //////////////////////////////////////////////////////////////////////////
+ ///
+ ///   【用法一】
+ ///    特点:灵活,扩展性强(推荐使用!)
+ ///
+ ////////////////////////////////////////////////////////////////////////*/
+
+/** 字符串选择器显示类型 */
+@property (nonatomic, assign) BRStringPickerMode pickerMode;
+
+/**
+ *  1.设置数据源
+ *    单列:@[@"男", @"女", @"其他"],或直接传一维模型数组(NSArray <BRResultModel *>*)
+ *    多列:@[@[@"语文", @"数学", @"英语"], @[@"优秀", @"良好"]],或直接传多维模型数组
+ *    联动:直接传一维模型数组(NSArray <BRResultModel *>*),要注意数据源联动格式,可参考Demo
+ */
+@property (nullable, nonatomic, copy) NSArray *dataSourceArr;
+/**
+ *  2.设置数据源
+ *    直接传plist文件名:NSString类型(如:@"test.plist"),要带后缀名
+ *    场景:可以将数据源数据(数组类型)放到plist文件中,直接传plist文件名更加简单
+ */
+@property (nullable, nonatomic, copy) NSString *plistName;
+
+/**
+ *  设置默认选中的位置【单列】
+ *  推荐使用 selectIndex,更加严谨,可以避免使用 selectValue 时,有名称相同的情况
+ */
+@property (nonatomic, assign) NSInteger selectIndex;
+@property (nullable, nonatomic, copy) NSString *selectValue;
+
+/**
+ *  设置默认选中的位置【多列】
+ *  推荐使用 selectIndexs,更加严谨,可以避免使用 selectValues 时,有名称相同的情况
+ */
+@property (nullable, nonatomic, copy) NSArray <NSNumber *> *selectIndexs;
+@property (nullable, nonatomic, copy) NSArray <NSString *> *selectValues;
+
+/** 选择结果的回调【单列】 */
+@property (nullable, nonatomic, copy) BRStringResultModelBlock resultModelBlock;
+/** 选择结果的回调【多列】 */
+@property (nullable, nonatomic, copy) BRStringResultModelArrayBlock resultModelArrayBlock;
+
+/** 滚动选择时触发的回调【单列】 */
+@property (nullable, nonatomic, copy) BRStringResultModelBlock changeModelBlock;
+/** 滚动选择时触发的回调【多列】 */
+@property (nullable, nonatomic, copy) BRStringResultModelArrayBlock changeModelArrayBlock;
+
+/**
+ *  最大层级数(列数) for `BRStringPickerComponentLinkage`, ignored otherwise.
+ *  使用场景:默认可选,当数据源中有 key 等于 parentKey 情况时,必须要设置
+ */
+@property (nonatomic, assign) NSInteger numberOfComponents;
+
+/// 初始化字符串选择器
+/// @param pickerMode 字符串选择器显示类型
+- (instancetype)initWithPickerMode:(BRStringPickerMode)pickerMode;
+
+/// 弹出选择器视图
+- (void)show;
+
+/// 关闭选择器视图
+- (void)dismiss;
+
+
+
+
+//================================================= 华丽的分割线 =================================================
+
+
+
+
+/**
+ //////////////////////////////////////////////////////////////////////////
+ ///
+ ///   【用法二】:快捷使用,直接选择下面其中的一个方法进行使用
+ ///    特点:快捷,方便
+ ///
+ ////////////////////////////////////////////////////////////////////////*/
+
+/**
+ *  1.显示【单列】选择器
+ *
+ *  @param title               选择器标题
+ *  @param dataSourceArr       数据源,格式:@[@"男", @"女", @"其他"],或直接传一维模型数组(NSArray <BRResultModel *>*)
+ *  @param selectIndex         默认选中的位置
+ *  @param resultBlock         选择后的回调
+ *
+ */
++ (void)showPickerWithTitle:(nullable NSString *)title
+              dataSourceArr:(nullable NSArray *)dataSourceArr
+                selectIndex:(NSInteger)selectIndex
+                resultBlock:(nullable BRStringResultModelBlock)resultBlock;
+
+/**
+ *  2.显示【单列】选择器
+ *
+ *  @param title               选择器标题
+ *  @param dataSourceArr       数据源(如:@[@"男", @"女", @"其他"],或直接传模型数组)
+ *  @param selectIndex         默认选中的位置
+ *  @param isAutoSelect        是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock         选择后的回调
+ *
+ */
++ (void)showPickerWithTitle:(nullable NSString *)title
+              dataSourceArr:(nullable NSArray *)dataSourceArr
+                selectIndex:(NSInteger)selectIndex
+               isAutoSelect:(BOOL)isAutoSelect
+                resultBlock:(nullable BRStringResultModelBlock)resultBlock;
+
+/**
+ *  3.显示【多列】选择器
+ *
+ *  @param title               选择器标题
+ *  @param dataSourceArr       数据源,格式:@[@[@"语文", @"数学", @"英语"], @[@"优秀", @"良好"]],或直接传多维模型数组
+ *  @param selectIndexs        默认选中的位置(传索引数组,如:@[@2, @1])
+ *  @param resultBlock         选择后的回调
+ *
+ */
++ (void)showMultiPickerWithTitle:(nullable NSString *)title
+                   dataSourceArr:(nullable NSArray *)dataSourceArr
+                    selectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                     resultBlock:(nullable BRStringResultModelArrayBlock)resultBlock;
+
+/**
+ *  4.显示【多列】选择器
+ *
+ *  @param title               选择器标题
+ *  @param dataSourceArr       数据源,格式:@[@[@"语文", @"数学", @"英语"], @[@"优秀", @"良好"]],或直接传多维模型数组
+ *  @param selectIndexs        默认选中的位置(传索引数组,如:@[@2, @1])
+ *  @param isAutoSelect        是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock         选择后的回调
+ *
+ */
++ (void)showMultiPickerWithTitle:(nullable NSString *)title
+                   dataSourceArr:(nullable NSArray *)dataSourceArr
+                    selectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                    isAutoSelect:(BOOL)isAutoSelect
+                     resultBlock:(nullable BRStringResultModelArrayBlock)resultBlock;
+
+/**
+ *  5.显示【联动】选择器
+ *
+ *  @param title               选择器标题
+ *  @param dataSourceArr       数据源,格式:直接传一维模型数组(NSArray <BRResultModel *>*)
+ *  @param selectIndexs        默认选中的位置(传索引数组,如:@[@2, @1])
+ *  @param isAutoSelect        是否自动选择,即滚动选择器后就执行结果回调,默认为 NO
+ *  @param resultBlock         选择后的回调
+ *
+ */
++ (void)showLinkagePickerWithTitle:(nullable NSString *)title
+                     dataSourceArr:(nullable NSArray *)dataSourceArr
+                      selectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                      isAutoSelect:(BOOL)isAutoSelect
+                       resultBlock:(nullable BRStringResultModelArrayBlock)resultBlock;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 571 - 0
Pods/BRPickerView/BRPickerView/StringPickerView/BRStringPickerView.m

@@ -0,0 +1,571 @@
+//
+//  BRStringPickerView.m
+//  BRPickerViewDemo
+//
+//  Created by renbo on 2017/8/11.
+//  Copyright © 2017 irenb. All rights reserved.
+//
+//  最新代码下载地址:https://github.com/91renb/BRPickerView
+
+#import "BRStringPickerView.h"
+
+@interface BRStringPickerView ()<UIPickerViewDelegate, UIPickerViewDataSource>
+{
+    BOOL _dataSourceException; // 数据源格式是否有误
+}
+/** 选择器 */
+@property (nonatomic, strong) UIPickerView *pickerView;
+/** 单列选择的值 */
+@property (nonatomic, copy) NSString *mSelectValue;
+/** 多列选择的值 */
+@property (nonatomic, copy) NSArray <NSString *>* mSelectValues;
+
+/** 数据源 */
+@property (nullable, nonatomic, copy) NSArray *mDataSourceArr;
+
+@end
+
+@implementation BRStringPickerView
+
+#pragma mark - 1.显示【单列】选择器
++ (void)showPickerWithTitle:(NSString *)title
+              dataSourceArr:(NSArray *)dataSourceArr
+                selectIndex:(NSInteger)selectIndex
+                resultBlock:(BRStringResultModelBlock)resultBlock {
+    [self showPickerWithTitle:title dataSourceArr:dataSourceArr selectIndex:selectIndex isAutoSelect:NO resultBlock:resultBlock];
+}
+
+#pragma mark - 2.显示【单列】选择器
++ (void)showPickerWithTitle:(NSString *)title
+              dataSourceArr:(NSArray *)dataSourceArr
+                selectIndex:(NSInteger)selectIndex
+               isAutoSelect:(BOOL)isAutoSelect
+                resultBlock:(BRStringResultModelBlock)resultBlock {
+    // 创建选择器
+    BRStringPickerView *strPickerView = [[BRStringPickerView alloc]init];
+    strPickerView.pickerMode = BRStringPickerComponentSingle;
+    strPickerView.title = title;
+    strPickerView.dataSourceArr = dataSourceArr;
+    strPickerView.selectIndex = selectIndex;
+    strPickerView.isAutoSelect = isAutoSelect;
+    strPickerView.resultModelBlock = resultBlock;
+    
+    // 显示
+    [strPickerView show];
+}
+
+#pragma mark - 3.显示【多列】选择器
++ (void)showMultiPickerWithTitle:(NSString *)title
+                   dataSourceArr:(NSArray *)dataSourceArr
+                    selectIndexs:(NSArray <NSNumber *>*)selectIndexs
+                     resultBlock:(BRStringResultModelArrayBlock)resultBlock {
+    [self showMultiPickerWithTitle:title dataSourceArr:dataSourceArr selectIndexs:selectIndexs isAutoSelect:NO resultBlock:resultBlock];
+}
+
+#pragma mark - 4.显示【多列】选择器
++ (void)showMultiPickerWithTitle:(NSString *)title
+                   dataSourceArr:(NSArray *)dataSourceArr
+                    selectIndexs:(NSArray <NSNumber *>*)selectIndexs
+                    isAutoSelect:(BOOL)isAutoSelect
+                     resultBlock:(BRStringResultModelArrayBlock)resultBlock {
+    // 创建选择器
+    BRStringPickerView *strPickerView = [[BRStringPickerView alloc]init];
+    strPickerView.pickerMode = BRStringPickerComponentMulti;
+    strPickerView.title = title;
+    strPickerView.dataSourceArr = dataSourceArr;
+    strPickerView.selectIndexs = selectIndexs;
+    strPickerView.isAutoSelect = isAutoSelect;
+    strPickerView.resultModelArrayBlock = resultBlock;
+    
+    // 显示
+    [strPickerView show];
+}
+
+#pragma mark - 5.显示【联动】选择器
++ (void)showLinkagePickerWithTitle:(nullable NSString *)title
+                     dataSourceArr:(nullable NSArray *)dataSourceArr
+                      selectIndexs:(nullable NSArray <NSNumber *> *)selectIndexs
+                      isAutoSelect:(BOOL)isAutoSelect
+                       resultBlock:(nullable BRStringResultModelArrayBlock)resultBlock {
+    // 创建选择器
+    BRStringPickerView *strPickerView = [[BRStringPickerView alloc]init];
+    strPickerView.pickerMode = BRStringPickerComponentLinkage;
+    strPickerView.title = title;
+    strPickerView.dataSourceArr = dataSourceArr;
+    strPickerView.selectIndexs = selectIndexs;
+    strPickerView.isAutoSelect = isAutoSelect;
+    strPickerView.resultModelArrayBlock = resultBlock;
+    
+    // 显示
+    [strPickerView show];
+}
+
+#pragma mark - 初始化自定义选择器
+- (instancetype)initWithPickerMode:(BRStringPickerMode)pickerMode {
+    if (self = [super init]) {
+        self.pickerMode = pickerMode;
+    }
+    return self;
+}
+
+#pragma mark - 处理选择器数据
+- (void)handlerPickerData {
+    if (self.dataSourceArr.count == 0) {
+        _dataSourceException = YES;
+    }
+    id item = [self.dataSourceArr firstObject];
+    if (self.pickerMode == BRStringPickerComponentSingle) {
+        _dataSourceException = [item isKindOfClass:[NSArray class]];
+    } else if (self.pickerMode == BRStringPickerComponentMulti) {
+        _dataSourceException = [item isKindOfClass:[NSString class]];
+    } else if (self.pickerMode == BRStringPickerComponentLinkage) {
+        _dataSourceException = ![item isKindOfClass:[BRResultModel class]];
+    }
+    if (_dataSourceException) {
+        NSAssert(!_dataSourceException, @"数据源异常!请检查选择器数据源的格式");
+        return;
+    }
+    
+    // 处理选择器当前选择的值
+    if (self.pickerMode == BRStringPickerComponentSingle) {
+        self.mDataSourceArr = self.dataSourceArr;
+        NSInteger selectIndex = 0;
+        if (self.selectIndex > 0 && self.selectIndex < self.mDataSourceArr.count) {
+            selectIndex = self.selectIndex;
+        } else {
+            if (self.mSelectValue) {
+                id item = [self.mDataSourceArr firstObject];
+                if ([item isKindOfClass:[BRResultModel class]]) {
+                    for (NSInteger i = 0; i < self.mDataSourceArr.count; i++) {
+                        BRResultModel *model = self.mDataSourceArr[i];
+                        if ([model.value isEqualToString:self.mSelectValue]) {
+                            selectIndex = i;
+                            break;
+                        }
+                    }
+                } else {
+                    if ([self.mDataSourceArr containsObject:self.mSelectValue]) {
+                        selectIndex = [self.mDataSourceArr indexOfObject:self.mSelectValue];
+                    }
+                }
+            }
+        }
+        self.selectIndex = selectIndex;
+        
+    } else if (self.pickerMode == BRStringPickerComponentMulti) {
+        self.mDataSourceArr = self.dataSourceArr;
+        NSMutableArray *selectIndexs = [[NSMutableArray alloc]init];
+        for (NSInteger i = 0; i < self.mDataSourceArr.count; i++) {
+            NSArray *itemArr = self.mDataSourceArr[i];
+            NSInteger row = 0;
+            if (self.selectIndexs.count > 0) {
+                if (i < self.selectIndexs.count) {
+                    NSInteger index = [self.selectIndexs[i] integerValue];
+                    row = ((index > 0 && index < itemArr.count) ? index : 0);
+                }
+            } else {
+                if (self.mSelectValues.count > 0 && i < self.mSelectValues.count) {
+                    NSString *value = self.mSelectValues[i];
+                    id item = [itemArr firstObject];
+                    if ([item isKindOfClass:[BRResultModel class]]) {
+                        for (NSInteger j = 0; j < itemArr.count; j++) {
+                            BRResultModel *model = itemArr[j];
+                            if ([model.value isEqualToString:value]) {
+                                row = j;
+                                break;
+                            }
+                        }
+                    } else {
+                        if ([itemArr containsObject:value]) {
+                            row = [itemArr indexOfObject:value];
+                        }
+                    }
+                }
+            }
+            [selectIndexs addObject:@(row)];
+        }
+        self.selectIndexs = [selectIndexs copy];
+        
+    } else if (self.pickerMode == BRStringPickerComponentLinkage) {
+        
+        NSMutableArray *selectIndexs = [[NSMutableArray alloc]init];
+        NSMutableArray *mDataSourceArr = [[NSMutableArray alloc]init];
+        
+        BRResultModel *selectModel = nil;
+        BOOL hasNext = YES;
+        NSInteger i = 0;
+
+        NSMutableArray *dataArr = [self.dataSourceArr mutableCopy];
+        
+        do {
+            NSArray *nextArr = [self getNextDataArr:dataArr selectModel:selectModel];
+            // 设置 numberOfComponents,防止 key 等于 parentKey 时进入死循环
+            if (nextArr.count == 0 || i > self.numberOfComponents - 1) {
+                hasNext = NO;
+                break;
+            }
+            
+            NSInteger selectIndex = 0;
+            if (self.selectIndexs.count > i && [self.selectIndexs[i] integerValue] < nextArr.count) {
+                selectIndex = [self.selectIndexs[i] integerValue];
+            }
+            selectModel = nextArr[selectIndex];
+            
+            [selectIndexs addObject:@(selectIndex)];
+            [mDataSourceArr addObject:nextArr];
+
+            i++;
+            
+        } while (hasNext);
+        
+        self.selectIndexs = [selectIndexs copy];
+        self.mDataSourceArr = [mDataSourceArr copy];
+    }
+}
+
+- (NSArray <BRResultModel *>*)getNextDataArr:(NSArray *)dataArr selectModel:(BRResultModel *)selectModel {
+    NSMutableArray *tempArr = [[NSMutableArray alloc]init];
+    // parentKey = @"-1",表示是第一列数据
+    NSString *key = selectModel ? selectModel.key : @"-1";
+    for (BRResultModel *model in dataArr) {
+        if ([model.parentKey isEqualToString:key]) {
+            [tempArr addObject:model];
+        }
+    }
+    return [tempArr copy];
+}
+
+#pragma mark - 选择器
+- (UIPickerView *)pickerView {
+    if (!_pickerView) {
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        _pickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, self.pickerStyle.titleBarHeight + pickerHeaderViewHeight, self.keyView.bounds.size.width, self.pickerStyle.pickerHeight)];
+        _pickerView.backgroundColor = self.pickerStyle.pickerColor;
+        _pickerView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
+        _pickerView.dataSource = self;
+        _pickerView.delegate = self;
+    }
+    return _pickerView;
+}
+
+#pragma mark - UIPickerViewDataSource
+// 1.设置 pickerView 的列数
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
+    switch (self.pickerMode) {
+        case BRStringPickerComponentSingle:
+            return 1;
+            break;
+        case BRStringPickerComponentMulti:
+        case BRStringPickerComponentLinkage:
+            return self.mDataSourceArr.count;
+            break;
+            
+        default:
+            break;
+    }
+}
+
+// 2.设置 pickerView 每列的行数
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
+    switch (self.pickerMode) {
+        case BRStringPickerComponentSingle:
+            return self.mDataSourceArr.count;
+            break;
+        case BRStringPickerComponentMulti:
+        case BRStringPickerComponentLinkage:
+        {
+            NSArray *itemArr = self.mDataSourceArr[component];
+            return itemArr.count;
+        }
+            break;
+            
+        default:
+            break;
+    }
+}
+
+#pragma mark - UIPickerViewDelegate
+// 3.设置 pickerView 的显示内容
+- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view {
+    // 1.自定义 row 的内容视图
+    UILabel *label = (UILabel *)view;
+    if (!label) {
+        label = [[UILabel alloc]init];
+        label.backgroundColor = [UIColor clearColor];
+        label.textAlignment = NSTextAlignmentCenter;
+        label.font = self.pickerStyle.pickerTextFont;
+        label.textColor = self.pickerStyle.pickerTextColor;
+        // 字体自适应属性
+        label.adjustsFontSizeToFitWidth = YES;
+        // 自适应最小字体缩放比例
+        label.minimumScaleFactor = 0.5f;
+    }
+    if (self.pickerMode == BRStringPickerComponentSingle) {
+        id item = self.mDataSourceArr[row];
+        if ([item isKindOfClass:[BRResultModel class]]) {
+            BRResultModel *model = (BRResultModel *)item;
+            label.text = model.value;
+        } else {
+            label.text = item;
+        }
+    } else if (self.pickerMode == BRStringPickerComponentMulti || self.pickerMode == BRStringPickerComponentLinkage) {
+        NSArray *itemArr = self.mDataSourceArr[component];
+        id item = [itemArr objectAtIndex:row];
+        if ([item isKindOfClass:[BRResultModel class]]) {
+            BRResultModel *model = (BRResultModel *)item;
+            label.text = model.value;
+        } else {
+            label.text = item;
+        }
+    }
+    
+    // 2.设置选择器中间选中行的样式
+    [self.pickerStyle setupPickerSelectRowStyle:pickerView titleForRow:row forComponent:component];
+    
+    return label;
+}
+
+// 4.滚动 pickerView 执行的回调方法
+- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
+    switch (self.pickerMode) {
+        case BRStringPickerComponentSingle:
+        {
+            self.selectIndex = row;
+            
+            // 滚动选择时执行 changeModelBlock
+            if (self.changeModelBlock) {
+                self.changeModelBlock([self getResultModel]);
+            }
+            
+            // 设置自动选择时,滚动选择时就执行 resultModelBlock
+            if (self.isAutoSelect) {
+                if (self.resultModelBlock) {
+                    self.resultModelBlock([self getResultModel]);
+                }
+            }
+        }
+            break;
+        case BRStringPickerComponentMulti:
+        {
+            if (component < self.selectIndexs.count) {
+                NSMutableArray *mutableArr = [self.selectIndexs mutableCopy];
+                [mutableArr replaceObjectAtIndex:component withObject:@(row)];
+                self.selectIndexs = [mutableArr copy];
+            }
+            
+            // 滚动选择时执行 changeModelArrayBlock
+            if (self.changeModelArrayBlock) {
+                self.changeModelArrayBlock([self getResultModelArr]);
+            }
+            
+            // 设置自动选择时,滚动选择时就执行 resultModelArrayBlock
+            if (self.isAutoSelect) {
+                if (self.resultModelArrayBlock) {
+                    self.resultModelArrayBlock([self getResultModelArr]);
+                }
+            }
+        }
+            break;
+        case BRStringPickerComponentLinkage:
+        {
+            if (component < self.selectIndexs.count) {
+                NSMutableArray *selectIndexs = [[NSMutableArray alloc]init];
+                for (NSInteger i = 0; i < self.selectIndexs.count; i++) {
+                    if (i < component) {
+                        [selectIndexs addObject:self.selectIndexs[i]];
+                    } else if (i == component) {
+                        [selectIndexs addObject:@(row)];
+                    } else {
+                        [selectIndexs addObject:@(0)];
+                    }
+                }
+                self.selectIndexs = [selectIndexs copy];
+            }
+            
+            // 刷新选择器数据
+            [self reloadData];
+            
+            // 滚动选择时执行 changeModelArrayBlock
+            if (self.changeModelArrayBlock) {
+                self.changeModelArrayBlock([self getResultModelArr]);
+            }
+            
+            // 设置自动选择时,滚动选择时就执行 resultModelArrayBlock
+            if (self.isAutoSelect) {
+                if (self.resultModelArrayBlock) {
+                    self.resultModelArrayBlock([self getResultModelArr]);
+                }
+            }
+        }
+            break;
+            
+        default:
+            break;
+    }
+}
+
+#pragma mark - 获取【单列】选择器选择的值
+- (BRResultModel *)getResultModel {
+    id item = self.selectIndex < self.mDataSourceArr.count ? self.mDataSourceArr[self.selectIndex] : nil;
+    if ([item isKindOfClass:[BRResultModel class]]) {
+        BRResultModel *model = (BRResultModel *)item;
+        model.index = self.selectIndex;
+        return model;
+    } else {
+        BRResultModel *model = [[BRResultModel alloc]init];
+        model.index = self.selectIndex;
+        model.value = item;
+        return model;
+    }
+}
+
+#pragma mark - 获取【多列】选择器选择的值
+- (NSArray *)getResultModelArr {
+    NSMutableArray *resultModelArr = [[NSMutableArray alloc]init];
+    for (NSInteger i = 0; i < self.mDataSourceArr.count; i++) {
+        NSInteger index = [self.selectIndexs[i] integerValue];
+        NSArray *dataArr = self.mDataSourceArr[i];
+        
+        id item = index < dataArr.count ? dataArr[index] : nil;
+        if ([item isKindOfClass:[BRResultModel class]]) {
+            BRResultModel *model = (BRResultModel *)item;
+            model.index = index;
+            [resultModelArr addObject:model];
+        } else {
+            BRResultModel *model = [[BRResultModel alloc]init];
+            model.index = index;
+            model.value = item;
+            [resultModelArr addObject:model];
+        }
+    }
+    return [resultModelArr copy];
+}
+
+// 设置行高
+- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
+    return self.pickerStyle.rowHeight;
+}
+
+#pragma mark - 重写父类方法
+- (void)reloadData {
+    // 1.处理数据源
+    [self handlerPickerData];
+    // 2.刷新选择器
+    [self.pickerView reloadAllComponents];
+    // 3.滚动到选择的值
+    if (self.pickerMode == BRStringPickerComponentSingle) {
+        [self.pickerView selectRow:self.selectIndex inComponent:0 animated:NO];
+    } else if (self.pickerMode == BRStringPickerComponentMulti || self.pickerMode == BRStringPickerComponentLinkage) {
+        for (NSInteger i = 0; i < self.selectIndexs.count; i++) {
+            NSNumber *index = [self.selectIndexs objectAtIndex:i];
+            [self.pickerView selectRow:[index integerValue] inComponent:i animated:NO];
+        }
+    }
+}
+
+- (void)addPickerToView:(UIView *)view {
+    // 1.添加选择器
+    if (view) {
+        // 立即刷新容器视图 view 的布局(防止 view 使用自动布局时,选择器视图无法正常显示)
+        [view setNeedsLayout];
+        [view layoutIfNeeded];
+        
+        self.frame = view.bounds;
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        CGFloat pickerFooterViewHeight = self.pickerFooterView ? self.pickerFooterView.bounds.size.height : 0;
+        self.pickerView.frame = CGRectMake(0, pickerHeaderViewHeight, view.bounds.size.width, view.bounds.size.height - pickerHeaderViewHeight - pickerFooterViewHeight);
+        [self addSubview:self.pickerView];
+    } else {
+        // iOS16:重新设置 pickerView 高度(解决懒加载设置frame不生效问题)
+        CGFloat pickerHeaderViewHeight = self.pickerHeaderView ? self.pickerHeaderView.bounds.size.height : 0;
+        self.pickerView.frame = CGRectMake(0, self.pickerStyle.titleBarHeight + pickerHeaderViewHeight, self.keyView.bounds.size.width, self.pickerStyle.pickerHeight);
+        
+        [self.alertView addSubview:self.pickerView];
+    }
+    
+    // ③添加中间选择行的两条分割线
+    if (self.pickerStyle.clearPickerNewStyle) {
+        [self.pickerStyle addSeparatorLineView:self.pickerView];
+    }
+    
+    // 2.绑定数据
+    [self reloadData];
+    
+    __weak typeof(self) weakSelf = self;
+    self.doneBlock = ^{
+        // 点击确定按钮后,执行block回调
+        if (weakSelf.pickerMode == BRStringPickerComponentSingle) {
+            if (weakSelf.resultModelBlock) {
+                weakSelf.resultModelBlock([weakSelf getResultModel]);
+            }
+        } else if (weakSelf.pickerMode == BRStringPickerComponentMulti || weakSelf.pickerMode == BRStringPickerComponentLinkage) {
+            if (weakSelf.resultModelArrayBlock) {
+                weakSelf.resultModelArrayBlock([weakSelf getResultModelArr]);
+            }
+        }
+    };
+    
+    [super addPickerToView:view];
+}
+
+#pragma mark - 重写父类方法
+- (void)addSubViewToPicker:(UIView *)customView {
+    [self.pickerView addSubview:customView];
+}
+
+#pragma mark - 弹出选择器视图
+- (void)show {
+    [self addPickerToView:nil];
+}
+
+#pragma mark - 关闭选择器视图
+- (void)dismiss {
+    [self removePickerFromView:nil];
+}
+
+#pragma mark - setter 方法
+- (void)setPlistName:(NSString *)plistName {
+    NSString *path = [[NSBundle mainBundle] pathForResource:plistName ofType:nil];
+    if (path && path.length > 0) {
+        self.dataSourceArr = [[NSArray alloc] initWithContentsOfFile:path];
+    }
+}
+
+- (void)setSelectValue:(NSString *)selectValue {
+    self.mSelectValue = selectValue;
+}
+
+- (void)setSelectValues:(NSArray<NSString *> *)selectValues {
+    self.mSelectValues = selectValues;
+}
+
+#pragma mark - getter 方法
+- (NSArray *)mDataSourceArr {
+    if (!_mDataSourceArr) {
+        _mDataSourceArr = [NSArray array];
+    }
+    return _mDataSourceArr;
+}
+
+- (NSArray<NSNumber *> *)selectIndexs {
+    if (!_selectIndexs) {
+        _selectIndexs = [NSArray array];
+    }
+    return _selectIndexs;
+}
+
+- (NSArray<NSString *> *)mSelectValues {
+    if (!_mSelectValues) {
+        _mSelectValues = [NSArray array];
+    }
+    return _mSelectValues;
+}
+
+- (NSInteger)numberOfComponents {
+    if (_numberOfComponents <= 0) {
+        _numberOfComponents = 3;
+    }
+    return _numberOfComponents;
+}
+
+@end

+ 21 - 0
Pods/BRPickerView/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 91renb
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 530 - 0
Pods/BRPickerView/README.md

@@ -0,0 +1,530 @@
+# BRPickerView
+
+BRPickerView 封装的是iOS中常用的选择器组件,主要包括:日期选择器(支持年月日、年月等15种日期样式选择,支持设置星期、至今等)、地址选择器(支持省市区、省市、省三种地区选择)、自定义字符串选择器(支持单列、多列、二级联动、三级联动选择)。支持自定义主题样式,适配深色模式,支持将选择器组件添加到指定容器视图。
+
+【说明】
+
+- 当前最新版本为: `2.8.1` 。
+- 如果不能找到最新版本,请先执行一下 `pod repo update` 更新本地仓库,待更新完成后;再执行 `pod search BRPickerView` 进行搜索,就会看到最新版本。
+
+# 效果演示
+
+查看并运行 `BRPickerViewDemo.xcodeproj`
+
+| ![效果图1](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/a.gif?raw=true) | ![效果图2](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/b.gif?raw=true) |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|                     框架Demo运行效果图1                      |                     框架Demo运行效果图2                      |
+
+# 安装
+
+#### 1. CocoaPods
+
+1. 在 Podfile 中添加 `pod 'BRPickerView'`。
+
+2. 执行 `pod install` 或 `pod update` 。
+
+3. 导入头文件 ` #import <BRPickerView.h>`。
+
+
+#### 2. 手动导入
+
+1. 将与 `README.md` 同级目录下的 `BRPickerView` 文件夹拽入项目中
+
+2. 导入头文件 ` #import "BRPickerView.h"`。
+
+
+# 系统要求
+
+- iOS 8.0+
+- ARC
+
+# 使用
+
+#### 1. 时间选择器:`BRDatePickerView`
+
+​	查看 BRDatePickerView.h 头文件,里面提供了两种使用方式,参见源码。
+
+```objective-c
+/// 日期选择器格式
+typedef NS_ENUM(NSInteger, BRDatePickerMode) {
+    // ----- 以下4种是系统样式(兼容国际化日期格式) -----
+    /** 【yyyy-MM-dd】UIDatePickerModeDate(美式日期:MM-dd-yyyy;英式日期:dd-MM-yyyy)*/
+    BRDatePickerModeDate,
+    /** 【yyyy-MM-dd HH:mm】 UIDatePickerModeDateAndTime */
+    BRDatePickerModeDateAndTime,
+    /** 【HH:mm】UIDatePickerModeTime */
+    BRDatePickerModeTime,
+    /** 【HH:mm】UIDatePickerModeCountDownTimer */
+    BRDatePickerModeCountDownTimer,
+    
+    // ----- 以下14种是自定义样式 -----
+    /** 【yyyy-MM-dd HH:mm:ss】年月日时分秒 */
+    BRDatePickerModeYMDHMS,
+    /** 【yyyy-MM-dd HH:mm】年月日时分 */
+    BRDatePickerModeYMDHM,
+    /** 【yyyy-MM-dd HH】年月日时 */
+    BRDatePickerModeYMDH,
+    /** 【MM-dd HH:mm】月日时分 */
+    BRDatePickerModeMDHM,
+    /** 【yyyy-MM-dd】年月日(兼容国际化日期:dd-MM-yyyy)*/
+    BRDatePickerModeYMD,
+    /** 【yyyy-MM】年月(兼容国际化日期:MM-yyyy)*/
+    BRDatePickerModeYM,
+    /** 【yyyy】年 */
+    BRDatePickerModeY,
+    /** 【MM-dd】月日 */
+    BRDatePickerModeMD,
+    /** 【HH:mm:ss】时分秒 */
+    BRDatePickerModeHMS,
+    /** 【HH:mm】时分 */
+    BRDatePickerModeHM,
+    /** 【mm:ss】分秒 */
+    BRDatePickerModeMS,
+    
+    /** 【yyyy-qq】年季度 */
+    BRDatePickerModeYQ,
+    /** 【yyyy-MM-ww】年月周 */
+    BRDatePickerModeYMW,
+    /** 【yyyy-ww】年周 */
+    BRDatePickerModeYW
+};
+```
+
+- 使用示例(参考Demo):
+
+```objective-c
+// 1.创建日期选择器
+BRDatePickerView *datePickerView = [[BRDatePickerView alloc]init];
+// 2.设置属性
+datePickerView.pickerMode = BRDatePickerModeYMD;
+datePickerView.title = @"选择年月日";
+// datePickerView.selectValue = @"2019-10-30";
+datePickerView.selectDate = [NSDate br_setYear:2019 month:10 day:30];
+datePickerView.minDate = [NSDate br_setYear:1949 month:3 day:12];
+datePickerView.maxDate = [NSDate date];
+datePickerView.isAutoSelect = YES;
+datePickerView.resultBlock = ^(NSDate *selectDate, NSString *selectValue) {
+    NSLog(@"选择的值:%@", selectValue);
+};
+// 设置自定义样式
+BRPickerStyle *customStyle = [[BRPickerStyle alloc]init];
+customStyle.pickerColor = BR_RGB_HEX(0xd9dbdf, 1.0f);
+customStyle.pickerTextColor = [UIColor redColor];
+customStyle.separatorColor = [UIColor redColor];
+datePickerView.pickerStyle = customStyle;
+
+// 3.显示
+[datePickerView show];
+```
+
+**时间选择器显示类型的效果图(默认样式):**
+
+- 以下4种样式是使用 UIDatePicker 类 进行封装的,支持循环滚动
+
+| ![样式1:BRDatePickerModeTime](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type1.png?raw=true) | ![样式2:BRDatePickerModeDate](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type2.png?raw=true) |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|                 样式1:BRDatePickerModeDate                  |              样式2:BRDatePickerModeDateAndTime              |
+|                                                              |                                                              |
+| ![样式3:BRDatePickerModeDateAndTime](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type3.png?raw=true) | ![样式4:BRDatePickerModeCountDownTimer](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type4.png?raw=true) |
+|                 样式3:BRDatePickerModeTime                  |            样式4:BRDatePickerModeCountDownTimer             |
+
+- 以下11种样式是使用 UIPickerView 类进行封装的。
+
+| ![样式5:BRDatePickerModeYMDHMS](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type5.png?raw=true) | ![样式6:BRDatePickerModeYMDHM](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type6.png?raw=true) |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|                样式5:BRDatePickerModeYMDHMS                 |                 样式6:BRDatePickerModeYMDHM                 |
+|                                                              |                                                              |
+| ![样式7:BRDatePickerModeYMDH](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type7.png?raw=true) | ![样式8:BRDatePickerModeMDHM](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type8.png?raw=true) |
+|                 样式7:BRDatePickerModeYMDH                  |                 样式8:BRDatePickerModeMDHM                  |
+|                                                              |                                                              |
+| ![样式9:BRDatePickerModeYMDE](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type9.png?raw=true) | ![样式10:BRDatePickerModeYMD](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type10.png?raw=true) |
+|                  样式9:BRDatePickerModeYMD                  |                  样式10:BRDatePickerModeYM                  |
+|                                                              |                                                              |
+| ![样式11:BRDatePickerModeYM](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type11.png?raw=true) | ![样式12:BRDatePickerModeY](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type12.png?raw=true) |
+|                  样式11:BRDatePickerModeY                   |                  样式12:BRDatePickerModeMD                  |
+|                                                              |                                                              |
+| ![样式13:BRDatePickerModeMD](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type13.png?raw=true) | ![样式14:BRDatePickerModeHMS](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type14.png?raw=true) |
+|                 样式13:BRDatePickerModeHMS                  |                  样式14:BRDatePickerModeHM                  |
+|                                                              |                                                              |
+| ![样式15:BRDatePickerModeHM](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type15.png?raw=true) |                                                              |
+|                  样式15:BRDatePickerModeMS                  |                                                              |
+
+- 其它日期样式
+
+| ![设置显示星期](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_week1.png?raw=true) | ![设置显示星期](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_week2.png?raw=true) |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| 设置显示星期:datePickerView.showWeek = YES;                 | 设置显示星期:datePickerView.showWeek = YES;                 |
+|                                                              |                                                              |
+| ![设置添加至今](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_now.png?raw=true) | ![设置显示今天](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_today.png?raw=true) |
+| 设置添加至今:datePickerView.addToNow = YES;                 | 设置显示今天:datePickerView.showToday = YES;                |
+|                                                              |                                                              |
+| ![日期单位单行显示样式](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_unit.png?raw=true) | ![自定义选择器选中行颜色](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_row.png?raw=true) |
+| 日期单位显示样式:datePickerView.showUnitType = BRShowUnitTypeOnlyCenter; | 设置选择器中间选中行的背景颜色:selectRowColor               |
+
+```objective-c
+// 设置选择器中间选中行的样式
+BRPickerStyle *customStyle = [[BRPickerStyle alloc]init];
+customStyle.selectRowColor = [UIColor blueColor];
+customStyle.selectRowTextFont = [UIFont boldSystemFontOfSize:20.0f];
+customStyle.selectRowTextColor = [UIColor redColor];
+datePickerView.pickerStyle = customStyle;
+```
+
+| ![英式日期年月日](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_en1.png?raw=true) | ![英式日期年月](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_en2.png?raw=true) |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| 样式:BRDatePickerModeYMD (默认非中文环境显示英式日期)     | 样式:BRDatePickerModeYM (默认非中文环境显示英式日期)      |
+
+- 几种常见的弹框样式模板
+
+| ![模板样式1](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/template_style1.png?raw=true) | ![模板样式2](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/template_style2.png?raw=true) |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| 弹框样式模板1:datePickerView.pickerStyle = [BRPickerStyle pickerStyleWithThemeColor:[UIColor blueColor]]; | 弹框样式模板2:datePickerView.pickerStyle = [BRPickerStyle pickerStyleWithDoneTextColor:[UIColor blueColor]]; |
+|                                                              |                                                              |
+| ![模板样式3](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/template_style3.png?raw=true) | ![添加选择器的头视图](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/date_type_top.png?raw=true) |
+| 弹框样式模板3:datePickerView.pickerStyle = [BRPickerStyle pickerStyleWithDoneBtnImage:[UIImage imageNamed:@"icon_close"]]; | 添加选择器的头视图:pickerHeaderView                         |
+
+```objective-c
+// 添加选择器头视图(pickerHeaderView)
+UIView *headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 36)];
+headerView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.1f];
+NSArray *unitArr = @[@"年", @"月", @"日"];
+for (NSInteger i = 0; i < unitArr.count; i++) {
+    CGFloat width = SCREEN_WIDTH / unitArr.count;
+    CGFloat orginX = i * (SCREEN_WIDTH / unitArr.count);
+    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(orginX, 0, width, 36)];
+    label.backgroundColor = [UIColor clearColor];
+    label.textAlignment = NSTextAlignmentCenter;
+    label.font = [UIFont systemFontOfSize:16.0f];
+    label.textColor = [UIColor darkGrayColor];
+    label.text = unitArr[i];
+    [headerView addSubview:label];
+}
+datePickerView.pickerHeaderView = headerView;
+```
+
+#### 2. 地址选择器:`BRAddressPickerView`
+
+​	查看 BRAddressPickerView.h 头文件,里面提供了两种使用方式,参见源码。
+
+- 使用示例(参考Demo):
+
+```objective-c
+/// 地址选择器
+BRAddressPickerView *addressPickerView = [[BRAddressPickerView alloc]init];
+addressPickerView.pickerMode = BRAddressPickerModeArea;
+addressPickerView.title = @"请选择地区";
+//addressPickerView.selectValues = @[@"浙江省", @"杭州市", @"西湖区"];
+addressPickerView.selectIndexs = @[@10, @0, @4];
+addressPickerView.isAutoSelect = YES;
+addressPickerView.resultBlock = ^(BRProvinceModel *province, BRCityModel *city, BRAreaModel *area) {
+    NSLog(@"选择的值:%@", [NSString stringWithFormat:@"%@ %@ %@", province.name, city.name, area.name]);
+};
+
+[addressPickerView show];
+```
+
+- 地址选择器的3种显示类型(showType 的3个枚举值):
+
+| ![省份](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/BRAddressPickerModeProvince.png?raw=true) | ![城市](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/BRAddressPickerModeCity.png?raw=true) |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|              样式1:BRAddressPickerModeProvince              |                样式2:BRAddressPickerModeCity                |
+|                                                              |                                                              |
+| ![地区](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/BRAddressPickerModeArea.png?raw=true) |                                                              |
+|                样式3:BRAddressPickerModeArea                |                                                              |
+
+#### 3.  自定义字符串选择器:`BRStringPickerView`
+
+​	查看 BRStringPickerView.h 头文件,里面提供了两种使用方式,参见源码。
+
+- 使用示例(参考Demo):
+
+```objective-c
+/// 1.单列字符串选择器(传字符串数组)
+BRStringPickerView *stringPickerView = [[BRStringPickerView alloc]init];
+stringPickerView.pickerMode = BRStringPickerComponentSingle;
+stringPickerView.title = @"学历";
+stringPickerView.dataSourceArr = @[@"大专以下", @"大专", @"本科", @"硕士", @"博士", @"博士后"];
+stringPickerView.selectIndex = 2;
+stringPickerView.resultModelBlock = ^(BRResultModel *resultModel) {
+    NSLog(@"选择的值:%@", resultModel.value);
+};
+
+[stringPickerView show];
+
+
+/// 2.单列字符串选择器(可以传模型数组)
+NSArray *infoArr = @[@{@"key": @"1001", @"value": @"无融资", @"remark": @""},
+                     @{@"key": @"2001", @"value": @"天使轮", @"remark": @""},
+                     @{@"key": @"3001", @"value": @"A轮", @"remark": @""},
+                     @{@"key": @"4001", @"value": @"B轮", @"remark": @""},
+                     @{@"key": @"5001", @"value": @"C轮以后", @"remark": @""},
+                     @{@"key": @"6001", @"value": @"已上市", @"remark": @""}];
+NSMutableArray *modelArr = [[NSMutableArray alloc]init];
+for (NSDictionary *dic in infoArr) {
+    BRResultModel *model = [[BRResultModel alloc]init];
+    model.key = dic[@"key"];
+    model.value = dic[@"value"];
+    model.remark = dic[@"remark"];
+    [modelArr addObject:model];
+}
+BRStringPickerView *stringPickerView = [[BRStringPickerView alloc]init];
+stringPickerView.pickerMode = BRStringPickerComponentSingle;
+stringPickerView.title = @"融资情况";
+stringPickerView.dataSourceArr = [modelArr copy];
+stringPickerView.selectIndex = 2;
+stringPickerView.resultModelBlock = ^(BRResultModel *resultModel) {
+    NSLog(@"选择的索引:%@", @(resultModel.index));
+    NSLog(@"选择的值:%@", resultModel.value);
+};
+
+[stringPickerView show];
+
+
+/// 3.多列字符串选择器
+BRStringPickerView *stringPickerView = [[BRStringPickerView alloc]init];
+stringPickerView.pickerMode = BRStringPickerComponentMulti;
+stringPickerView.title = @"自定义多列字符串";
+stringPickerView.dataSourceArr = @[@[@"语文", @"数学", @"英语", @"物理", @"化学", @"生物"], @[@"优秀", @"良好", @"及格", @"不及格"]];
+stringPickerView.selectIndexs = @[@2, @1];
+stringPickerView.resultModelArrayBlock = ^(NSArray<BRResultModel *> *resultModelArr) {
+    NSLog(@"选择的值:%@", [NSString stringWithFormat:@"%@,%@", resultModelArr[0].value, resultModelArr[1].value]);
+};
+
+// 设置选择器中间选中行的样式
+BRPickerStyle *customStyle = [[BRPickerStyle alloc]init];
+customStyle.selectRowTextFont = [UIFont boldSystemFontOfSize:20.0f];
+customStyle.selectRowTextColor = [UIColor blueColor];
+stringPickerView.pickerStyle = customStyle;
+
+[stringPickerView show];
+```
+
+- 字符串选择器效果图:
+
+| ![自定义单列字符串](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/string_single.png?raw=true) | ![融资情况](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/string_rongzi.png?raw=true) |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+|                       单列字符串选择器                       |                       单列字符串选择器                       |
+|                                                              |                                                              |
+| ![多列字符串选择器](https://github.com/91renb/BRPickerView/blob/master/BRPickerViewDemo/images/string_more.png?raw=true) |                                                              |
+|                       多列字符串选择器                       |                                                              |
+
+# 更新记录
+
+#### 2022-07-08(V2.8.0)
+
+- 优化代码。
+
+#### 2022-06-16(V2.7.8)
+
+- 优化代码。
+
+#### 2022-03-30(V2.7.7)
+
+- 优化代码。
+
+#### 2021-10-09(V2.7.6)
+
+- 适配iOS15
+
+#### 2021-05-28(V2.7.5)
+
+- 日期选择器新增属性:`monthNames` 和 `customUnit`
+
+- 解决已知问题:[#232](https://github.com/91renb/BRPickerView/issues/232) 、[#231](https://github.com/91renb/BRPickerView/issues/231)  、[#230](https://github.com/91renb/BRPickerView/issues/230)  、[#227](https://github.com/91renb/BRPickerView/issues/227)  、[#225](https://github.com/91renb/BRPickerView/issues/225) 、[#219](https://github.com/91renb/BRPickerView/issues/219) 、[#206](https://github.com/91renb/BRPickerView/issues/206) 
+
+#### 2020-09-25(V2.7.3)
+
+- 适配选择器iOS14的样式:[#189](https://github.com/91renb/BRPickerView/issues/189) 、[#191](https://github.com/91renb/BRPickerView/issues/191)
+
+#### 2020-09-23(V2.7.2)
+
+- 日期选择器新增添加自定义字符串属性:`firstRowContent` 和 `lastRowContent`
+- 解决日期选择器设置最小日期时,存在的联动不正确的问题:[#184](https://github.com/91renb/BRPickerView/issues/184) 
+
+#### 2020-08-28(V2.7.0)
+
+- 日期选择器添加 `nonSelectableDates` 属性:[#178](https://github.com/91renb/BRPickerView/issues/178) 
+- 优化选中行文本显示:[#177](https://github.com/91renb/BRPickerView/issues/177) 
+
+#### 2020-08-16(V2.6.8)
+
+- 优化代码,适配 iPad 分屏显示
+- 新增 `keyView` 属性(即组件的父视图:可以将组件添加到 自己获取的 keyWindow 上,或页面的 view 上)
+
+#### 2020-08-09(V2.6.7)
+
+- 适配 iOS14
+
+#### 2020-08-06(V2.6.6)
+
+- 修复 [#163](https://github.com/91renb/BRPickerView/issues/163) 和  [#170](https://github.com/91renb/BRPickerView/issues/170) 
+
+#### 2020-07-18(V2.6.5)
+
+- 字符串选择器新增支持多级联动选择
+
+#### 2020-06-24(V2.6.3)
+
+- 日期选择器新增属性:`timeZone` 和 `addCustomString`
+
+#### 2020-05-12(V2.6.2)
+
+- 实现 [#145](#145) 和  [#146](#146) 需求
+
+#### 2020-04-30(V2.6.0)
+
+- 新增样式属性:`selectRowTextColor` 和 `selectRowTextFont`
+- 日期选择器新增数字显示属性:`numberFullName`
+- 优化代码,添加 `BRDatePickerModeYMD` 支持国际化英式日期
+
+- 修复 [#143](#143)
+
+#### 2020-04-27(V2.5.8)
+
+- 修复 [#138](https://github.com/91renb/BRPickerView/issues/138) 和 [#142](https://github.com/91renb/BRPickerView/issues/142)
+- 日期选择器新增 `descending` 属性,支持降序的时间列表
+- 更新地址选择器地区数据源
+
+#### 2020-03-31(V2.5.7)
+
+- 优化代码,解决已知问题
+
+#### 2020-02-26(V2.5.6)
+
+- 优化代码,兼容部分国际化日期样式
+
+#### 2020-02-24(V2.5.5)
+
+- 添加设置选择器选中行背景颜色的功能,新增属性 `selectRowColor`
+
+#### 2020-01-31(V2.5.3)
+
+- 新增属性:`pickerHeaderView`、`pickerFooterView`
+- 新增刷新选择器数据方法:`reloadData`
+
+#### 2020-01-05(V2.5.1)
+
+- 优化代码,添加 `BRDatePickerModeYM` 支持国际化英式日期
+
+#### 2020-01-02(V2.5.0)
+
+- 日期选择器新增属性:`showUnitType`(日期单位显示样式)、`minuteInterval`、`secondInterval`
+- 封装了常用的几种模板样式,使用更加简单便捷
+- 框架内默认适配深色模式显示
+
+#### 2019-12-26(V2.4.6)
+
+- 添加支持动态更新属性 `title` 、 `selectDate`、`pickerMode` 的值
+- 日期选择器添加 `showWeek` 属性,及新增 `BRDatePickerModeMS` 日期类型
+- 优化选择器【用法二】的使用,新增选择器滚动选择时回调的属性
+
+#### 2019-11-28(V2.4.5)
+
+- 日期选择器新增选择 ”至今“ 和 显示 ”今天“ 的功能,见以下两个属性:
+
+  `showToday` :控制是否显示 “今天” ,默认为 NO
+
+  `addToNow`:控制是否添加选择 “至今”,默认为 NO
+
+#### 2019-11-26(V2.4.3)
+
+- 日期选择器新增以下三种选择类型:
+
+  `BRDatePickerModeYMDHMS`(年月日时分秒)、`BRDatePickerModeYMDE`(年月日星期)、`BRDatePickerModeHMS`(时分秒)
+
+- 更新地址选择器地区数据源
+
+#### 2019-11-07(V2.4.2)
+
+- 日期选择器添加:BRDatePickerModeYMDH(yyyy-MM-dd HH)类型
+- 地址选择器添加:selectIndexs 属性,可根据索引去设置默认选择
+- 适配横屏及刘海屏安全区域显示效果
+
+#### 2019-11-04(V2.4.0)
+
+- 优化选择器子目录管理,方便轻量级、模块化集成
+
+  `pod 'BRPickerView'`	// 集成全部的功能
+
+  `pod 'BRPickerView/DatePickerView'`	// 仅集成日期选择器的功能
+
+  `pod 'BRPickerView/AddressPickerView'`	// 仅集成地址选择器的功能
+
+  `pod 'BRPickerView/StringPickerView'`	// 仅集成字符串选择器的功能
+
+#### 2019-11-01(V2.3.8)
+
+- 优化代码,添加更多的自定义样式属性
+
+#### 2019-10-30(V2.3.6)
+
+- 优化代码,添加国际化支持
+
+#### 2019-10-26(V2.3.5)
+
+- 添加传统的创建对象设置属性的使用方式
+- 开放设置选择器颜色及样式,适配深色模式
+- 更新省市区数据源,数据与政府官网最新公布的一致(参见:[行政区划代码](http://www.mca.gov.cn/article/sj/xzqh/2019/))
+- 支持将选择器添加到指定容器视图上(见BaseView.h文件,扩展一方法)
+- 支持将子视图添加到选择器上(见BaseView.h文件,扩展二方法)
+- 优化代码,配置Pod库的层级目录
+
+#### 2018-04-27(V2.2.1):
+
+- 修复bug,适配iPad和横屏显示。
+- 优化代码,提高框架适应性,降低内存消耗。
+
+#### 2018-04-03(V2.2.0)
+
+- 时间选择器新添加了7种显示类型(BRDatePickerMode),可根据自己项目的需求选择性使用。
+- 适配横屏,及 iPhoneX 底部安全区域。
+- 修改了最小时间和最大时间的参数名称(以前版本是传 NSString 类型, 现在传 NSDate 类型)
+- 修复比较时间大小时出现的bug。
+
+#### 2018-03-19(V2.1.3)
+
+- 修改地址选择器确认选择后的回调参数。
+- 现修改如下:可通过省市区的模型获取省市区的 name(名称)、code(id)、index(索引)`resultBlock:^(BRProvinceModel *province, BRCityModel *city, BRAreaModel *area) {}`
+- 去掉第三方依赖库 `MJExtension` ,修改为手动解析地址数据源。
+
+#### 2018-03-11(V2.1.2)
+
+- 重命名了Github用户名,更新项目相关的路径。(提示:pod之前的版本不受影响)
+
+#### 2018-02-28(V2.1.1)
+
+- 修复某些情况下无法用bundle加载本地数据源(BRCity.plist)bug。
+
+#### 2018-01-26(V2.1.0)
+
+- 给地址选择器添加了一个方法(见方法4),提供数据源参数,支持外部传入地区数据源。
+- 提示:要注意数据源格式,参考 BRCity.json。可以把 BRCity.json 文件的内容放到后台去维护,通过后台接口获取地区数据源(即 BRCity.json 文件的内容)。
+
+#### 2018-01-25(V2.0.0)
+
+- 更新了地址数据源(BRCity.plist),地区信息是2018年最新最全的,与微信的地区信息完全一致。
+- 支持自定义默认选择地址(格式:@[@"浙江省", @"杭州市", @"西湖区"]),支持下次点击进入地址选择器时,默认地址为上次选择的结果。
+- 修改了日期选择器、地址选择器、字符串选择器的接口方法(删除了之前的方法2)。
+- 添加了地址选择器显示类型,支持3种显示:只显示省份、显示省份和城市、显示省市区。
+
+#### 2018-01-05(V1.3.0)
+
+- 添加取消选择的回调方法(点击背景或取消按钮会执行 `cancelBlock` )
+- 合并了字符串选择器 数组数据源和plist数据源对应的方法,`dataSource` 参数支持两种类型:
+
+#### 2018-01-02(V1.2.0)
+
+- 添加支持自定义主题颜色的方法。
+
+#### 2017-11-26(V1.1.0)
+
+- 更换第三方依赖库。
+- 用MJExtension 替换了 原来的YYModel,以前没有注意导入YYModel,同时又导入YYKit会导致重复导入而冲突(另外使用YYModel时,手动导入和pod导入 其中的头文件和方法名也不一样,所以很容易出错)。
+
+#### 2017-11-16(V1.0.0)
+
+- 初始版本!
+
+# 许可证
+
+BRPickerView 使用 MIT 许可证,详情见 LICENSE 文件。

+ 6 - 0
Pods/Local Podspecs/WMBase.podspec.json

@@ -36,6 +36,9 @@
     ],
     "YYCache": [
 
+    ],
+    "YYText": [
+
     ],
     "MBProgressHUD": [
 
@@ -54,6 +57,9 @@
     ],
     "CTMediator": [
 
+    ],
+    "BRPickerView": [
+
     ]
   }
 }

+ 20 - 1
Pods/Manifest.lock

@@ -623,6 +623,18 @@ PODS:
   - BoringSSL-GRPC/Implementation (0.0.24):
     - BoringSSL-GRPC/Interface (= 0.0.24)
   - BoringSSL-GRPC/Interface (0.0.24)
+  - BRPickerView (2.8.1):
+    - BRPickerView/AddressPickerView (= 2.8.1)
+    - BRPickerView/Base (= 2.8.1)
+    - BRPickerView/DatePickerView (= 2.8.1)
+    - BRPickerView/StringPickerView (= 2.8.1)
+  - BRPickerView/AddressPickerView (2.8.1):
+    - BRPickerView/Base
+  - BRPickerView/Base (2.8.1)
+  - BRPickerView/DatePickerView (2.8.1):
+    - BRPickerView/Base
+  - BRPickerView/StringPickerView (2.8.1):
+    - BRPickerView/Base
   - Bugly (2.5.93)
   - CTMediator (48)
   - FBAEMKit (16.1.0):
@@ -1120,6 +1132,7 @@ PODS:
   - Toast (4.0.0)
   - WMBase (1.0.9):
     - AFNetworking
+    - BRPickerView
     - CTMediator
     - Masonry
     - MBProgressHUD
@@ -1130,9 +1143,11 @@ PODS:
     - Toast
     - YTKNetwork
     - YYCache
+    - YYText
   - YTKNetwork (3.0.6):
     - AFNetworking/NSURLSession (~> 4.0)
   - YYCache (1.0.4)
+  - YYText (1.0.7)
 
 DEPENDENCIES:
   - AFNetworking
@@ -1164,6 +1179,7 @@ SPEC REPOS:
     - AFNetworking
     - AppAuth
     - BoringSSL-GRPC
+    - BRPickerView
     - Bugly
     - CTMediator
     - FBAEMKit
@@ -1203,6 +1219,7 @@ SPEC REPOS:
     - Toast
     - YTKNetwork
     - YYCache
+    - YYText
 
 EXTERNAL SOURCES:
   WMBase:
@@ -1213,6 +1230,7 @@ SPEC CHECKSUMS:
   AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
   AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
   BoringSSL-GRPC: 3175b25143e648463a56daeaaa499c6cb86dad33
+  BRPickerView: 2531a2d4d0fea0b57a1c738de215af0f88863a2f
   Bugly: b8715e6ec4004b7f7fbffab0643ba80545aee3da
   CTMediator: 3f3578b525b3a46a7a2f92a99922ec40363f4269
   FBAEMKit: c7efe06720a8b15b1d25b68921ba46dee20996e0
@@ -1250,9 +1268,10 @@ SPEC CHECKSUMS:
   Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
   SDWebImage: cb032eba469c54e0000e78bcb0a13cdde0a52798
   Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
-  WMBase: eb93e38dff7d9be4edb267acef5b3bdc1bc4d3a8
+  WMBase: a0c4b37b0af79598c62864d8580991b7d4f651f2
   YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04
   YYCache: 8105b6638f5e849296c71f331ff83891a4942952
+  YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
 
 PODFILE CHECKSUM: 9e16269a21fd5c9c1688e530bba69cffe563a650
 

File diff ditekan karena terlalu besar
+ 27820 - 27102
Pods/Pods.xcodeproj/project.pbxproj


+ 26 - 0
Pods/Target Support Files/BRPickerView/BRPickerView-Info.plist

@@ -0,0 +1,26 @@
+<?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>CFBundleDevelopmentRegion</key>
+  <string>${PODS_DEVELOPMENT_LANGUAGE}</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>2.8.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>${CURRENT_PROJECT_VERSION}</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>

+ 5 - 0
Pods/Target Support Files/BRPickerView/BRPickerView-dummy.m

@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_BRPickerView : NSObject
+@end
+@implementation PodsDummy_BRPickerView
+@end

+ 12 - 0
Pods/Target Support Files/BRPickerView/BRPickerView-prefix.pch

@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+

+ 28 - 0
Pods/Target Support Files/BRPickerView/BRPickerView-umbrella.h

@@ -0,0 +1,28 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
+#import "BRPickerView.h"
+#import "BRAddressModel.h"
+#import "BRAddressPickerView.h"
+#import "BRBaseView.h"
+#import "BRPickerStyle.h"
+#import "BRPickerViewMacro.h"
+#import "NSBundle+BRPickerView.h"
+#import "BRDatePickerView+BR.h"
+#import "BRDatePickerView.h"
+#import "NSDate+BRPickerView.h"
+#import "BRResultModel.h"
+#import "BRStringPickerView.h"
+
+FOUNDATION_EXPORT double BRPickerViewVersionNumber;
+FOUNDATION_EXPORT const unsigned char BRPickerViewVersionString[];
+

+ 13 - 0
Pods/Target Support Files/BRPickerView/BRPickerView.debug.xcconfig

@@ -0,0 +1,13 @@
+APPLICATION_EXTENSION_API_ONLY = YES
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/BRPickerView
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/BRPickerView
+PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6 - 0
Pods/Target Support Files/BRPickerView/BRPickerView.modulemap

@@ -0,0 +1,6 @@
+framework module BRPickerView {
+  umbrella header "BRPickerView-umbrella.h"
+
+  export *
+  module * { export * }
+}

+ 13 - 0
Pods/Target Support Files/BRPickerView/BRPickerView.release.xcconfig

@@ -0,0 +1,13 @@
+APPLICATION_EXTENSION_API_ONLY = YES
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/BRPickerView
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/BRPickerView
+PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 51 - 0
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.markdown

@@ -230,6 +230,31 @@ THE SOFTWARE.
    limitations under the License.
 
 
+## BRPickerView
+
+MIT License
+
+Copyright (c) 2019 91renb
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
 ## BoringSSL-GRPC
 
 BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
@@ -3214,6 +3239,32 @@ SOFTWARE.
 
 
 
+## YYText
+
+The MIT License (MIT)
+
+Copyright (c) 2015 ibireme <ibireme@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+
 ## abseil
 
 

+ 63 - 0
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension-acknowledgements.plist

@@ -253,6 +253,37 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>MIT License
+
+Copyright (c) 2019 91renb
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>BRPickerView</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
@@ -3459,6 +3490,38 @@ SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>The MIT License (MIT)
+
+Copyright (c) 2015 ibireme &lt;ibireme@gmail.com&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>YYText</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>

File diff ditekan karena terlalu besar
+ 3 - 3
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.debug.xcconfig


File diff ditekan karena terlalu besar
+ 3 - 3
Pods/Target Support Files/Pods-Asteria-NotificationServiceExtension/Pods-Asteria-NotificationServiceExtension.release.xcconfig


+ 51 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.markdown

@@ -230,6 +230,31 @@ THE SOFTWARE.
    limitations under the License.
 
 
+## BRPickerView
+
+MIT License
+
+Copyright (c) 2019 91renb
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
 ## BoringSSL-GRPC
 
 BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
@@ -3214,6 +3239,32 @@ SOFTWARE.
 
 
 
+## YYText
+
+The MIT License (MIT)
+
+Copyright (c) 2015 ibireme <ibireme@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+
 ## abseil
 
 

+ 63 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-acknowledgements.plist

@@ -253,6 +253,37 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>MIT License
+
+Copyright (c) 2019 91renb
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>BRPickerView</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
@@ -3459,6 +3490,38 @@ SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>The MIT License (MIT)
+
+Copyright (c) 2015 ibireme &lt;ibireme@gmail.com&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>YYText</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>

+ 2 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-input-files.xcfilelist

@@ -1,6 +1,7 @@
 ${PODS_ROOT}/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks.sh
 ${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework
 ${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework
+${BUILT_PRODUCTS_DIR}/BRPickerView/BRPickerView.framework
 ${BUILT_PRODUCTS_DIR}/BoringSSL-GRPC/openssl_grpc.framework
 ${BUILT_PRODUCTS_DIR}/CTMediator/CTMediator.framework
 ${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework
@@ -29,6 +30,7 @@ ${BUILT_PRODUCTS_DIR}/Toast/Toast.framework
 ${BUILT_PRODUCTS_DIR}/WMBase/WMBase.framework
 ${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
 ${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework
+${BUILT_PRODUCTS_DIR}/YYText/YYText.framework
 ${BUILT_PRODUCTS_DIR}/abseil/absl.framework
 ${BUILT_PRODUCTS_DIR}/gRPC-C++/grpcpp.framework
 ${BUILT_PRODUCTS_DIR}/gRPC-Core/grpc.framework

+ 2 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Debug-output-files.xcfilelist

@@ -1,5 +1,6 @@
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BRPickerView.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/openssl_grpc.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CTMediator.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework
@@ -28,6 +29,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WMBase.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYText.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/absl.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/grpcpp.framework
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/grpc.framework

+ 2 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-input-files.xcfilelist

@@ -1,6 +1,7 @@
 ${PODS_ROOT}/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks.sh
 ${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework
 ${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework
+${BUILT_PRODUCTS_DIR}/BRPickerView/BRPickerView.framework
 ${BUILT_PRODUCTS_DIR}/BoringSSL-GRPC/openssl_grpc.framework
 ${BUILT_PRODUCTS_DIR}/CTMediator/CTMediator.framework
 ${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework
@@ -29,6 +30,7 @@ ${BUILT_PRODUCTS_DIR}/Toast/Toast.framework
 ${BUILT_PRODUCTS_DIR}/WMBase/WMBase.framework
 ${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
 ${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework
+${BUILT_PRODUCTS_DIR}/YYText/YYText.framework
 ${BUILT_PRODUCTS_DIR}/abseil/absl.framework
 ${BUILT_PRODUCTS_DIR}/gRPC-C++/grpcpp.framework
 ${BUILT_PRODUCTS_DIR}/gRPC-Core/grpc.framework

+ 0 - 0
Pods/Target Support Files/Pods-Asteria/Pods-Asteria-frameworks-Release-output-files.xcfilelist


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini