├── .DS_Store ├── GHAlibabaSpecificationSelectionDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── mac.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── mac.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── GHAlibabaSpecificationSelectionDemo.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── mac.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── GHAlibabaSpecificationSelectionDemo ├── .DS_Store ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon-1024.png │ │ ├── icon-20-ipad.png │ │ ├── icon-20@2x-ipad.png │ │ ├── icon-20@2x.png │ │ ├── icon-20@3x.png │ │ ├── icon-29-ipad.png │ │ ├── icon-29.png │ │ ├── icon-29@2x-ipad.png │ │ ├── icon-29@2x.png │ │ ├── icon-29@3x.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ └── icon-83.5@2x.png │ ├── Contents.json │ ├── close.imageset │ │ ├── Contents.json │ │ └── close.png │ ├── emptyPage.imageset │ │ ├── Contents.json │ │ └── emptyPage.png │ ├── home.imageset │ │ ├── Contents.json │ │ └── home.png │ ├── leftArrow.imageset │ │ ├── Contents.json │ │ └── leftArrow.png │ ├── logo1.imageset │ │ ├── Contents.json │ │ └── logo1.png │ ├── rightArrow.imageset │ │ ├── Contents.json │ │ └── rightArrow.png │ └── shopCar.imageset │ │ ├── Contents.json │ │ └── shopCar.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── GHAlibabaSpecificationSelection.html ├── GHAlibabaSpecificationSelection │ ├── .DS_Store │ ├── Category │ │ ├── NSString+Extension.h │ │ ├── NSString+Extension.m │ │ ├── UIButton+Extension.h │ │ ├── UIButton+Extension.m │ │ ├── UIImage+Extension.h │ │ ├── UIImage+Extension.m │ │ ├── UIImage+ViewToImage.h │ │ ├── UIImage+ViewToImage.m │ │ ├── UIView+ActivityIndicator.h │ │ ├── UIView+ActivityIndicator.m │ │ ├── UIView+EmptyPage.h │ │ ├── UIView+EmptyPage.m │ │ ├── UIView+Extension.h │ │ └── UIView+Extension.m │ ├── Model │ │ ├── GHSpecificationSelectionBaseModel.h │ │ ├── GHSpecificationSelectionBaseModel.m │ │ ├── GHSpecificationSelectionImageModel.h │ │ ├── GHSpecificationSelectionImageModel.m │ │ ├── GHSpecificationSelectionModel.h │ │ ├── GHSpecificationSelectionModel.m │ │ ├── GHSpecificationSelectionTitleModel.h │ │ └── GHSpecificationSelectionTitleModel.m │ ├── Tool │ │ ├── ToastTool.h │ │ └── ToastTool.m │ └── View │ │ ├── GHAlibabaSpecificationSelection.h │ │ ├── GHAlibabaSpecificationSelection.m │ │ ├── GHAlibabaSpecificationSelectionBottomView.h │ │ ├── GHAlibabaSpecificationSelectionBottomView.m │ │ ├── GHButton.h │ │ ├── GHButton.m │ │ ├── GHPopView.h │ │ ├── GHPopView.m │ │ ├── GHScrollTitles.h │ │ ├── GHScrollTitles.m │ │ ├── GHTableView.h │ │ ├── GHTableView.m │ │ ├── GHTextField.h │ │ └── GHTextField.m ├── GHHTTPSessionManager.h ├── GHHTTPSessionManager.m ├── Info.plist ├── PrefixHeader.pch ├── ViewController.h ├── ViewController.m └── main.m ├── LICENSE ├── Podfile ├── README.md └── Untitled.gif /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/.DS_Store -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 04035982238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035981238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.m */; }; 11 | 04035986238EAF2200151AC2 /* UIButton+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035985238EAF2200151AC2 /* UIButton+Extension.m */; }; 12 | 04035989238EAF9000151AC2 /* UIImage+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035988238EAF9000151AC2 /* UIImage+Extension.m */; }; 13 | 0403598D238EB35100151AC2 /* ToastTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 0403598C238EB35100151AC2 /* ToastTool.m */; }; 14 | 04035992238EB38000151AC2 /* UIView+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035990238EB38000151AC2 /* UIView+Extension.m */; }; 15 | 04035993238EB38000151AC2 /* NSString+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035991238EB38000151AC2 /* NSString+Extension.m */; }; 16 | 0403599E238EB3BD00151AC2 /* GHSpecificationSelectionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035996238EB3BD00151AC2 /* GHSpecificationSelectionModel.m */; }; 17 | 0403599F238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035997238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.m */; }; 18 | 040359A0238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04035998238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.m */; }; 19 | 040359AF238EB40000151AC2 /* GHAlibabaSpecificationSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359A2238EB40000151AC2 /* GHAlibabaSpecificationSelection.m */; }; 20 | 040359B0238EB40000151AC2 /* GHPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359A3238EB40000151AC2 /* GHPopView.m */; }; 21 | 040359B1238EB40000151AC2 /* GHScrollTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359A6238EB40000151AC2 /* GHScrollTitles.m */; }; 22 | 040359B2238EB40000151AC2 /* GHTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359A8238EB40000151AC2 /* GHTableView.m */; }; 23 | 040359B4238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359AA238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.m */; }; 24 | 040359B5238EB40000151AC2 /* GHTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359AD238EB40000151AC2 /* GHTextField.m */; }; 25 | 040359C5238F9F7100151AC2 /* UIView+ActivityIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359C4238F9F7100151AC2 /* UIView+ActivityIndicator.m */; }; 26 | 040359C8238FA95F00151AC2 /* UIImage+ViewToImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359C7238FA95F00151AC2 /* UIImage+ViewToImage.m */; }; 27 | 040359CC2390250800151AC2 /* GHButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 040359CB2390250800151AC2 /* GHButton.m */; }; 28 | 040FA5B623544A4E001D2877 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 040FA5B523544A4E001D2877 /* AppDelegate.m */; }; 29 | 040FA5BC23544A4E001D2877 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 040FA5BB23544A4E001D2877 /* ViewController.m */; }; 30 | 040FA5BF23544A4E001D2877 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 040FA5BD23544A4E001D2877 /* Main.storyboard */; }; 31 | 040FA5C123544A4F001D2877 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 040FA5C023544A4F001D2877 /* Assets.xcassets */; }; 32 | 040FA5C423544A4F001D2877 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 040FA5C223544A4F001D2877 /* LaunchScreen.storyboard */; }; 33 | 040FA5C723544A4F001D2877 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 040FA5C623544A4F001D2877 /* main.m */; }; 34 | 040FA62F23599B27001D2877 /* GHHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 040FA62E23599B27001D2877 /* GHHTTPSessionManager.m */; }; 35 | 0450CF372432F0D100BD600C /* GHAlibabaSpecificationSelection.html in Resources */ = {isa = PBXBuildFile; fileRef = 0450CF362432F0D100BD600C /* GHAlibabaSpecificationSelection.html */; }; 36 | 0462804B238EA09500C4C277 /* GHTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 0462804A238EA09500C4C277 /* GHTextField.m */; }; 37 | 04C99BEA23902825005991EA /* GHSpecificationSelectionBaseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C99BE923902825005991EA /* GHSpecificationSelectionBaseModel.m */; }; 38 | 04C99CF92390E2DB005991EA /* UIView+EmptyPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C99CF82390E2DB005991EA /* UIView+EmptyPage.m */; }; 39 | F2990ADB9C9CE728232AA502 /* Pods_GHAlibabaSpecificationSelectionDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE7BDF1FC910CEB0A31B80C /* Pods_GHAlibabaSpecificationSelectionDemo.framework */; }; 40 | /* End PBXBuildFile section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 04035980238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHAlibabaSpecificationSelectionBottomView.h; sourceTree = ""; }; 44 | 04035981238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHAlibabaSpecificationSelectionBottomView.m; sourceTree = ""; }; 45 | 04035984238EAF2200151AC2 /* UIButton+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIButton+Extension.h"; sourceTree = ""; }; 46 | 04035985238EAF2200151AC2 /* UIButton+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIButton+Extension.m"; sourceTree = ""; }; 47 | 04035987238EAF9000151AC2 /* UIImage+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+Extension.h"; sourceTree = ""; }; 48 | 04035988238EAF9000151AC2 /* UIImage+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Extension.m"; sourceTree = ""; }; 49 | 0403598B238EB35100151AC2 /* ToastTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToastTool.h; sourceTree = ""; }; 50 | 0403598C238EB35100151AC2 /* ToastTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToastTool.m; sourceTree = ""; }; 51 | 0403598E238EB38000151AC2 /* NSString+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Extension.h"; sourceTree = ""; }; 52 | 0403598F238EB38000151AC2 /* UIView+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Extension.h"; sourceTree = ""; }; 53 | 04035990238EB38000151AC2 /* UIView+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Extension.m"; sourceTree = ""; }; 54 | 04035991238EB38000151AC2 /* NSString+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Extension.m"; sourceTree = ""; }; 55 | 04035996238EB3BD00151AC2 /* GHSpecificationSelectionModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHSpecificationSelectionModel.m; sourceTree = ""; }; 56 | 04035997238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHSpecificationSelectionTitleModel.m; sourceTree = ""; }; 57 | 04035998238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHSpecificationSelectionImageModel.m; sourceTree = ""; }; 58 | 0403599A238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHSpecificationSelectionTitleModel.h; sourceTree = ""; }; 59 | 0403599B238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHSpecificationSelectionImageModel.h; sourceTree = ""; }; 60 | 0403599C238EB3BD00151AC2 /* GHSpecificationSelectionModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHSpecificationSelectionModel.h; sourceTree = ""; }; 61 | 040359A1238EB40000151AC2 /* GHTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHTextField.h; sourceTree = ""; }; 62 | 040359A2238EB40000151AC2 /* GHAlibabaSpecificationSelection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHAlibabaSpecificationSelection.m; sourceTree = ""; }; 63 | 040359A3238EB40000151AC2 /* GHPopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHPopView.m; sourceTree = ""; }; 64 | 040359A4238EB40000151AC2 /* GHTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHTableView.h; sourceTree = ""; }; 65 | 040359A5238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHAlibabaSpecificationSelectionBottomView.h; sourceTree = ""; }; 66 | 040359A6238EB40000151AC2 /* GHScrollTitles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHScrollTitles.m; sourceTree = ""; }; 67 | 040359A7238EB40000151AC2 /* GHAlibabaSpecificationSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHAlibabaSpecificationSelection.h; sourceTree = ""; }; 68 | 040359A8238EB40000151AC2 /* GHTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHTableView.m; sourceTree = ""; }; 69 | 040359AA238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHAlibabaSpecificationSelectionBottomView.m; sourceTree = ""; }; 70 | 040359AB238EB40000151AC2 /* GHPopView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHPopView.h; sourceTree = ""; }; 71 | 040359AD238EB40000151AC2 /* GHTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHTextField.m; sourceTree = ""; }; 72 | 040359AE238EB40000151AC2 /* GHScrollTitles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHScrollTitles.h; sourceTree = ""; }; 73 | 040359C3238F9F7100151AC2 /* UIView+ActivityIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+ActivityIndicator.h"; sourceTree = ""; }; 74 | 040359C4238F9F7100151AC2 /* UIView+ActivityIndicator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+ActivityIndicator.m"; sourceTree = ""; }; 75 | 040359C6238FA95F00151AC2 /* UIImage+ViewToImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+ViewToImage.h"; sourceTree = ""; }; 76 | 040359C7238FA95F00151AC2 /* UIImage+ViewToImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ViewToImage.m"; sourceTree = ""; }; 77 | 040359CA2390250800151AC2 /* GHButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHButton.h; sourceTree = ""; }; 78 | 040359CB2390250800151AC2 /* GHButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHButton.m; sourceTree = ""; }; 79 | 040FA5B123544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GHAlibabaSpecificationSelectionDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | 040FA5B423544A4E001D2877 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 81 | 040FA5B523544A4E001D2877 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 82 | 040FA5BA23544A4E001D2877 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 83 | 040FA5BB23544A4E001D2877 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 84 | 040FA5BE23544A4E001D2877 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 85 | 040FA5C023544A4F001D2877 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 86 | 040FA5C323544A4F001D2877 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 87 | 040FA5C523544A4F001D2877 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 88 | 040FA5C623544A4F001D2877 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 89 | 040FA62D23599B27001D2877 /* GHHTTPSessionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHHTTPSessionManager.h; sourceTree = ""; }; 90 | 040FA62E23599B27001D2877 /* GHHTTPSessionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHHTTPSessionManager.m; sourceTree = ""; }; 91 | 0450CF362432F0D100BD600C /* GHAlibabaSpecificationSelection.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = GHAlibabaSpecificationSelection.html; sourceTree = ""; }; 92 | 04628044238E835200C4C277 /* PrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; 93 | 04628049238EA09500C4C277 /* GHTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHTextField.h; sourceTree = ""; }; 94 | 0462804A238EA09500C4C277 /* GHTextField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHTextField.m; sourceTree = ""; }; 95 | 04C99BE823902825005991EA /* GHSpecificationSelectionBaseModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GHSpecificationSelectionBaseModel.h; sourceTree = ""; }; 96 | 04C99BE923902825005991EA /* GHSpecificationSelectionBaseModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHSpecificationSelectionBaseModel.m; sourceTree = ""; }; 97 | 04C99CF72390E2DB005991EA /* UIView+EmptyPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+EmptyPage.h"; sourceTree = ""; }; 98 | 04C99CF82390E2DB005991EA /* UIView+EmptyPage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+EmptyPage.m"; sourceTree = ""; }; 99 | 1D64B2FE7F97A0941C374FA6 /* Pods-GHAlibabaSpecificationSelectionDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GHAlibabaSpecificationSelectionDemo.release.xcconfig"; path = "Target Support Files/Pods-GHAlibabaSpecificationSelectionDemo/Pods-GHAlibabaSpecificationSelectionDemo.release.xcconfig"; sourceTree = ""; }; 100 | AFE7BDF1FC910CEB0A31B80C /* Pods_GHAlibabaSpecificationSelectionDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GHAlibabaSpecificationSelectionDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 101 | EF6CA08E36706B06D4CE6A26 /* Pods-GHAlibabaSpecificationSelectionDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GHAlibabaSpecificationSelectionDemo.debug.xcconfig"; path = "Target Support Files/Pods-GHAlibabaSpecificationSelectionDemo/Pods-GHAlibabaSpecificationSelectionDemo.debug.xcconfig"; sourceTree = ""; }; 102 | /* End PBXFileReference section */ 103 | 104 | /* Begin PBXFrameworksBuildPhase section */ 105 | 040FA5AE23544A4E001D2877 /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | F2990ADB9C9CE728232AA502 /* Pods_GHAlibabaSpecificationSelectionDemo.framework in Frameworks */, 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | /* End PBXFrameworksBuildPhase section */ 114 | 115 | /* Begin PBXGroup section */ 116 | 04035983238EAF0A00151AC2 /* Category */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 04C99CF72390E2DB005991EA /* UIView+EmptyPage.h */, 120 | 04C99CF82390E2DB005991EA /* UIView+EmptyPage.m */, 121 | 0403598E238EB38000151AC2 /* NSString+Extension.h */, 122 | 04035991238EB38000151AC2 /* NSString+Extension.m */, 123 | 0403598F238EB38000151AC2 /* UIView+Extension.h */, 124 | 04035990238EB38000151AC2 /* UIView+Extension.m */, 125 | 04035984238EAF2200151AC2 /* UIButton+Extension.h */, 126 | 04035985238EAF2200151AC2 /* UIButton+Extension.m */, 127 | 04035987238EAF9000151AC2 /* UIImage+Extension.h */, 128 | 04035988238EAF9000151AC2 /* UIImage+Extension.m */, 129 | 040359C6238FA95F00151AC2 /* UIImage+ViewToImage.h */, 130 | 040359C7238FA95F00151AC2 /* UIImage+ViewToImage.m */, 131 | 040359C3238F9F7100151AC2 /* UIView+ActivityIndicator.h */, 132 | 040359C4238F9F7100151AC2 /* UIView+ActivityIndicator.m */, 133 | ); 134 | path = Category; 135 | sourceTree = ""; 136 | }; 137 | 0403598A238EB31900151AC2 /* Tool */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 0403598B238EB35100151AC2 /* ToastTool.h */, 141 | 0403598C238EB35100151AC2 /* ToastTool.m */, 142 | ); 143 | path = Tool; 144 | sourceTree = ""; 145 | }; 146 | 04035994238EB39D00151AC2 /* Model */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 0403599B238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.h */, 150 | 04035998238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.m */, 151 | 0403599C238EB3BD00151AC2 /* GHSpecificationSelectionModel.h */, 152 | 04035996238EB3BD00151AC2 /* GHSpecificationSelectionModel.m */, 153 | 0403599A238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.h */, 154 | 04035997238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.m */, 155 | 04C99BE823902825005991EA /* GHSpecificationSelectionBaseModel.h */, 156 | 04C99BE923902825005991EA /* GHSpecificationSelectionBaseModel.m */, 157 | ); 158 | path = Model; 159 | sourceTree = ""; 160 | }; 161 | 040359C92390249000151AC2 /* Controller */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | ); 165 | path = Controller; 166 | sourceTree = ""; 167 | }; 168 | 040FA5A823544A4E001D2877 = { 169 | isa = PBXGroup; 170 | children = ( 171 | 040FA5B323544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo */, 172 | 040FA5B223544A4E001D2877 /* Products */, 173 | B4F0B1F47559439ADCD9416E /* Pods */, 174 | 512CDB4D147EE6F6F97CADBE /* Frameworks */, 175 | ); 176 | sourceTree = ""; 177 | }; 178 | 040FA5B223544A4E001D2877 /* Products */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | 040FA5B123544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo.app */, 182 | ); 183 | name = Products; 184 | sourceTree = ""; 185 | }; 186 | 040FA5B323544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | 040FA5CD23544A61001D2877 /* GHAlibabaSpecificationSelection */, 190 | 040FA5B423544A4E001D2877 /* AppDelegate.h */, 191 | 040FA5B523544A4E001D2877 /* AppDelegate.m */, 192 | 040FA5BA23544A4E001D2877 /* ViewController.h */, 193 | 040FA5BB23544A4E001D2877 /* ViewController.m */, 194 | 040FA5BD23544A4E001D2877 /* Main.storyboard */, 195 | 040FA62D23599B27001D2877 /* GHHTTPSessionManager.h */, 196 | 040FA62E23599B27001D2877 /* GHHTTPSessionManager.m */, 197 | 04628044238E835200C4C277 /* PrefixHeader.pch */, 198 | 0450CF362432F0D100BD600C /* GHAlibabaSpecificationSelection.html */, 199 | 040FA5C023544A4F001D2877 /* Assets.xcassets */, 200 | 040FA5C223544A4F001D2877 /* LaunchScreen.storyboard */, 201 | 040FA5C523544A4F001D2877 /* Info.plist */, 202 | 040FA5C623544A4F001D2877 /* main.m */, 203 | ); 204 | path = GHAlibabaSpecificationSelectionDemo; 205 | sourceTree = ""; 206 | }; 207 | 040FA5CD23544A61001D2877 /* GHAlibabaSpecificationSelection */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | 040359C92390249000151AC2 /* Controller */, 211 | 04035994238EB39D00151AC2 /* Model */, 212 | 0403598A238EB31900151AC2 /* Tool */, 213 | 04035983238EAF0A00151AC2 /* Category */, 214 | 04628048238EA08000C4C277 /* View */, 215 | ); 216 | path = GHAlibabaSpecificationSelection; 217 | sourceTree = ""; 218 | }; 219 | 04628048238EA08000C4C277 /* View */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 040359A7238EB40000151AC2 /* GHAlibabaSpecificationSelection.h */, 223 | 040359A2238EB40000151AC2 /* GHAlibabaSpecificationSelection.m */, 224 | 040359A5238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.h */, 225 | 040359AA238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.m */, 226 | 040359AB238EB40000151AC2 /* GHPopView.h */, 227 | 040359A3238EB40000151AC2 /* GHPopView.m */, 228 | 040359AE238EB40000151AC2 /* GHScrollTitles.h */, 229 | 040359A6238EB40000151AC2 /* GHScrollTitles.m */, 230 | 040359A4238EB40000151AC2 /* GHTableView.h */, 231 | 040359A8238EB40000151AC2 /* GHTableView.m */, 232 | 040359A1238EB40000151AC2 /* GHTextField.h */, 233 | 040359AD238EB40000151AC2 /* GHTextField.m */, 234 | 04628049238EA09500C4C277 /* GHTextField.h */, 235 | 0462804A238EA09500C4C277 /* GHTextField.m */, 236 | 04035980238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.h */, 237 | 04035981238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.m */, 238 | 040359CA2390250800151AC2 /* GHButton.h */, 239 | 040359CB2390250800151AC2 /* GHButton.m */, 240 | ); 241 | path = View; 242 | sourceTree = ""; 243 | }; 244 | 512CDB4D147EE6F6F97CADBE /* Frameworks */ = { 245 | isa = PBXGroup; 246 | children = ( 247 | AFE7BDF1FC910CEB0A31B80C /* Pods_GHAlibabaSpecificationSelectionDemo.framework */, 248 | ); 249 | name = Frameworks; 250 | sourceTree = ""; 251 | }; 252 | B4F0B1F47559439ADCD9416E /* Pods */ = { 253 | isa = PBXGroup; 254 | children = ( 255 | EF6CA08E36706B06D4CE6A26 /* Pods-GHAlibabaSpecificationSelectionDemo.debug.xcconfig */, 256 | 1D64B2FE7F97A0941C374FA6 /* Pods-GHAlibabaSpecificationSelectionDemo.release.xcconfig */, 257 | ); 258 | path = Pods; 259 | sourceTree = ""; 260 | }; 261 | /* End PBXGroup section */ 262 | 263 | /* Begin PBXNativeTarget section */ 264 | 040FA5B023544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo */ = { 265 | isa = PBXNativeTarget; 266 | buildConfigurationList = 040FA5CA23544A4F001D2877 /* Build configuration list for PBXNativeTarget "GHAlibabaSpecificationSelectionDemo" */; 267 | buildPhases = ( 268 | 42E93C4C4E1CED15B8CB4857 /* [CP] Check Pods Manifest.lock */, 269 | 040FA5AD23544A4E001D2877 /* Sources */, 270 | 040FA5AE23544A4E001D2877 /* Frameworks */, 271 | 040FA5AF23544A4E001D2877 /* Resources */, 272 | 709CA1EB4814EF56DD6189A2 /* [CP] Embed Pods Frameworks */, 273 | ); 274 | buildRules = ( 275 | ); 276 | dependencies = ( 277 | ); 278 | name = GHAlibabaSpecificationSelectionDemo; 279 | productName = GHAlibabaSpecificationSelectionDemo; 280 | productReference = 040FA5B123544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo.app */; 281 | productType = "com.apple.product-type.application"; 282 | }; 283 | /* End PBXNativeTarget section */ 284 | 285 | /* Begin PBXProject section */ 286 | 040FA5A923544A4E001D2877 /* Project object */ = { 287 | isa = PBXProject; 288 | attributes = { 289 | LastUpgradeCheck = 1100; 290 | ORGANIZATIONNAME = macBookPro; 291 | TargetAttributes = { 292 | 040FA5B023544A4E001D2877 = { 293 | CreatedOnToolsVersion = 11.0; 294 | }; 295 | }; 296 | }; 297 | buildConfigurationList = 040FA5AC23544A4E001D2877 /* Build configuration list for PBXProject "GHAlibabaSpecificationSelectionDemo" */; 298 | compatibilityVersion = "Xcode 9.3"; 299 | developmentRegion = en; 300 | hasScannedForEncodings = 0; 301 | knownRegions = ( 302 | en, 303 | Base, 304 | ); 305 | mainGroup = 040FA5A823544A4E001D2877; 306 | productRefGroup = 040FA5B223544A4E001D2877 /* Products */; 307 | projectDirPath = ""; 308 | projectRoot = ""; 309 | targets = ( 310 | 040FA5B023544A4E001D2877 /* GHAlibabaSpecificationSelectionDemo */, 311 | ); 312 | }; 313 | /* End PBXProject section */ 314 | 315 | /* Begin PBXResourcesBuildPhase section */ 316 | 040FA5AF23544A4E001D2877 /* Resources */ = { 317 | isa = PBXResourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | 040FA5C423544A4F001D2877 /* LaunchScreen.storyboard in Resources */, 321 | 0450CF372432F0D100BD600C /* GHAlibabaSpecificationSelection.html in Resources */, 322 | 040FA5C123544A4F001D2877 /* Assets.xcassets in Resources */, 323 | 040FA5BF23544A4E001D2877 /* Main.storyboard in Resources */, 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | }; 327 | /* End PBXResourcesBuildPhase section */ 328 | 329 | /* Begin PBXShellScriptBuildPhase section */ 330 | 42E93C4C4E1CED15B8CB4857 /* [CP] Check Pods Manifest.lock */ = { 331 | isa = PBXShellScriptBuildPhase; 332 | buildActionMask = 2147483647; 333 | files = ( 334 | ); 335 | inputFileListPaths = ( 336 | ); 337 | inputPaths = ( 338 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 339 | "${PODS_ROOT}/Manifest.lock", 340 | ); 341 | name = "[CP] Check Pods Manifest.lock"; 342 | outputFileListPaths = ( 343 | ); 344 | outputPaths = ( 345 | "$(DERIVED_FILE_DIR)/Pods-GHAlibabaSpecificationSelectionDemo-checkManifestLockResult.txt", 346 | ); 347 | runOnlyForDeploymentPostprocessing = 0; 348 | shellPath = /bin/sh; 349 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 350 | showEnvVarsInLog = 0; 351 | }; 352 | 709CA1EB4814EF56DD6189A2 /* [CP] Embed Pods Frameworks */ = { 353 | isa = PBXShellScriptBuildPhase; 354 | buildActionMask = 2147483647; 355 | files = ( 356 | ); 357 | inputFileListPaths = ( 358 | "${PODS_ROOT}/Target Support Files/Pods-GHAlibabaSpecificationSelectionDemo/Pods-GHAlibabaSpecificationSelectionDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", 359 | ); 360 | name = "[CP] Embed Pods Frameworks"; 361 | outputFileListPaths = ( 362 | "${PODS_ROOT}/Target Support Files/Pods-GHAlibabaSpecificationSelectionDemo/Pods-GHAlibabaSpecificationSelectionDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | shellPath = /bin/sh; 366 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-GHAlibabaSpecificationSelectionDemo/Pods-GHAlibabaSpecificationSelectionDemo-frameworks.sh\"\n"; 367 | showEnvVarsInLog = 0; 368 | }; 369 | /* End PBXShellScriptBuildPhase section */ 370 | 371 | /* Begin PBXSourcesBuildPhase section */ 372 | 040FA5AD23544A4E001D2877 /* Sources */ = { 373 | isa = PBXSourcesBuildPhase; 374 | buildActionMask = 2147483647; 375 | files = ( 376 | 0403599F238EB3BD00151AC2 /* GHSpecificationSelectionTitleModel.m in Sources */, 377 | 040359B0238EB40000151AC2 /* GHPopView.m in Sources */, 378 | 04035986238EAF2200151AC2 /* UIButton+Extension.m in Sources */, 379 | 040359C8238FA95F00151AC2 /* UIImage+ViewToImage.m in Sources */, 380 | 040FA5BC23544A4E001D2877 /* ViewController.m in Sources */, 381 | 040359A0238EB3BD00151AC2 /* GHSpecificationSelectionImageModel.m in Sources */, 382 | 040359C5238F9F7100151AC2 /* UIView+ActivityIndicator.m in Sources */, 383 | 04C99CF92390E2DB005991EA /* UIView+EmptyPage.m in Sources */, 384 | 040359B4238EB40000151AC2 /* GHAlibabaSpecificationSelectionBottomView.m in Sources */, 385 | 0462804B238EA09500C4C277 /* GHTextField.m in Sources */, 386 | 040359AF238EB40000151AC2 /* GHAlibabaSpecificationSelection.m in Sources */, 387 | 04035992238EB38000151AC2 /* UIView+Extension.m in Sources */, 388 | 040FA5B623544A4E001D2877 /* AppDelegate.m in Sources */, 389 | 0403598D238EB35100151AC2 /* ToastTool.m in Sources */, 390 | 04C99BEA23902825005991EA /* GHSpecificationSelectionBaseModel.m in Sources */, 391 | 04035993238EB38000151AC2 /* NSString+Extension.m in Sources */, 392 | 04035982238EAE3300151AC2 /* GHAlibabaSpecificationSelectionBottomView.m in Sources */, 393 | 0403599E238EB3BD00151AC2 /* GHSpecificationSelectionModel.m in Sources */, 394 | 040359B1238EB40000151AC2 /* GHScrollTitles.m in Sources */, 395 | 040359CC2390250800151AC2 /* GHButton.m in Sources */, 396 | 04035989238EAF9000151AC2 /* UIImage+Extension.m in Sources */, 397 | 040FA5C723544A4F001D2877 /* main.m in Sources */, 398 | 040FA62F23599B27001D2877 /* GHHTTPSessionManager.m in Sources */, 399 | 040359B5238EB40000151AC2 /* GHTextField.m in Sources */, 400 | 040359B2238EB40000151AC2 /* GHTableView.m in Sources */, 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | /* End PBXSourcesBuildPhase section */ 405 | 406 | /* Begin PBXVariantGroup section */ 407 | 040FA5BD23544A4E001D2877 /* Main.storyboard */ = { 408 | isa = PBXVariantGroup; 409 | children = ( 410 | 040FA5BE23544A4E001D2877 /* Base */, 411 | ); 412 | name = Main.storyboard; 413 | sourceTree = ""; 414 | }; 415 | 040FA5C223544A4F001D2877 /* LaunchScreen.storyboard */ = { 416 | isa = PBXVariantGroup; 417 | children = ( 418 | 040FA5C323544A4F001D2877 /* Base */, 419 | ); 420 | name = LaunchScreen.storyboard; 421 | sourceTree = ""; 422 | }; 423 | /* End PBXVariantGroup section */ 424 | 425 | /* Begin XCBuildConfiguration section */ 426 | 040FA5C823544A4F001D2877 /* Debug */ = { 427 | isa = XCBuildConfiguration; 428 | buildSettings = { 429 | ALWAYS_SEARCH_USER_PATHS = NO; 430 | CLANG_ANALYZER_NONNULL = YES; 431 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 432 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 433 | CLANG_CXX_LIBRARY = "libc++"; 434 | CLANG_ENABLE_MODULES = YES; 435 | CLANG_ENABLE_OBJC_ARC = YES; 436 | CLANG_ENABLE_OBJC_WEAK = YES; 437 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_COMMA = YES; 440 | CLANG_WARN_CONSTANT_CONVERSION = YES; 441 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 442 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 443 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 444 | CLANG_WARN_EMPTY_BODY = YES; 445 | CLANG_WARN_ENUM_CONVERSION = YES; 446 | CLANG_WARN_INFINITE_RECURSION = YES; 447 | CLANG_WARN_INT_CONVERSION = YES; 448 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 449 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 450 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 451 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 452 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 453 | CLANG_WARN_STRICT_PROTOTYPES = YES; 454 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 455 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 456 | CLANG_WARN_UNREACHABLE_CODE = YES; 457 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 458 | COPY_PHASE_STRIP = NO; 459 | DEBUG_INFORMATION_FORMAT = dwarf; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | ENABLE_TESTABILITY = YES; 462 | GCC_C_LANGUAGE_STANDARD = gnu11; 463 | GCC_DYNAMIC_NO_PIC = NO; 464 | GCC_NO_COMMON_BLOCKS = YES; 465 | GCC_OPTIMIZATION_LEVEL = 0; 466 | GCC_PREPROCESSOR_DEFINITIONS = ( 467 | "DEBUG=1", 468 | "$(inherited)", 469 | ); 470 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 471 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 472 | GCC_WARN_UNDECLARED_SELECTOR = YES; 473 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 474 | GCC_WARN_UNUSED_FUNCTION = YES; 475 | GCC_WARN_UNUSED_VARIABLE = YES; 476 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 477 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 478 | MTL_FAST_MATH = YES; 479 | ONLY_ACTIVE_ARCH = YES; 480 | SDKROOT = iphoneos; 481 | }; 482 | name = Debug; 483 | }; 484 | 040FA5C923544A4F001D2877 /* Release */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | ALWAYS_SEARCH_USER_PATHS = NO; 488 | CLANG_ANALYZER_NONNULL = YES; 489 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_MODULES = YES; 493 | CLANG_ENABLE_OBJC_ARC = YES; 494 | CLANG_ENABLE_OBJC_WEAK = YES; 495 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 496 | CLANG_WARN_BOOL_CONVERSION = YES; 497 | CLANG_WARN_COMMA = YES; 498 | CLANG_WARN_CONSTANT_CONVERSION = YES; 499 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 500 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 501 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 502 | CLANG_WARN_EMPTY_BODY = YES; 503 | CLANG_WARN_ENUM_CONVERSION = YES; 504 | CLANG_WARN_INFINITE_RECURSION = YES; 505 | CLANG_WARN_INT_CONVERSION = YES; 506 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 507 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 508 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 509 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 510 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 511 | CLANG_WARN_STRICT_PROTOTYPES = YES; 512 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 513 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 514 | CLANG_WARN_UNREACHABLE_CODE = YES; 515 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 516 | COPY_PHASE_STRIP = NO; 517 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 518 | ENABLE_NS_ASSERTIONS = NO; 519 | ENABLE_STRICT_OBJC_MSGSEND = YES; 520 | GCC_C_LANGUAGE_STANDARD = gnu11; 521 | GCC_NO_COMMON_BLOCKS = YES; 522 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 523 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 524 | GCC_WARN_UNDECLARED_SELECTOR = YES; 525 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 526 | GCC_WARN_UNUSED_FUNCTION = YES; 527 | GCC_WARN_UNUSED_VARIABLE = YES; 528 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 529 | MTL_ENABLE_DEBUG_INFO = NO; 530 | MTL_FAST_MATH = YES; 531 | SDKROOT = iphoneos; 532 | VALIDATE_PRODUCT = YES; 533 | }; 534 | name = Release; 535 | }; 536 | 040FA5CB23544A4F001D2877 /* Debug */ = { 537 | isa = XCBuildConfiguration; 538 | baseConfigurationReference = EF6CA08E36706B06D4CE6A26 /* Pods-GHAlibabaSpecificationSelectionDemo.debug.xcconfig */; 539 | buildSettings = { 540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 541 | CODE_SIGN_IDENTITY = "Apple Development"; 542 | CODE_SIGN_STYLE = Automatic; 543 | DEVELOPMENT_TEAM = KZ9JB9ZT4S; 544 | GCC_PREFIX_HEADER = GHAlibabaSpecificationSelectionDemo/PrefixHeader.pch; 545 | INFOPLIST_FILE = GHAlibabaSpecificationSelectionDemo/Info.plist; 546 | LD_RUNPATH_SEARCH_PATHS = ( 547 | "$(inherited)", 548 | "@executable_path/Frameworks", 549 | ); 550 | PRODUCT_BUNDLE_IDENTIFIER = macBookPro.GHAlibabaSpecificationSelectionDemo; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | PROVISIONING_PROFILE_SPECIFIER = ""; 553 | TARGETED_DEVICE_FAMILY = 1; 554 | }; 555 | name = Debug; 556 | }; 557 | 040FA5CC23544A4F001D2877 /* Release */ = { 558 | isa = XCBuildConfiguration; 559 | baseConfigurationReference = 1D64B2FE7F97A0941C374FA6 /* Pods-GHAlibabaSpecificationSelectionDemo.release.xcconfig */; 560 | buildSettings = { 561 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 562 | CODE_SIGN_IDENTITY = "Apple Development"; 563 | CODE_SIGN_STYLE = Automatic; 564 | DEVELOPMENT_TEAM = KZ9JB9ZT4S; 565 | GCC_PREFIX_HEADER = GHAlibabaSpecificationSelectionDemo/PrefixHeader.pch; 566 | INFOPLIST_FILE = GHAlibabaSpecificationSelectionDemo/Info.plist; 567 | LD_RUNPATH_SEARCH_PATHS = ( 568 | "$(inherited)", 569 | "@executable_path/Frameworks", 570 | ); 571 | PRODUCT_BUNDLE_IDENTIFIER = macBookPro.GHAlibabaSpecificationSelectionDemo; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | PROVISIONING_PROFILE_SPECIFIER = ""; 574 | TARGETED_DEVICE_FAMILY = 1; 575 | }; 576 | name = Release; 577 | }; 578 | /* End XCBuildConfiguration section */ 579 | 580 | /* Begin XCConfigurationList section */ 581 | 040FA5AC23544A4E001D2877 /* Build configuration list for PBXProject "GHAlibabaSpecificationSelectionDemo" */ = { 582 | isa = XCConfigurationList; 583 | buildConfigurations = ( 584 | 040FA5C823544A4F001D2877 /* Debug */, 585 | 040FA5C923544A4F001D2877 /* Release */, 586 | ); 587 | defaultConfigurationIsVisible = 0; 588 | defaultConfigurationName = Release; 589 | }; 590 | 040FA5CA23544A4F001D2877 /* Build configuration list for PBXNativeTarget "GHAlibabaSpecificationSelectionDemo" */ = { 591 | isa = XCConfigurationList; 592 | buildConfigurations = ( 593 | 040FA5CB23544A4F001D2877 /* Debug */, 594 | 040FA5CC23544A4F001D2877 /* Release */, 595 | ); 596 | defaultConfigurationIsVisible = 0; 597 | defaultConfigurationName = Release; 598 | }; 599 | /* End XCConfigurationList section */ 600 | }; 601 | rootObject = 040FA5A923544A4E001D2877 /* Project object */; 602 | } 603 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcodeproj/xcuserdata/mac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | GHAlibabaSpecificationSelectionDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 15 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo.xcworkspace/xcuserdata/mac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 16 | 17 | 18 | 20 | 32 | 33 | 34 | 36 | 48 | 49 | 50 | 52 | 64 | 65 | 66 | 68 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/.DS_Store -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 18 | if (@available(iOS 11.0, *)) { 19 | [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; 20 | } 21 | return YES; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "size": "20x20", 5 | "idiom": "iphone", 6 | "filename": "icon-20@2x.png", 7 | "scale": "2x" 8 | }, 9 | { 10 | "size": "20x20", 11 | "idiom": "iphone", 12 | "filename": "icon-20@3x.png", 13 | "scale": "3x" 14 | }, 15 | { 16 | "size": "29x29", 17 | "idiom": "iphone", 18 | "filename": "icon-29.png", 19 | "scale": "1x" 20 | }, 21 | { 22 | "size": "29x29", 23 | "idiom": "iphone", 24 | "filename": "icon-29@2x.png", 25 | "scale": "2x" 26 | }, 27 | { 28 | "size": "29x29", 29 | "idiom": "iphone", 30 | "filename": "icon-29@3x.png", 31 | "scale": "3x" 32 | }, 33 | { 34 | "size": "40x40", 35 | "idiom": "iphone", 36 | "filename": "icon-40@2x.png", 37 | "scale": "2x" 38 | }, 39 | { 40 | "size": "40x40", 41 | "idiom": "iphone", 42 | "filename": "icon-40@3x.png", 43 | "scale": "3x" 44 | }, 45 | { 46 | "size": "60x60", 47 | "idiom": "iphone", 48 | "filename": "icon-60@2x.png", 49 | "scale": "2x" 50 | }, 51 | { 52 | "size": "60x60", 53 | "idiom": "iphone", 54 | "filename": "icon-60@3x.png", 55 | "scale": "3x" 56 | }, 57 | { 58 | "size": "20x20", 59 | "idiom": "ipad", 60 | "filename": "icon-20-ipad.png", 61 | "scale": "1x" 62 | }, 63 | { 64 | "size": "20x20", 65 | "idiom": "ipad", 66 | "filename": "icon-20@2x-ipad.png", 67 | "scale": "2x" 68 | }, 69 | { 70 | "size": "29x29", 71 | "idiom": "ipad", 72 | "filename": "icon-29-ipad.png", 73 | "scale": "1x" 74 | }, 75 | { 76 | "size": "29x29", 77 | "idiom": "ipad", 78 | "filename": "icon-29@2x-ipad.png", 79 | "scale": "2x" 80 | }, 81 | { 82 | "size": "40x40", 83 | "idiom": "ipad", 84 | "filename": "icon-40.png", 85 | "scale": "1x" 86 | }, 87 | { 88 | "size": "40x40", 89 | "idiom": "ipad", 90 | "filename": "icon-40@2x.png", 91 | "scale": "2x" 92 | }, 93 | { 94 | "size": "76x76", 95 | "idiom": "ipad", 96 | "filename": "icon-76.png", 97 | "scale": "1x" 98 | }, 99 | { 100 | "size": "76x76", 101 | "idiom": "ipad", 102 | "filename": "icon-76@2x.png", 103 | "scale": "2x" 104 | }, 105 | { 106 | "size": "83.5x83.5", 107 | "idiom": "ipad", 108 | "filename": "icon-83.5@2x.png", 109 | "scale": "2x" 110 | }, 111 | { 112 | "size": "1024x1024", 113 | "idiom": "ios-marketing", 114 | "filename": "icon-1024.png", 115 | "scale": "1x" 116 | } 117 | ], 118 | "info": { 119 | "version": 1, 120 | "author": "icon.wuruihong.com" 121 | } 122 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-1024.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "close.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/close.imageset/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/close.imageset/close.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/emptyPage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "emptyPage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/emptyPage.imageset/emptyPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/emptyPage.imageset/emptyPage.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/home.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "home.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/home.imageset/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/home.imageset/home.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/leftArrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "leftArrow.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/leftArrow.imageset/leftArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/leftArrow.imageset/leftArrow.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/logo1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "logo1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/logo1.imageset/logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/logo1.imageset/logo1.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/rightArrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "rightArrow.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/rightArrow.imageset/rightArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/rightArrow.imageset/rightArrow.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/shopCar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "shopCar.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Assets.xcassets/shopCar.imageset/shopCar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/Assets.xcassets/shopCar.imageset/shopCar.png -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/.DS_Store -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/NSString+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Extension.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface NSString (Extension) 16 | 17 | + (CGSize)sizeWithText:(NSString *)text andFont:(UIFont *)font andMaxSize:(CGSize)maxSize; 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/NSString+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Extension.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "NSString+Extension.h" 10 | 11 | 12 | @implementation NSString (Extension) 13 | 14 | + (CGSize)sizeWithText:(NSString *)text andFont:(UIFont *)font andMaxSize:(CGSize)maxSize { 15 | CGSize expectedLabelSize = CGSizeZero; 16 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 17 | paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; 18 | [paragraphStyle setLineSpacing:0]; 19 | NSDictionary *attributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName:paragraphStyle.copy}; 20 | paragraphStyle.alignment = NSTextAlignmentJustified; 21 | paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping; 22 | expectedLabelSize = [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil].size; 23 | return CGSizeMake(ceil(expectedLabelSize.width), ceil(expectedLabelSize.height)); 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIButton+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Extension.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIButton (Extension) 15 | 16 | - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state; 17 | 18 | 19 | #pragma mark - Runtime解决UIButton重复点击问题 20 | 21 | /** 22 | 23 | * 点击事件的事件间隔 24 | */ 25 | @property (nonatomic, assign) NSTimeInterval acceptEventInterval; 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIButton+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Extension.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "UIButton+Extension.h" 10 | #import "UIImage+Extension.h" 11 | #import 12 | @interface UIControl() 13 | 14 | @property (nonatomic, assign) NSTimeInterval acceptEventTime; 15 | 16 | @end 17 | @implementation UIButton (Extension) 18 | 19 | static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval"; 20 | static const char *UIControl_acceptEventTime = "UIControl_acceptEventTime"; 21 | 22 | - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state { 23 | [self setBackgroundImage:[UIImage imageWithColor:backgroundColor] forState:state]; 24 | } 25 | 26 | + (UIImage *)imageWithColor:(UIColor *)color 27 | { 28 | CGRect rect = CGRectMake(0, 0, 1, 1); 29 | UIGraphicsBeginImageContext(rect.size); 30 | CGContextRef context = UIGraphicsGetCurrentContext(); 31 | 32 | CGContextSetFillColorWithColor(context, [color CGColor]); 33 | CGContextFillRect(context, rect); 34 | 35 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 36 | UIGraphicsEndImageContext(); 37 | 38 | return image; 39 | } 40 | 41 | #pragma mark - Runtime解决UIButton重复点击问题 42 | 43 | - (NSTimeInterval)acceptEventInterval{ 44 | return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue]; 45 | } 46 | 47 | - (void)setAcceptEventInterval:(NSTimeInterval)acceptEventInterval{ 48 | objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 49 | } 50 | 51 | - (NSTimeInterval)acceptEventTime{ 52 | return [objc_getAssociatedObject(self, UIControl_acceptEventTime) doubleValue]; 53 | } 54 | 55 | - (void)setAcceptEventTime:(NSTimeInterval)acceptEventTime{ 56 | objc_setAssociatedObject(self, UIControl_acceptEventTime, @(acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 57 | } 58 | 59 | + (void)load{ 60 | //获取着两个方法 61 | Method systemMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:)); 62 | SEL sysSEL = @selector(sendAction:to:forEvent:); 63 | 64 | Method myMethod = class_getInstanceMethod(self, @selector(cjr_sendAction:to:forEvent:)); 65 | SEL mySEL = @selector(cjr_sendAction:to:forEvent:); 66 | 67 | //添加方法进去 68 | BOOL didAddMethod = class_addMethod(self, sysSEL, method_getImplementation(myMethod), method_getTypeEncoding(myMethod)); 69 | 70 | //如果方法已经存在了 71 | if (didAddMethod) { 72 | class_replaceMethod(self, mySEL, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod)); 73 | }else{ 74 | method_exchangeImplementations(systemMethod, myMethod); 75 | } 76 | 77 | //----------------以上主要是实现两个方法的互换,load是gcd的只shareinstance,果断保证执行一次 78 | } 79 | 80 | - (void)cjr_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ 81 | if([NSStringFromClass(self.class)isEqualToString:@"UIButton"]) { 82 | self.acceptEventInterval = (!self.acceptEventInterval || self.acceptEventInterval == 0) ? 0.001 : self.acceptEventInterval; 83 | if (NSDate.date.timeIntervalSince1970 - self.acceptEventTime < self.acceptEventInterval) { 84 | return; 85 | 86 | } } 87 | 88 | if (self.acceptEventInterval > 0) { 89 | self.acceptEventTime = NSDate.date.timeIntervalSince1970; 90 | } 91 | 92 | [self cjr_sendAction:action to:target forEvent:event]; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIImage+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Extension.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (Extension) 15 | 16 | + (UIImage *)imageWithColor:(UIColor *)color; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIImage+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Extension.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Extension.h" 10 | 11 | 12 | @implementation UIImage (Extension) 13 | 14 | + (UIImage *)imageWithColor:(UIColor *)color { 15 | CGRect rect = CGRectMake(0, 0, 1, 1); 16 | UIGraphicsBeginImageContext(rect.size); 17 | CGContextRef context = UIGraphicsGetCurrentContext(); 18 | 19 | CGContextSetFillColorWithColor(context, [color CGColor]); 20 | CGContextFillRect(context, rect); 21 | 22 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 23 | UIGraphicsEndImageContext(); 24 | 25 | return image; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIImage+ViewToImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ViewToImage.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/28. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (ViewToImage) 15 | 16 | + (UIImage *)imageWithFrame:(CGRect)frame backGroundColor:(UIColor *)backGroundColor text:(NSString *)text textColor:(UIColor *)textColor textFontOfSize:(CGFloat)size; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIImage+ViewToImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ViewToImage.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/28. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "UIImage+ViewToImage.h" 10 | 11 | @implementation UIImage (ViewToImage) 12 | 13 | + (UIImage *)imageWithFrame:(CGRect)frame backGroundColor:(UIColor *)backGroundColor text:(NSString *)text textColor:(UIColor *)textColor textFontOfSize:(CGFloat)size { 14 | UIView *backView = [[UIView alloc] initWithFrame:frame]; 15 | backView.layer.masksToBounds = YES; 16 | backView.layer.cornerRadius = 5; 17 | backView.backgroundColor = backGroundColor; 18 | UILabel *label = [[UILabel alloc] initWithFrame:frame]; 19 | label.text = text; 20 | label.textColor = textColor; 21 | label.backgroundColor = backGroundColor; 22 | label.textAlignment = 1; 23 | label.font = [UIFont systemFontOfSize:size]; 24 | [backView addSubview:label]; 25 | UIGraphicsBeginImageContextWithOptions(backView.bounds.size,NO, 0.0); 26 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 27 | [backView.layer renderInContext:ctx]; 28 | UIImage* tImage = UIGraphicsGetImageFromCurrentImageContext(); 29 | UIGraphicsEndImageContext(); 30 | return tImage; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIView+ActivityIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ActivityIndicator.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/28. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIView (ActivityIndicator) 15 | 16 | - (void)addActivityIndicator; 17 | 18 | - (void)gh_startAnimating; 19 | 20 | - (void)gh_stopAnimating; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIView+ActivityIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ActivityIndicator.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/28. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "UIView+ActivityIndicator.h" 10 | #import 11 | 12 | static NSString *activityIndicatorKey = @"activityIndicatorKey"; 13 | 14 | @implementation UIView (ActivityIndicator) 15 | 16 | - (void)addActivityIndicator { 17 | UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; 18 | CGPoint point = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5); 19 | [activity setCenter:point]; 20 | [activity setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge]; 21 | [self addSubview:activity]; 22 | objc_setAssociatedObject(self, &activityIndicatorKey, activity, OBJC_ASSOCIATION_RETAIN); 23 | } 24 | 25 | - (void)gh_startAnimating { 26 | UIActivityIndicatorView *activity = objc_getAssociatedObject(self, & activityIndicatorKey); 27 | [activity startAnimating]; 28 | } 29 | 30 | - (void)gh_stopAnimating { 31 | UIActivityIndicatorView *activity = objc_getAssociatedObject(self, & activityIndicatorKey); 32 | [activity stopAnimating]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIView+EmptyPage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+EmptyPage.h 3 | // GHEmptyPage 4 | // 5 | // Created by mac on 2019/11/29. 6 | // Copyright © 2019 Yeetied. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | typedef void (^EmptyPageDidClickReloadBlock)(void); 15 | 16 | @interface UIView (EmptyPage) 17 | 18 | - (void)hideEmptyPage ; 19 | 20 | - (void)showEmptyPage:(CGFloat)y imageName:(NSString *)imageName imageFrame:(CGRect)imageFrame didClickReloadBlock:(EmptyPageDidClickReloadBlock)didClickReloadBlock; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIView+EmptyPage.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+EmptyPage.m 3 | // GHEmptyPage 4 | // 5 | // Created by mac on 2019/11/29. 6 | // Copyright © 2019 Yeetied. All rights reserved. 7 | // 8 | 9 | #import "UIView+EmptyPage.h" 10 | #import 11 | 12 | @interface UIView() 13 | @property (nonatomic , copy) EmptyPageDidClickReloadBlock didClickReloadBlock; 14 | 15 | @end 16 | 17 | @implementation UIView (EmptyPage) 18 | 19 | 20 | static NSString *emptyPageDidClickReloadBlockKey = @"emptyPageDidClickReloadBlockKey"; 21 | 22 | - (void)hideEmptyPage { 23 | for (UIView *view in self.subviews) { 24 | if (view.tag == 10 || view.tag == 20|| view.tag ==30) { 25 | [view removeFromSuperview]; 26 | } 27 | } 28 | } 29 | 30 | - (EmptyPageDidClickReloadBlock)didClickReloadBlock { 31 | return objc_getAssociatedObject(self, &emptyPageDidClickReloadBlockKey); 32 | } 33 | 34 | - (void)setDidClickReloadBlock:(EmptyPageDidClickReloadBlock)didClickReloadBlock { 35 | objc_setAssociatedObject(self, &emptyPageDidClickReloadBlockKey, didClickReloadBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 36 | } 37 | 38 | - (void)showEmptyPage:(CGFloat)y imageName:(NSString *)imageName imageFrame:(CGRect)imageFrame didClickReloadBlock:(EmptyPageDidClickReloadBlock)didClickReloadBlock{ 39 | UIView *backView = [[UIView alloc]init]; 40 | backView.tag = 10; 41 | backView.backgroundColor = [UIColor whiteColor]; 42 | backView.frame = CGRectMake(0, y, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - y); 43 | [self addSubview:backView]; 44 | UIImageView *imageView = [[UIImageView alloc]initWithFrame:imageFrame]; 45 | imageView.image = [UIImage imageNamed:imageName]; 46 | imageView.contentMode = UIViewContentModeScaleAspectFill; 47 | imageView.tag = 20; 48 | UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(CGRectGetMinX(imageView.frame), CGRectGetMaxY(imageView.frame) + 10, imageFrame.size.width, 30)]; 49 | [button setTitle:@"点击重试" forState:UIControlStateNormal]; 50 | button.tag = 30; 51 | button.titleLabel.font = [UIFont systemFontOfSize:12]; 52 | [button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal]; 53 | [button addTarget:self action:@selector(clickButton) forControlEvents:UIControlEventTouchUpInside]; 54 | [backView addSubview:button]; 55 | self.didClickReloadBlock = didClickReloadBlock; 56 | [backView addSubview:imageView]; 57 | } 58 | 59 | - (void)clickButton { 60 | if (self.didClickReloadBlock) { 61 | self.didClickReloadBlock(); 62 | } 63 | } 64 | 65 | @end 66 | 67 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIView+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+GH.h 3 | // DanHa 4 | // 5 | // Created by GHome on 2017/11/8. 6 | // Copyright © 2017年 www.danxia.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Extension) 12 | 13 | - (CGFloat)x; 14 | - (CGFloat)y; 15 | - (CGFloat)width; 16 | - (CGFloat)height; 17 | - (CGSize)size; 18 | 19 | - (void)setX:(CGFloat)x; 20 | - (void)setY:(CGFloat)y; 21 | - (void)setWidth:(CGFloat)width; 22 | - (void)setHeight:(CGFloat)height; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Category/UIView+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+GH.m 3 | // DanHa 4 | // 5 | // Created by GHome on 2017/11/8. 6 | // Copyright © 2017年 www.danxia.com. All rights reserved. 7 | // 8 | 9 | #import "UIView+Extension.h" 10 | 11 | @implementation UIView (Extension) 12 | 13 | - (CGFloat)x { 14 | return self.frame.origin.x; 15 | } 16 | - (CGFloat)y { 17 | return self.frame.origin.y; 18 | } 19 | - (CGFloat)width { 20 | return self.frame.size.width; 21 | } 22 | - (CGFloat)height { 23 | return self.frame.size.height; 24 | } 25 | 26 | - (void)setX:(CGFloat)x { 27 | CGRect newFrame = self.frame; 28 | newFrame.origin.x = x; 29 | self.frame = newFrame; 30 | } 31 | - (void)setY:(CGFloat)y { 32 | CGRect newFrame = self.frame; 33 | newFrame.origin.y = y; 34 | self.frame = newFrame; 35 | } 36 | - (void)setWidth:(CGFloat)width { 37 | CGRect newFrame = self.frame; 38 | newFrame.size.width = width; 39 | self.frame = newFrame; 40 | } 41 | - (void)setHeight:(CGFloat)height { 42 | CGRect newFrame = self.frame; 43 | newFrame.size.height = height; 44 | self.frame = newFrame; 45 | } 46 | - (CGSize)size { 47 | return self.frame.size; 48 | } 49 | @end 50 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionBaseModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionBaseModel.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/29. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSObject+YYModel.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface GHSpecificationSelectionBaseModel : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionBaseModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionBaseModel.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/29. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionBaseModel.h" 10 | 11 | @implementation GHSpecificationSelectionBaseModel 12 | 13 | - (void)encodeWithCoder:(NSCoder *)aCoder { 14 | [self yy_modelEncodeWithCoder:aCoder]; 15 | } 16 | 17 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 18 | self = [super init]; 19 | return [self yy_modelInitWithCoder:aDecoder]; 20 | } 21 | 22 | - (instancetype)copyWithZone:(NSZone *)zone { 23 | return [self yy_modelCopy]; 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionImageModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionImageModel.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/18. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionBaseModel.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHSpecificationSelectionImageModel : GHSpecificationSelectionBaseModel 14 | 15 | @property (nonatomic , copy) NSString *spu_code; 16 | 17 | @property (nonatomic , copy) NSString *img_id; 18 | 19 | @property (nonatomic , copy) NSString *last_modified_by; 20 | 21 | @property (nonatomic , copy) NSString *img_sort; 22 | 23 | @property (nonatomic , copy) NSString *status; 24 | 25 | @property (nonatomic , copy) NSString *sku_code; 26 | 27 | @property (nonatomic , copy) NSString *img_name; 28 | 29 | @property (nonatomic , copy) NSString *sku_id; 30 | 31 | @property (nonatomic , copy) NSString *img_url; 32 | 33 | @property (nonatomic , copy) NSString *img_code; 34 | 35 | @property (nonatomic , copy) NSString *creation_date; 36 | 37 | @property (nonatomic , copy) NSString *creation_by; 38 | 39 | @property (nonatomic , copy) NSString *sku_img_id; 40 | 41 | @property (nonatomic , copy) NSString *img_type; 42 | 43 | @property (nonatomic , copy) NSString *last_modified_date; 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionImageModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionImageModel.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/18. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionImageModel.h" 10 | 11 | @implementation GHSpecificationSelectionImageModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionModel.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/18. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionBaseModel.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHSpecificationSelectionModel : GHSpecificationSelectionBaseModel 14 | 15 | @property (nonatomic , copy) NSString *sku_id; 16 | 17 | @property (nonatomic , copy) NSString *arrival_cycle; 18 | 19 | @property (nonatomic , copy) NSString *sku_code; 20 | 21 | @property (nonatomic , copy) NSString *order_limit_type; 22 | 23 | @property (nonatomic , copy) NSString *sku_name; 24 | 25 | @property (nonatomic , copy) NSString *mini_order; 26 | 27 | @property (nonatomic , copy) NSString *virtual_stock; 28 | 29 | @property (nonatomic , copy) NSString *sale_price; 30 | 31 | @property (nonatomic , strong) NSArray *images; 32 | 33 | @property (nonatomic , copy) NSString *specifications; 34 | 35 | @property (nonatomic , copy) NSString *actual_stock; 36 | 37 | @property (nonatomic , copy) NSString *color; 38 | 39 | @property (nonatomic , copy) NSString *unit; 40 | 41 | @property (nonatomic , copy) NSString *count; 42 | 43 | /** 44 | * 0 = 无活动 1 特价 2 满减 45 | */ 46 | @property (nonatomic , copy) NSString *activityType; 47 | 48 | @property (nonatomic, copy) NSString *activity_price; 49 | 50 | @end 51 | 52 | NS_ASSUME_NONNULL_END 53 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionModel.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/18. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionModel.h" 10 | 11 | @implementation GHSpecificationSelectionModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionTitleModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionTitleModel.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionBaseModel.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHSpecificationSelectionTitleModel : GHSpecificationSelectionBaseModel 14 | 15 | /** 16 | * 颜色 17 | */ 18 | @property (nonatomic ,copy) NSString *color; 19 | 20 | /** 21 | * XFSGoodDetailsSkuModel集合 22 | */ 23 | @property (nonatomic ,strong) NSArray *skuList; 24 | 25 | /** 26 | * 当前颜色规格够买数量 27 | */ 28 | @property (nonatomic ,copy) NSString *count; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Model/GHSpecificationSelectionTitleModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHSpecificationSelectionTitleModel.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHSpecificationSelectionTitleModel.h" 10 | 11 | @implementation GHSpecificationSelectionTitleModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Tool/ToastTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // ToastTool.h 3 | // SmartOffice 4 | // 5 | // Created by zhaozhiwei on 2019/9/5. 6 | // Copyright © 2019年 Phil Mansfield. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef void(^ToastToolCompleteBlock)(void); 14 | @interface ToastTool : NSObject 15 | 16 | /** 17 | * 单例 18 | * 19 | * @return 返回该对象 20 | */ 21 | + (instancetype)share; 22 | 23 | 24 | 25 | #pragma mark - MBProgressHUD相关 26 | 27 | /** 28 | * 加载显示菊花 29 | * 30 | * @param title 显示的title 31 | * @param inView 菊花所放置的view 32 | * @param isPenetration 菊花所放置的view是否可穿透, YES:可穿透,NO:不可穿透 33 | */ 34 | -(void)showHUDWithTitle:(NSString *)title 35 | inView:(UIView *)inView 36 | isPenetration:(BOOL)isPenetration; 37 | 38 | /** 39 | * 加载显示菊花[默认不可穿透] 40 | * 41 | * @param title 显示的title 42 | * @param inView 菊花所放置的view 43 | */ 44 | -(void)showHUDWithTitle:(NSString *)title 45 | inView:(UIView *)inView; 46 | 47 | /** 48 | * 隐藏菊花 49 | */ 50 | -(void)hide; 51 | 52 | /** 53 | * 延迟隐藏菊花 54 | * 55 | * @param delay 延迟时间 56 | */ 57 | - (void)hideAfterDelay:(NSTimeInterval)delay; 58 | 59 | 60 | #pragma mark - Toast相关 61 | + (void)makeToast:(NSString *)message targetView:(UIView *)targetView delay: (NSTimeInterval)delay; 62 | /** 显示Toast+message */ 63 | + (void)makeToast:(NSString *)message targetView:(UIView *)targetView; 64 | 65 | + (void)makeToast:(NSString *)message targetView:(UIView *)targetView toastToolCompleteBlock:(ToastToolCompleteBlock)toastToolCompleteBlock; 66 | 67 | /** 隐藏Toast */ 68 | + (void)hideToast:(UIView *)targetView; 69 | /** 指示器Toast */ 70 | + (void)makeToastActivity:(UIView *)targetView; 71 | /** 隐藏指示器Toast */ 72 | + (void)hideToastActivity:(UIView *)targetView; 73 | 74 | /** 指示器Toast */ 75 | + (void)makeToastActivity:(UIView *)targetView toastToolCompleteBlock: (ToastToolCompleteBlock)toastToolCompleteBlock; 76 | 77 | @end 78 | 79 | NS_ASSUME_NONNULL_END 80 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/Tool/ToastTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // ToastTool.m 3 | // SmartOffice 4 | // 5 | // Created by zhaozhiwei on 2019/9/5. 6 | // Copyright © 2019年 Phil Mansfield. All rights reserved. 7 | // 8 | 9 | #import "ToastTool.h" 10 | #import "MBProgressHUD.h" 11 | #define kKeyWindow [UIApplication sharedApplication].keyWindow 12 | 13 | 14 | @interface ToastTool() { 15 | __weak UIView *_inView; 16 | } 17 | 18 | @property (nonatomic,strong) MBProgressHUD *mBProgressHUD; 19 | 20 | @end 21 | @implementation ToastTool 22 | 23 | #ifndef dispatch_main_async_safe 24 | #define dispatch_main_async_safe(block)\ 25 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\ 26 | block();\ 27 | } else {\ 28 | dispatch_async(dispatch_get_main_queue(), block);\ 29 | } 30 | #endif 31 | 32 | + (instancetype)share{ 33 | static dispatch_once_t t; 34 | static ToastTool *manager = nil; 35 | dispatch_once(&t, ^{ 36 | manager = [[ToastTool alloc] init]; 37 | }); 38 | return manager; 39 | } 40 | 41 | 42 | 43 | #pragma mark - MBProgressHUD相关 44 | 45 | - (void)showHUDWithTitle:(NSString *)title 46 | inView:(UIView *)inView 47 | isPenetration:(BOOL)isPenetration{ 48 | if (_mBProgressHUD) { 49 | [self hide]; 50 | _mBProgressHUD = nil; 51 | } 52 | _inView = inView; 53 | UIView *baseView = nil; 54 | if (_inView) { 55 | baseView = _inView; 56 | } 57 | else{ 58 | baseView = kKeyWindow; 59 | } 60 | 61 | _mBProgressHUD = [[MBProgressHUD alloc] initWithView:baseView]; 62 | _mBProgressHUD.labelText = title; 63 | _mBProgressHUD.userInteractionEnabled = !isPenetration; 64 | _mBProgressHUD.removeFromSuperViewOnHide = YES; 65 | _mBProgressHUD.cornerRadius = 5.0; 66 | _mBProgressHUD.color = [UIColor colorWithWhite:0.0 alpha:0.75]; 67 | _inView = inView; 68 | [baseView addSubview:_mBProgressHUD]; 69 | [self show]; 70 | } 71 | 72 | -(void)showHUDWithTitle:(NSString *)title 73 | inView:(UIView *)inView 74 | { 75 | [self showHUDWithTitle:title inView:inView isPenetration:NO]; 76 | } 77 | 78 | -(void)show{ 79 | [kKeyWindow bringSubviewToFront:_mBProgressHUD]; 80 | [_mBProgressHUD show:YES]; 81 | } 82 | 83 | -(void)hide{ 84 | if (_inView) { 85 | _inView.userInteractionEnabled = YES; 86 | } 87 | dispatch_main_async_safe(^{ 88 | [self->_mBProgressHUD hide:YES]; 89 | }); 90 | } 91 | 92 | - (void)hideAfterDelay:(NSTimeInterval)delay{ 93 | [self performSelector:@selector(hide) withObject:nil afterDelay:delay]; 94 | } 95 | 96 | 97 | 98 | #pragma mark - Toast相关 99 | 100 | + (void)makeToast:(NSString *)message targetView:(UIView *)targetView delay: (NSTimeInterval)delay { 101 | 102 | if (targetView == nil) targetView = [[UIApplication sharedApplication].windows lastObject]; 103 | //每次显示前先隐藏 104 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 105 | // 快速显示一个提示信息 106 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:targetView animated:YES]; 107 | hud.mode = MBProgressHUDModeText; 108 | hud.detailsLabelText = message; 109 | hud.alpha = 0.7; 110 | // 隐藏时候从父控件中移除 111 | hud.removeFromSuperViewOnHide = YES; 112 | // 2秒之后再消失 113 | [hud hide:YES afterDelay:delay]; 114 | } 115 | 116 | + (void)makeToast:(NSString *)message targetView:(UIView *)targetView { 117 | 118 | if (targetView == nil) targetView = [[UIApplication sharedApplication].windows lastObject]; 119 | //每次显示前先隐藏 120 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 121 | // 快速显示一个提示信息 122 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:targetView animated:YES]; 123 | hud.mode = MBProgressHUDModeText; 124 | hud.detailsLabelText = message; 125 | hud.alpha = 0.7; 126 | // 隐藏时候从父控件中移除 127 | hud.removeFromSuperViewOnHide = YES; 128 | // 2秒之后再消失 129 | [hud hide:YES afterDelay:1.5]; 130 | } 131 | 132 | + (void)makeToast:(NSString *)message targetView:(UIView *)targetView toastToolCompleteBlock:(ToastToolCompleteBlock)toastToolCompleteBlock { 133 | 134 | if (targetView == nil) targetView = [[UIApplication sharedApplication].windows lastObject]; 135 | //每次显示前先隐藏 136 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 137 | // 快速显示一个提示信息 138 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:targetView animated:YES]; 139 | hud.mode = MBProgressHUDModeText; 140 | hud.detailsLabelText = message; 141 | hud.detailsLabelFont = [UIFont systemFontOfSize:18]; 142 | hud.alpha = 0.7; 143 | // 隐藏时候从父控件中移除 144 | hud.removeFromSuperViewOnHide = YES; 145 | [hud hide:YES afterDelay:1]; 146 | hud.completionBlock = ^{ 147 | if (toastToolCompleteBlock) { 148 | toastToolCompleteBlock(); 149 | } 150 | }; 151 | } 152 | 153 | + (void)hideToast:(UIView *)targetView { 154 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 155 | } 156 | 157 | + (void)makeToastActivity:(UIView *)targetView { 158 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 159 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:targetView animated:YES]; 160 | hud.mode = MBProgressHUDModeIndeterminate; 161 | hud.alpha = 0.7; 162 | hud.removeFromSuperViewOnHide = YES; 163 | } 164 | 165 | + (void)makeToastActivity:(UIView *)targetView toastToolCompleteBlock: (ToastToolCompleteBlock)toastToolCompleteBlock { 166 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 167 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:targetView animated:YES]; 168 | hud.mode = MBProgressHUDModeIndeterminate; 169 | hud.alpha = 0.7; 170 | hud.removeFromSuperViewOnHide = YES; 171 | [hud hide:YES afterDelay:1]; 172 | hud.completionBlock = ^{ 173 | if (toastToolCompleteBlock) { 174 | toastToolCompleteBlock(); 175 | } 176 | }; 177 | } 178 | 179 | + (void)hideToastActivity:(UIView *)targetView { 180 | [MBProgressHUD hideHUDForView:targetView animated:YES]; 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHAlibabaSpecificationSelection.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHAlibabaSpecificationSelection.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHPopView.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef void (^GHAlibabaSpecificationSelectionGetDataBlock)(NSArray *dataArray); 14 | 15 | @interface GHAlibabaSpecificationSelection : GHPopView 16 | 17 | /** 18 | * 数据源 19 | * @param skuList 装skuModel数组 20 | * @param colors 颜色数组 21 | * @param sectePrice 价格区间字典 22 | */ 23 | - (void)setSkuList:(NSArray *)skuList colors:(NSArray *)colors sectePrice:(NSDictionary *)sectePrice; 24 | 25 | @property (nonatomic , copy) GHAlibabaSpecificationSelectionGetDataBlock getDataBlock; 26 | 27 | /** 28 | * 重置数据 29 | */ 30 | - (void)resetData; 31 | 32 | @property (nonatomic , assign) CGRect shopCarRect; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHAlibabaSpecificationSelection.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHAlibabaSpecificationSelection.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHAlibabaSpecificationSelection.h" 10 | #import "GHScrollTitles.h" 11 | #import "GHTableView.h" 12 | #import "GHSpecificationSelectionModel.h" 13 | #import "UIImageView+WebCache.h" 14 | #import "GHSpecificationSelectionImageModel.h" 15 | #import "GHSpecificationSelectionTitleModel.h" 16 | #import "GHTextField.h" 17 | #import "NSString+Extension.h" 18 | #import "GHAlibabaSpecificationSelectionBottomView.h" 19 | #import "UIView+ActivityIndicator.h" 20 | #import "UIImage+ViewToImage.h" 21 | 22 | typedef void (^GHSpecificationSelectionCellCountBlock)(GHSpecificationSelectionModel *skuModel); 23 | 24 | @interface GHSpecificationSelectionCell : UITableViewCell 25 | 26 | + (CGFloat)getCellHeightWithSkuModel:(GHSpecificationSelectionModel *)skuModel; 27 | 28 | @property (nonatomic , strong) GHSpecificationSelectionModel *skuModel; 29 | 30 | /** 31 | * skuName 32 | */ 33 | @property (nonatomic , strong) UILabel *skuName; 34 | 35 | /** 36 | * skuCode 37 | */ 38 | @property (nonatomic , strong) UILabel *skuCode; 39 | 40 | /** 41 | * 价格 42 | */ 43 | @property (nonatomic , strong) UILabel *price; 44 | 45 | /** 46 | * 预计出货日 47 | */ 48 | @property (nonatomic , strong) UILabel *estimatedDate; 49 | 50 | /** 51 | * 计数控件 52 | */ 53 | @property (nonatomic , strong) GHTextField *countField; 54 | 55 | /** 56 | 库存不足 57 | */ 58 | @property (nonatomic , strong) UILabel *inventory; 59 | 60 | @property (nonatomic , strong) UIView *line; 61 | 62 | @property (nonatomic , copy) GHSpecificationSelectionCellCountBlock countBlock; 63 | 64 | @end 65 | 66 | @implementation GHSpecificationSelectionCell 67 | 68 | - (void)setSkuModel:(GHSpecificationSelectionModel *)skuModel { 69 | _skuModel = skuModel; 70 | self.skuName.attributedText = [self getRealString:skuModel]; 71 | if ([skuModel.activityType isEqualToString:@"1"]) { 72 | NSString *price = [NSString stringWithFormat:@"¥%.2f",skuModel.sale_price.doubleValue];; 73 | NSString *activity_price = [NSString stringWithFormat:@"¥%.2f",skuModel.activity_price.doubleValue]; 74 | NSMutableAttributedString *att = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@",activity_price,price]]; 75 | [att addAttributes:@{NSForegroundColorAttributeName:KMainColor} range:NSMakeRange(0, activity_price.length)]; 76 | [att addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x999999),NSStrikethroughStyleAttributeName: @(1),NSBaselineOffsetAttributeName : @(NSUnderlineStyleSingle)} range:NSMakeRange(activity_price.length + 1, price.length)]; 77 | self.price.attributedText = att; 78 | } else { 79 | self.price.text = [NSString stringWithFormat:@"¥%@",skuModel.sale_price]; 80 | } 81 | self.skuCode.text = [NSString stringWithFormat:@"商品编码:%@",skuModel.sku_code]; 82 | NSString *estimatedDate = @""; 83 | if (skuModel.count.integerValue <= skuModel.actual_stock.integerValue && skuModel.actual_stock.integerValue > 0) { 84 | estimatedDate = @"1天"; 85 | } else { 86 | estimatedDate = [NSString stringWithFormat:@"%ld天",skuModel.arrival_cycle.integerValue + 1]; 87 | } 88 | self.estimatedDate.text = [NSString stringWithFormat:@"预计出货日:%@",estimatedDate]; 89 | self.countField.maxCount = skuModel.actual_stock.integerValue + skuModel.virtual_stock.integerValue; 90 | self.countField.minCount = 0; 91 | self.countField.count = skuModel.count.integerValue; 92 | self.countField.miniOrder = skuModel.mini_order.integerValue; 93 | 94 | if ([skuModel.order_limit_type isEqualToString:@"0"]) { 95 | self.countField.miniOrderType = GHCountFieldMiniOrderTypeMultiple; 96 | } else { 97 | self.countField.miniOrderType = GHCountFieldMiniOrderTypeStep; 98 | } 99 | [self actionControlState]; 100 | } 101 | 102 | - (NSMutableAttributedString *)getActivityPrice { 103 | NSString *price = [NSString stringWithFormat:@"¥%.2f",self.skuModel.sale_price.doubleValue];; 104 | NSString *activity_price = [NSString stringWithFormat:@"¥%.2f",self.skuModel.activity_price.doubleValue]; 105 | NSMutableAttributedString *att = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@",activity_price,price]]; 106 | [att addAttributes:@{NSForegroundColorAttributeName:KMainColor} range:NSMakeRange(0, activity_price.length)]; 107 | [att addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x999999),NSStrikethroughStyleAttributeName: @(1),NSBaselineOffsetAttributeName : @(NSUnderlineStyleSingle)} range:NSMakeRange(activity_price.length + 1, price.length)]; 108 | return att; 109 | } 110 | 111 | - (void)actionControlState { 112 | if ((self.skuModel.actual_stock.integerValue + self.skuModel.virtual_stock.integerValue) <= 0) { 113 | self.skuName.textColor = UIColorFromRGB(0x999999); 114 | self.price.textColor = UIColorFromRGB(0x999999); 115 | self.countField.textColor = UIColorFromRGB(0x999999); 116 | self.userInteractionEnabled = NO; 117 | self.inventory.hidden = NO; 118 | } else { 119 | self.countField.textColor = UIColorFromRGB(0x333333); 120 | self.skuName.textColor = UIColorFromRGB(0x333333); 121 | self.userInteractionEnabled = YES; 122 | self.inventory.hidden = YES; 123 | } 124 | } 125 | 126 | - (UIImage *)getImageWithSkuModel:(GHSpecificationSelectionModel *)skuModel { 127 | UIImage *image = nil; 128 | if ([skuModel.activityType isEqualToString:@"1"]) { 129 | image = [UIImage imageWithFrame:CGRectMake(0, 0, 30, 14) backGroundColor:KMainColor text:@"特价" textColor:[UIColor whiteColor] textFontOfSize:8]; 130 | } else if ([skuModel.activityType isEqualToString:@"2"]) { 131 | image = [UIImage imageWithFrame:CGRectMake(0, 0, 30, 14) backGroundColor:[UIColor orangeColor] text:@"满减" textColor:[UIColor whiteColor] textFontOfSize:8]; 132 | } else { 133 | image = nil; 134 | } 135 | return image; 136 | } 137 | 138 | - (NSAttributedString *)getRealString:(GHSpecificationSelectionModel *)skuModel{ 139 | 140 | NSMutableAttributedString *attriStr = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@%@", ValidStr(skuModel.color)? skuModel.color:@"", ValidStr(skuModel.color) ? @"/":@"", ValidStr(skuModel.specifications) ? skuModel.specifications :@""]]; 141 | NSTextAttachment *location = [[NSTextAttachment alloc]init]; 142 | UIImage *image = [self getImageWithSkuModel:skuModel]; 143 | location.image = image; 144 | location.bounds = CGRectMake(0, -3, 30, 14); 145 | NSAttributedString *firstImage = [NSAttributedString attributedStringWithAttachment:location]; 146 | NSMutableAttributedString *space = [[NSMutableAttributedString alloc] initWithString:@" "]; 147 | if (image) { 148 | [attriStr insertAttributedString:space atIndex:0]; 149 | [attriStr insertAttributedString:firstImage atIndex:0]; 150 | } 151 | return attriStr; 152 | } 153 | 154 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 155 | if (self == [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 156 | self.selectionStyle = UITableViewCellSelectionStyleNone; 157 | [self addSubview]; 158 | } 159 | return self; 160 | } 161 | 162 | - (void)addSubview { 163 | [self.contentView addSubview:self.skuCode]; 164 | [self.contentView addSubview:self.estimatedDate]; 165 | [self.contentView addSubview:self.inventory]; 166 | [self.contentView addSubview:self.skuName]; 167 | [self.contentView addSubview:self.price]; 168 | [self.contentView addSubview:self.countField]; 169 | [self.contentView addSubview:self.line]; 170 | } 171 | 172 | - (void)layoutSubviews { 173 | [super layoutSubviews]; 174 | 175 | CGFloat width = (kScreenWidth - 50) / 3.01; 176 | [self.skuCode mas_remakeConstraints:^(MASConstraintMaker *make) { 177 | make.left.equalTo(self.contentView).offset(15); 178 | make.bottom.equalTo(self.contentView).offset(-15); 179 | make.width.equalTo(@(width)); 180 | }]; 181 | 182 | [self.estimatedDate mas_remakeConstraints:^(MASConstraintMaker *make) { 183 | make.left.equalTo(self.skuCode.mas_right).offset(10); 184 | make.centerY.equalTo(self.skuCode); 185 | make.width.equalTo(@(width)); 186 | }]; 187 | 188 | [self.inventory mas_remakeConstraints:^(MASConstraintMaker *make) { 189 | make.left.equalTo(self.estimatedDate.mas_right).offset(10); 190 | make.centerY.equalTo(self.estimatedDate); 191 | make.width.equalTo(@(width)); 192 | }]; 193 | 194 | [self.skuName mas_remakeConstraints:^(MASConstraintMaker *make) { 195 | make.left.equalTo(self.skuCode); 196 | make.bottom.equalTo(self.skuCode.mas_top).offset(-10); 197 | make.width.equalTo(@(width)); 198 | }]; 199 | 200 | [self.price mas_remakeConstraints:^(MASConstraintMaker *make) { 201 | make.left.equalTo(self.skuName.mas_right).offset(10); 202 | make.centerY.equalTo(self.skuName); 203 | make.width.equalTo(@(width)); 204 | }]; 205 | 206 | [self.countField mas_remakeConstraints:^(MASConstraintMaker *make) { 207 | make.left.equalTo(self.price.mas_right).offset(10); 208 | make.centerY.equalTo(self.price); 209 | make.width.equalTo(@(width)); 210 | make.height.equalTo(@(26)); 211 | }]; 212 | 213 | [self.line mas_makeConstraints:^(MASConstraintMaker *make) { 214 | make.left.equalTo(self.skuName); 215 | make.right.equalTo(self.countField); 216 | make.bottom.equalTo(self.contentView); 217 | make.height.equalTo(@(1)); 218 | }]; 219 | } 220 | 221 | + (CGFloat)getCellHeightWithSkuModel:(GHSpecificationSelectionModel *)skuModel { 222 | CGFloat width = (kScreenWidth - 50) / 3.01; 223 | UILabel *skuName = [[UILabel alloc]init]; 224 | UILabel *priceLab = [[UILabel alloc]init]; 225 | priceLab.text = [NSString stringWithFormat:@"¥%@",skuModel.sale_price]; 226 | CGSize skuNameSize = [NSString sizeWithText:[NSString stringWithFormat:@"%@%@%@", ValidStr(skuModel.color)? skuModel.color:@"", ValidStr(skuModel.color) ? @"/":@"", ValidStr(skuModel.specifications) ? skuModel.specifications :@""]andFont:[UIFont systemFontOfSize:10] andMaxSize:CGSizeMake(width, MAXFLOAT)]; [skuName sizeThatFits:CGSizeMake(width, MAXFLOAT)]; 227 | CGSize skuCodeSzie = [NSString sizeWithText:[NSString stringWithFormat:@"商品编码:%@",skuModel.sku_code] andFont:[UIFont systemFontOfSize:10] andMaxSize:CGSizeMake(width, MAXFLOAT)]; 228 | CGFloat leftHeight = 15 + skuNameSize.height + 10 + skuCodeSzie.height + 15; 229 | CGSize priceSzie = [priceLab sizeThatFits:CGSizeMake(width, MAXFLOAT)]; 230 | NSString *estimatedDate = @""; 231 | if (skuModel.count.integerValue <= skuModel.actual_stock.integerValue && skuModel.actual_stock.integerValue > 0) { 232 | estimatedDate = @"1天"; 233 | } else { 234 | estimatedDate = [NSString stringWithFormat:@"%ld天",skuModel.arrival_cycle.integerValue + 1]; 235 | } 236 | CGSize estimatedDateSzie = [NSString sizeWithText:[NSString stringWithFormat:@"预计出货日:%@",estimatedDate] andFont:[UIFont systemFontOfSize:10] andMaxSize:CGSizeMake(width, MAXFLOAT)]; 237 | CGFloat rightHeight = 15 + priceSzie.height + 10 + estimatedDateSzie.height + 15; 238 | if (leftHeight >= rightHeight) { 239 | return leftHeight; 240 | } 241 | return rightHeight; 242 | } 243 | 244 | - (UILabel *)price { 245 | if (_price == nil) { 246 | _price = [[UILabel alloc]init]; 247 | _price.font = [UIFont systemFontOfSize:12]; 248 | _price.textColor = UIColorFromRGB(0x333333); 249 | _price.text = @"价格(元)"; 250 | _price.numberOfLines = 0; 251 | _price.textAlignment = NSTextAlignmentCenter; 252 | } 253 | return _price; 254 | } 255 | 256 | - (UILabel *)estimatedDate { 257 | if (_estimatedDate == nil) { 258 | _estimatedDate = [[UILabel alloc]init]; 259 | _estimatedDate.font = [UIFont systemFontOfSize:10]; 260 | _estimatedDate.textColor = UIColorFromRGB(0x999999); 261 | _estimatedDate.textAlignment = NSTextAlignmentCenter; 262 | 263 | } 264 | return _estimatedDate; 265 | } 266 | 267 | - (UILabel *)skuName { 268 | if (_skuName == nil) { 269 | _skuName = [[UILabel alloc]init]; 270 | _skuName.font = [UIFont systemFontOfSize:10]; 271 | _skuName.textColor = UIColorFromRGB(0x999999); 272 | _skuName.numberOfLines = 0; 273 | } 274 | return _skuName; 275 | } 276 | 277 | - (UILabel *)skuCode { 278 | if (_skuCode == nil) { 279 | _skuCode = [[UILabel alloc]init]; 280 | _skuCode.font = [UIFont systemFontOfSize:10]; 281 | _skuCode.textColor = UIColorFromRGB(0x999999); 282 | } 283 | return _skuCode; 284 | } 285 | 286 | - (UILabel *)inventory { 287 | if (_inventory == nil) { 288 | _inventory = [[UILabel alloc]init]; 289 | _inventory.font = [UIFont systemFontOfSize:10]; 290 | _inventory.textColor = [UIColor redColor]; 291 | _inventory.text = @"库存不足"; 292 | _inventory.textAlignment = NSTextAlignmentCenter; 293 | } 294 | return _inventory; 295 | } 296 | 297 | - (GHTextField *)countField { 298 | if (_countField == nil) { 299 | _countField = [[GHTextField alloc] init]; 300 | _countField.backgroundColor = [UIColor whiteColor]; 301 | _countField.showBorderLine = YES; 302 | _countField.delegate = self; 303 | _countField.tintColor = KMainColor; 304 | weakself(self); 305 | _countField.countDidChangeBlock = ^(NSInteger count) { 306 | weakSelf.skuModel.count = [NSString stringWithFormat:@"%ld",(long)count]; 307 | if (weakSelf.countBlock) { 308 | weakSelf.countBlock(weakSelf.skuModel); 309 | } 310 | }; 311 | } 312 | return _countField; 313 | } 314 | 315 | - (UIView *)line { 316 | if (_line == nil) { 317 | _line = [[UIView alloc]init]; 318 | _line.backgroundColor = UIColorFromRGB(0xF5F5F5); 319 | } 320 | return _line; 321 | } 322 | 323 | 324 | @end 325 | 326 | @interface GHAlibabaSpecificationSelection() 327 | 328 | /** 329 | 自定义view 330 | */ 331 | @property (nonatomic , strong) GHScrollTitles *scrollTitles; 332 | 333 | /** 334 | 自定义view 335 | */ 336 | @property (nonatomic , strong) UIView *backGround; 337 | /** 338 | 图标 339 | */ 340 | @property (nonatomic , strong) UIImageView *icon; 341 | /** 342 | 关闭 343 | */ 344 | @property (nonatomic , strong) UIButton *close; 345 | 346 | /** 347 | sku标题 348 | */ 349 | @property (nonatomic , strong) UILabel *title; 350 | 351 | /** 352 | sku价格 353 | */ 354 | @property (nonatomic , strong) UILabel *price; 355 | 356 | /** 357 | 最小起订量 358 | */ 359 | @property (nonatomic , strong) UILabel *minimumOrder; 360 | 361 | /** 362 | * 363 | */ 364 | @property (nonatomic , strong) UIView *shadow; 365 | 366 | /** 367 | * 368 | */ 369 | @property (nonatomic , strong) UIScrollView *scrollView; 370 | 371 | /** 372 | * 373 | */ 374 | @property (nonatomic , strong) UIView *test; 375 | 376 | @property (nonatomic , strong) NSMutableArray *arrays; 377 | 378 | @property (nonatomic , assign) NSInteger currentPage; 379 | 380 | @property (nonatomic , strong) UITableView *table; 381 | 382 | @property (nonatomic , strong) UILabel *t; 383 | 384 | @property (nonatomic , strong) NSArray *skuList; 385 | 386 | @property (nonatomic , strong) NSMutableArray *tables; 387 | 388 | @property (nonatomic , strong) NSArray *colors; 389 | 390 | @property (nonatomic , strong) GHAlibabaSpecificationSelectionBottomView *bottomView; 391 | 392 | @end 393 | 394 | @implementation GHAlibabaSpecificationSelection 395 | 396 | - (void)clickClose { 397 | [self dismiss]; 398 | } 399 | 400 | - (void)show { 401 | [self configuration]; 402 | [self configDefaultUI]; 403 | [super show]; 404 | } 405 | 406 | - (void)setSkuList:(NSArray *)skuList colors:(NSArray *)colors sectePrice:(NSDictionary *)sectePrice { 407 | self.skuList = skuList; 408 | self.colors = nil; 409 | self.colors = colors; 410 | NSString *max_price = sectePrice[@"max_price"]; 411 | NSString *min_price = sectePrice[@"min_price"]; 412 | self.price.attributedText = [self getRealPirceWithMaxPrice:max_price min_price:min_price]; 413 | NSMutableArray *titles = [NSMutableArray array]; 414 | if (colors.count > 1) { 415 | for (NSInteger i = 0; i < colors.count; i++) { 416 | GHSpecificationSelectionTitleModel *titleModel = [[GHSpecificationSelectionTitleModel alloc]init]; 417 | NSString *colorStr = colors[i]; 418 | titleModel.color = colorStr; 419 | NSMutableArray *skus = [NSMutableArray array]; 420 | for (NSInteger j = 0; j < skuList.count; j++) { 421 | GHSpecificationSelectionModel *skuModel = skuList[j]; 422 | if ([skuModel.color isEqualToString:titleModel.color]) { 423 | [skus addObject:skuModel]; 424 | } 425 | } 426 | titleModel.skuList = skus.copy; 427 | [titles addObject:titleModel]; 428 | } 429 | } else { 430 | GHSpecificationSelectionTitleModel *titleModel = [[GHSpecificationSelectionTitleModel alloc]init]; 431 | NSMutableArray *skus = [NSMutableArray array]; 432 | for (NSInteger j = 0; j < skuList.count; j++) { 433 | GHSpecificationSelectionModel *skuModel = skuList[j]; 434 | [skus addObject:skuModel]; 435 | } 436 | self.currentPage = 0; 437 | titleModel.skuList = skus.copy; 438 | [titles addObject:titleModel]; 439 | } 440 | self.scrollTitles.titles = titles.mutableCopy; 441 | [self setTableViews]; 442 | [self loadIconWithIndex:0]; 443 | } 444 | 445 | - (NSMutableAttributedString *)getRealPirceWithMaxPrice:(NSString *)max_price min_price:(NSString *)min_price { 446 | if (!ValidStr(max_price)) { 447 | return nil; 448 | } 449 | if (!ValidStr(min_price)) { 450 | return nil; 451 | } 452 | NSMutableAttributedString *maxPrice = [self actionPrice:max_price]; 453 | NSMutableAttributedString *minPrice = [self actionPrice:min_price]; 454 | NSMutableAttributedString *realPrice = [[NSMutableAttributedString alloc]init]; 455 | [realPrice appendAttributedString:minPrice]; 456 | [realPrice appendAttributedString:[[NSMutableAttributedString alloc]initWithString:@" ~"]]; 457 | [realPrice appendAttributedString:maxPrice]; 458 | return realPrice; 459 | } 460 | 461 | - (NSMutableAttributedString *)actionPrice:(NSString *)price { 462 | 463 | NSString *priceStr = [NSString stringWithFormat:@"¥%.2f",price.doubleValue]; 464 | NSMutableAttributedString *att = [[NSMutableAttributedString alloc] initWithString:priceStr]; 465 | [att addAttributes:@{NSForegroundColorAttributeName:[UIColor orangeColor],NSFontAttributeName:[UIFont systemFontOfSize:18]} range:NSMakeRange(0, priceStr.length)]; 466 | [att addAttributes:@{NSForegroundColorAttributeName:[UIColor orangeColor],NSFontAttributeName:[UIFont systemFontOfSize:12]} range:NSMakeRange(0, 1)]; 467 | [att addAttributes:@{NSForegroundColorAttributeName:[UIColor orangeColor],NSFontAttributeName:[UIFont systemFontOfSize:12]} range:NSMakeRange(priceStr.length - 2, 2)]; 468 | return att; 469 | } 470 | 471 | - (void)loadIconWithIndex:(NSInteger)index { 472 | GHSpecificationSelectionTitleModel *titleModel = self.scrollTitles.titles[index]; 473 | GHSpecificationSelectionModel *skuModelFirst = titleModel.skuList.firstObject; 474 | GHSpecificationSelectionImageModel *imagesModel = skuModelFirst.images.firstObject; 475 | self.title.text = [NSString stringWithFormat:@"%@",skuModelFirst.sku_name]; 476 | weakself(self); 477 | [self.icon gh_startAnimating]; 478 | [self.icon sd_setImageWithURL:[NSURL URLWithString:imagesModel.img_url] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { 479 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 480 | [weakSelf.icon gh_stopAnimating]; 481 | }); 482 | }]; 483 | self.minimumOrder.text = [NSString stringWithFormat:@"最少起订量: %@%@",skuModelFirst.mini_order,skuModelFirst.unit]; 484 | UITableView *tabele = self.tables[index]; 485 | self.currentPage = index; 486 | [tabele reloadData]; 487 | } 488 | 489 | - (instancetype)initWithFrame:(CGRect)frame { 490 | if (self == [super initWithFrame:frame]) { 491 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardDidShow:) name:UIKeyboardWillShowNotification object:nil]; 492 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardDidHide:) name:UIKeyboardWillHideNotification object:nil]; 493 | [self.contentView addSubview:self.icon]; 494 | [self.contentView addSubview:self.close]; 495 | [self.contentView addSubview:self.title]; 496 | [self.contentView addSubview:self.price]; 497 | [self.contentView addSubview:self.shadow]; 498 | } 499 | return self; 500 | } 501 | 502 | - (void)keyBoardDidShow:(NSNotification*)notifiction { 503 | 504 | NSValue *keyboardObject = [[notifiction userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]; 505 | CGRect keyboardRect; 506 | [keyboardObject getValue:&keyboardRect]; 507 | double duration = [[notifiction.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 508 | [UIView beginAnimations:nil context:nil]; 509 | [UIView setAnimationDuration:duration]; 510 | [UIView setAnimationDelay:0]; 511 | self.contentView.y = kScreenHeight - keyboardRect.size.height - self.contentView.height; 512 | [UIView commitAnimations]; 513 | } 514 | 515 | - (void)keyBoardDidHide:(NSNotification*)notification { 516 | 517 | double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 518 | [UIView beginAnimations:nil context:nil]; 519 | [UIView setAnimationDuration:duration]; 520 | self.contentView.y = kScreenHeight - self.contentView.height - kSafeAreaBottomHeight; 521 | [UIView commitAnimations]; 522 | } 523 | 524 | - (void)layoutSubviews { 525 | [super layoutSubviews]; 526 | CGFloat width = kScreenWidth - (CGRectGetMaxX(self.icon.frame) + 20) - (kScreenWidth - CGRectGetMinX(self.close.frame)) - 10; 527 | CGSize titleSize = [NSString sizeWithText:self.title.text andFont:[UIFont systemFontOfSize:16] andMaxSize:CGSizeMake(width, MAXFLOAT)]; 528 | self.title.frame = CGRectMake(CGRectGetMaxX(self.icon.frame) + 20, 10, width, titleSize.height); 529 | self.price.frame = CGRectMake(CGRectGetMinX(self.title.frame), CGRectGetMaxY(self.title.frame) + 3, self.title.width , 21); 530 | [self.contentView addSubview:self.minimumOrder]; 531 | self.minimumOrder.frame = CGRectMake(CGRectGetMinX(self.price.frame), CGRectGetMaxY(self.price.frame) + 2, self.price.width, 21); 532 | self.shadow.frame = CGRectMake(0, CGRectGetMaxY(self.icon.frame) + 10, kScreenWidth, 10); 533 | } 534 | 535 | - (void)setTableViews { 536 | [self.tables removeAllObjects]; 537 | for (UITableView *tab in self.tables) { 538 | [tab removeFromSuperview]; 539 | } 540 | [self.contentView addSubview:self.scrollTitles]; 541 | if (self.colors.count > 1) { 542 | [self.contentView addSubview:self.scrollTitles]; 543 | self.scrollTitles.frame = CGRectMake(0, CGRectGetMaxY(self.shadow.frame) + 10, kScreenWidth, 50); 544 | } else { 545 | self.scrollTitles.frame = CGRectMake(0, CGRectGetMaxY(self.shadow.frame) + 10, kScreenWidth, 0); 546 | } 547 | [self.contentView addSubview:self.scrollView]; 548 | CGFloat scrollViewH = 500 - CGRectGetMaxY(self.scrollTitles.frame) - 80; 549 | CGFloat scrollViewY = self.colors.count > 1 ? CGRectGetMaxY(self.scrollTitles.frame):CGRectGetMaxY(self.shadow.frame) + 10; 550 | self.scrollView.frame = CGRectMake(0,scrollViewY, kScreenWidth,scrollViewH); 551 | for (NSInteger index = 0; index < (self.colors.count > 1 ? self.colors.count:1); index++) { 552 | UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(self.scrollView.frame.size.width * index , 0, self.scrollView.frame.size.width, scrollViewH) style:UITableViewStylePlain]; 553 | tableView.delegate = self; 554 | tableView.dataSource = self; 555 | tableView.tableFooterView = [UIView new]; 556 | tableView.showsVerticalScrollIndicator = YES; 557 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 558 | [tableView registerClass:[GHSpecificationSelectionCell class] forCellReuseIdentifier:@"GHSpecificationSelectionCellID"]; 559 | [self.tables addObject:tableView]; 560 | [self.scrollView addSubview:tableView]; 561 | } 562 | self.scrollView.contentSize = CGSizeMake(kScreenWidth * self.scrollTitles.titles.count, 0); 563 | [self.contentView addSubview:self.bottomView]; 564 | self.bottomView.frame = CGRectMake(0, CGRectGetMaxY(self.scrollView.frame), kScreenWidth, 80 + kSafeAreaBottomHeight); 565 | } 566 | 567 | #pragma mark UIScrollViewDelegate 568 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 569 | [self.scrollTitles setMenusScrollViewEnd:scrollView.contentOffset]; 570 | NSInteger page = (NSInteger)self.scrollView.contentOffset.x / kScreenWidth; 571 | [self loadIconWithIndex:page]; 572 | } 573 | 574 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 575 | if (scrollView == self.scrollView) { 576 | [self scrollViewDidEndScrollingAnimation:scrollView]; 577 | } 578 | } 579 | 580 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 581 | if (scrollView == self.scrollView) { 582 | [self.scrollTitles setMenusScrollView:scrollView.contentOffset]; 583 | } 584 | } 585 | 586 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 587 | GHSpecificationSelectionTitleModel *titleModel = self.scrollTitles.titles[self.currentPage]; 588 | return titleModel.skuList.count; 589 | } 590 | 591 | #pragma mark 创建cell 592 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 593 | GHSpecificationSelectionTitleModel *titleModel = self.scrollTitles.titles[self.currentPage]; 594 | GHSpecificationSelectionModel *skuModel = titleModel.skuList[indexPath.row]; 595 | GHSpecificationSelectionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GHSpecificationSelectionCellID"]; 596 | cell.skuModel = skuModel; 597 | weakself(self); 598 | cell.countBlock = ^(GHSpecificationSelectionModel * _Nonnull skuModel) { 599 | [weakSelf.scrollTitles reloadData]; 600 | [weakSelf.bottomView changeStatusWithTitles:weakSelf.scrollTitles.titles]; 601 | }; 602 | return cell; 603 | } 604 | 605 | #pragma mark - 计算高度 606 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 607 | GHSpecificationSelectionTitleModel *titleModel = self.scrollTitles.titles[self.currentPage]; 608 | GHSpecificationSelectionModel *skuModel = titleModel.skuList[indexPath.row]; 609 | return [GHSpecificationSelectionCell getCellHeightWithSkuModel:skuModel]; 610 | } 611 | 612 | - (void)scrollWithCurrentIndex:(NSInteger)currentIndex { 613 | CGPoint offset = self.scrollView.contentOffset; 614 | offset.x = kScreenWidth * currentIndex; 615 | [self.scrollView setContentOffset:offset animated:YES]; 616 | } 617 | 618 | #pragma mark - 重置所有数据 619 | - (void)resetData { 620 | for (GHSpecificationSelectionTitleModel *titleModel in self.scrollTitles.titles) { 621 | titleModel.count = @""; 622 | for (GHSpecificationSelectionModel *skuModel in titleModel.skuList) { 623 | skuModel.count = @""; 624 | } 625 | } 626 | for (UITableView *tab in self.tables) { 627 | [tab reloadData]; 628 | } 629 | [self.scrollTitles resetData]; 630 | // self.currentPage = 0; 631 | [self.bottomView changeStatusWithTitles:self.scrollTitles.titles]; 632 | // [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES]; 633 | } 634 | 635 | - (void)showAnimation { 636 | UIImageView *icon = [[UIImageView alloc]initWithImage:self.icon.image]; 637 | icon.backgroundColor = [UIColor redColor]; 638 | icon.frame = [self relativeFrameForScreenWithView]; 639 | [[UIApplication sharedApplication].keyWindow addSubview:icon]; 640 | CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 641 | rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 11.0 ]; 642 | rotationAnimation.duration = 1.0; 643 | rotationAnimation.cumulative = YES; 644 | rotationAnimation.repeatCount = 0; 645 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 646 | [icon.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"]; 647 | }); 648 | 649 | [UIView animateWithDuration:1.0 animations:^{ 650 | icon.frame = self.shopCarRect; 651 | } completion:^(BOOL finished) { 652 | [icon removeFromSuperview]; 653 | }]; 654 | } 655 | 656 | - (CGRect)relativeFrameForScreenWithView { 657 | UIView *view = self.icon; 658 | CGFloat x = .0; 659 | CGFloat y = .0; 660 | while (view != [UIApplication sharedApplication].keyWindow && nil != view) { 661 | x += view.frame.origin.x; 662 | y += view.frame.origin.y; 663 | view = view.superview; 664 | if ([view isKindOfClass:[UIScrollView class]]) { 665 | x -= ((UIScrollView *) view).contentOffset.x; 666 | y -= ((UIScrollView *) view).contentOffset.y; 667 | } 668 | } 669 | return CGRectMake(x, y, self.icon.size.width, self.icon.size.height); 670 | } 671 | 672 | - (void)clickSure { 673 | [self showAnimation]; 674 | NSMutableArray *skuList = [NSMutableArray array]; 675 | for (GHSpecificationSelectionTitleModel *titleModel in self.scrollTitles.titles) { 676 | [skuList addObject:titleModel]; 677 | } 678 | 679 | NSArray *deepCopyArray = [[NSArray alloc]initWithArray:skuList.copy copyItems:YES]; 680 | for (NSInteger i = 0 ; i < deepCopyArray.count; i ++) { 681 | GHSpecificationSelectionTitleModel *titleModel = deepCopyArray[i]; 682 | titleModel.skuList = [[NSArray alloc]initWithArray:titleModel.skuList copyItems:YES]; 683 | } 684 | if (skuList.count == 0) { 685 | [ToastTool makeToast:@"至少选择一种商品" targetView:self.scrollView]; 686 | return; 687 | } 688 | weakself(self); 689 | [ToastTool makeToast:@"添加成功" targetView:self.scrollView toastToolCompleteBlock:^{ 690 | [weakSelf resetData]; 691 | weakSelf.getDataBlock? weakSelf.getDataBlock(deepCopyArray):nil; 692 | }]; 693 | } 694 | 695 | #pragma mark - get 696 | 697 | - (GHScrollTitles *)scrollTitles { 698 | if (_scrollTitles == nil) { 699 | _scrollTitles = [[GHScrollTitles alloc]init]; 700 | _scrollTitles.frame = CGRectMake(0, CGRectGetMaxY(self.shadow.frame) + 10, kScreenWidth, 50); 701 | weakself(self); 702 | _scrollTitles.didClickTitleBlock = ^(NSInteger tag) { 703 | [weakSelf scrollWithCurrentIndex:tag]; 704 | }; 705 | _scrollTitles.didClickLeftBlock = ^{ 706 | CGPoint point = CGPointMake(weakSelf.scrollView.contentOffset.x - kScreenWidth , 0); 707 | [weakSelf.scrollView setContentOffset:point animated:YES]; 708 | }; 709 | _scrollTitles.didClickRightBlock = ^{ 710 | CGPoint point = CGPointMake(weakSelf.scrollView.contentOffset.x + kScreenWidth , 0); 711 | [weakSelf.scrollView setContentOffset:point animated:YES]; 712 | }; 713 | } 714 | return _scrollTitles; 715 | } 716 | 717 | - (UIScrollView *)scrollView { 718 | if (_scrollView == nil) { 719 | _scrollView = [[UIScrollView alloc]init]; 720 | _scrollView.frame = CGRectMake(0,CGRectGetMaxY(self.scrollTitles.frame), kScreenWidth,self.contentViewHeight - CGRectGetMaxY(self.scrollTitles.frame)); 721 | _scrollView.pagingEnabled = YES; 722 | _scrollView.delegate = self; 723 | _scrollView.backgroundColor = [UIColor redColor]; 724 | _scrollView.bounces = NO; 725 | _scrollView.showsHorizontalScrollIndicator = NO; 726 | } 727 | return _scrollView; 728 | } 729 | 730 | - (UIImageView *)icon { 731 | if (_icon == nil) { 732 | _icon = [[UIImageView alloc]initWithFrame:CGRectMake(10, -20, 100, 100)]; 733 | _icon.layer.masksToBounds = YES; 734 | _icon.layer.cornerRadius = 5; 735 | [_icon addActivityIndicator]; 736 | } 737 | return _icon; 738 | } 739 | 740 | - (UIButton *)close { 741 | if (_close == nil) { 742 | _close = [[UIButton alloc]init]; 743 | [_close setImage:[UIImage imageNamed:@"close"] forState:UIControlStateNormal]; 744 | _close.frame = CGRectMake(self.frame.size.width - 30 - 10, 20, 30, 30); 745 | [_close addTarget:self action:@selector(clickClose) forControlEvents:UIControlEventTouchUpInside]; 746 | } 747 | return _close; 748 | } 749 | - (UIView *)shadow { 750 | if (_shadow == nil) { 751 | _shadow = [[UIView alloc]init]; 752 | _shadow.frame = CGRectMake(0, CGRectGetMaxY(self.icon.frame) + 10, kScreenWidth, 10); 753 | _shadow.backgroundColor = [UIColor whiteColor]; 754 | _shadow.layer.shadowColor = [UIColor blackColor].CGColor; 755 | _shadow.layer.shadowOffset = CGSizeMake(0, 5); 756 | _shadow.layer.shadowOpacity = 0.09; 757 | } 758 | return _shadow; 759 | } 760 | 761 | - (UILabel *)minimumOrder { 762 | if (_minimumOrder == nil) { 763 | _minimumOrder = [[UILabel alloc]init]; 764 | _minimumOrder.frame = CGRectMake(CGRectGetMinX(self.price.frame), CGRectGetMaxY(self.price.frame) + 5, 100, 21); 765 | } 766 | return _minimumOrder; 767 | } 768 | 769 | - (UILabel *)price { 770 | if (_price == nil) { 771 | _price = [[UILabel alloc]init]; 772 | _price.frame = CGRectMake(CGRectGetMinX(self.title.frame), CGRectGetMaxY(self.title.frame) + 5, 100, 21); 773 | _price.textColor = [UIColor orangeColor]; 774 | } 775 | return _price; 776 | } 777 | 778 | - (UILabel *)title { 779 | if (_title == nil) { 780 | _title = [[UILabel alloc]init]; 781 | _title.frame = CGRectMake(CGRectGetMaxX(self.icon.frame) + 20, 30, 200, 21); 782 | _title.numberOfLines = 0; 783 | } 784 | return _title; 785 | } 786 | 787 | - (NSMutableArray *)arrays { 788 | if (_arrays == nil) { 789 | _arrays = [NSMutableArray array]; 790 | } 791 | return _arrays; 792 | } 793 | 794 | - (NSMutableArray *)tables { 795 | if (_tables == nil) { 796 | _tables = [NSMutableArray array]; 797 | } 798 | return _tables; 799 | } 800 | 801 | - (GHAlibabaSpecificationSelectionBottomView *)bottomView { 802 | if (_bottomView == nil) { 803 | _bottomView = [[GHAlibabaSpecificationSelectionBottomView alloc]init]; 804 | weakself(self); 805 | _bottomView.didClickSureBlock = ^{ 806 | [weakSelf clickSure]; 807 | }; 808 | } 809 | return _bottomView; 810 | } 811 | 812 | @end 813 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHAlibabaSpecificationSelectionBottomView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHAlibabaSpecificationSelectionBottomView.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef void (^GHAlibabaSpecificationSelectionBottomViewDidClickSureBlock)(void); 14 | 15 | @interface GHAlibabaSpecificationSelectionBottomView : UIView 16 | 17 | @property (nonatomic , copy) GHAlibabaSpecificationSelectionBottomViewDidClickSureBlock didClickSureBlock; 18 | 19 | /** 20 | * 根据数据来决定确定按钮的状态 21 | */ 22 | - (void)changeStatusWithTitles:(NSMutableArray *)titles; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHAlibabaSpecificationSelectionBottomView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHAlibabaSpecificationSelectionBottomView.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHAlibabaSpecificationSelectionBottomView.h" 10 | #import "GHSpecificationSelectionModel.h" 11 | #import "GHSpecificationSelectionTitleModel.h" 12 | #import "UIButton+Extension.h" 13 | 14 | @interface GHAlibabaSpecificationSelectionBottomView() 15 | 16 | @property (nonatomic , strong) UIView *line; 17 | 18 | /** 19 | * 金额 20 | */ 21 | @property (nonatomic , strong) UILabel *amount; 22 | 23 | /** 24 | * 确定 25 | */ 26 | @property (nonatomic , strong) UIButton *sure; 27 | 28 | @end 29 | @implementation GHAlibabaSpecificationSelectionBottomView 30 | 31 | - (void)changeStatusWithTitles:(NSMutableArray *)titles { 32 | NSInteger count = 0; 33 | double amount = 0; 34 | for (NSInteger i = 0 ; i < titles.count; i ++) { 35 | GHSpecificationSelectionTitleModel *titleModel = titles[i ]; 36 | for (NSInteger j = 0 ; j < titleModel.skuList.count; j++) { 37 | GHSpecificationSelectionModel *skuModel = titleModel.skuList[j]; 38 | count += skuModel.count.integerValue; 39 | amount += [skuModel.activityType isEqualToString:@"1"] ?skuModel.count.doubleValue * skuModel.activity_price.doubleValue: skuModel.count.doubleValue * skuModel.sale_price.doubleValue; 40 | } 41 | } 42 | self.sure.enabled = count == 0 ? NO:YES; 43 | self.amount.text = [NSString stringWithFormat:@"共 %ld个¥%.2f",(long)count,amount]; 44 | } 45 | 46 | - (instancetype)initWithFrame:(CGRect)frame { 47 | if (self == [super initWithFrame:frame]) { 48 | [self setupUI]; 49 | [self changeStatusWithTitles:@[].copy]; 50 | } 51 | return self; 52 | } 53 | 54 | - (void)setupUI { 55 | [self addSubview:self.line]; 56 | [self.line mas_makeConstraints:^(MASConstraintMaker *make) { 57 | make.left.top.right.equalTo(self); 58 | make.height.equalTo(@1); 59 | }]; 60 | 61 | [self addSubview:self.amount]; 62 | [self.amount mas_makeConstraints:^(MASConstraintMaker *make) { 63 | make.right.equalTo(self).offset(-20); 64 | make.top.equalTo(self.line).offset(5); 65 | make.height.equalTo(@20); 66 | make.left.equalTo(self).offset(20); 67 | }]; 68 | 69 | [self addSubview:self.sure]; 70 | [self.sure mas_makeConstraints:^(MASConstraintMaker *make) { 71 | make.left.right.equalTo(self); 72 | make.height.equalTo(@50); 73 | make.bottom.equalTo(self).offset(-kSafeAreaBottomHeight); 74 | }]; 75 | } 76 | 77 | - (void)clickSure { 78 | if (self.didClickSureBlock) { 79 | self.didClickSureBlock(); 80 | } 81 | } 82 | 83 | - (UIView *)line { 84 | if (_line == nil) { 85 | _line = [[UIView alloc]init]; 86 | _line.backgroundColor = UIColorFromRGB(0xe5e5e5); 87 | } 88 | return _line; 89 | } 90 | 91 | - (UILabel *)amount { 92 | if (_amount == nil) { 93 | _amount = [[UILabel alloc]init]; 94 | _amount.textColor = KMainColor; 95 | _amount.font = [UIFont systemFontOfSize:14]; 96 | _amount.textAlignment = NSTextAlignmentRight; 97 | } 98 | return _amount; 99 | } 100 | 101 | - (UIButton *)sure { 102 | if (_sure == nil) { 103 | _sure = [[UIButton alloc]init]; 104 | [_sure setTitle:@"确 定" forState:UIControlStateNormal]; 105 | [_sure setBackgroundColor:KMainColor forState:UIControlStateNormal]; 106 | [_sure setBackgroundColor:UIColorFromRGB(0xe5e5e5) forState:UIControlStateDisabled]; 107 | [_sure addTarget:self action:@selector(clickSure) forControlEvents:UIControlEventTouchUpInside]; 108 | } 109 | return _sure; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHButton.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/28. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHButton : UIButton 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHButton.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/28. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHButton.h" 10 | 11 | @implementation GHButton 12 | 13 | - (void)setHighlighted:(BOOL)highlighted { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHPopView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHPopView.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHPopView : UIView 14 | 15 | #pragma mark - Value 16 | /** 内容View高度 */ 17 | @property (nonatomic, assign) CGFloat contentViewHeight; 18 | 19 | #pragma mark - Event 20 | /** 显示完成Block */ 21 | @property (nonatomic, copy) void (^showFinish)(CGRect frame); 22 | /** 消失完成Block */ 23 | @property (nonatomic, copy) void (^dimissFinish)(void); 24 | 25 | /** 显示 */ 26 | - (void)show; 27 | /** 消失 */ 28 | - (void)dismiss; 29 | 30 | @property (nonatomic, strong) UIView *contentView; 31 | 32 | - (void)configuration; 33 | - (void)configDefaultUI; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHPopView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHPopView.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHPopView.h" 10 | 11 | /** 12 | * 动画时间 13 | */ 14 | #define animateDuration 0.3 15 | 16 | #define WS(weakSelf) __weak __typeof(&*self)weakSelf = self; 17 | 18 | #define kKeyWindow [UIApplication sharedApplication].keyWindow 19 | 20 | #define kScreenWidth ([UIScreen mainScreen].bounds.size.width) //屏幕宽度 21 | #define kScreenHeight ([UIScreen mainScreen].bounds.size.height) 22 | 23 | #define IS_PhoneXAll \ 24 | ({BOOL isPhoneX = NO;\ 25 | if (@available(iOS 11.0, *)) {\ 26 | isPhoneX = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0;\ 27 | }\ 28 | (isPhoneX);}) 29 | 30 | #define kSafeAreaBottomHeight (IS_PhoneXAll ? 34.0f : 0.0f) 31 | 32 | @interface GHPopView() 33 | 34 | /** 35 | * 背景 36 | */ 37 | @property (nonatomic, strong) UIButton *backView; 38 | 39 | @end 40 | @implementation GHPopView 41 | 42 | - (void)setContentViewHeight:(CGFloat)contentViewHeight { 43 | _contentViewHeight = contentViewHeight; 44 | } 45 | 46 | - (instancetype)init { 47 | if (self == [super init]) { 48 | [self configuration]; 49 | [self configDefaultUI]; 50 | } 51 | return self; 52 | } 53 | 54 | - (instancetype)initWithFrame:(CGRect)frame { 55 | if (self == [super initWithFrame:frame]) { 56 | [self configuration]; 57 | [self configDefaultUI]; 58 | } 59 | return self; 60 | } 61 | 62 | - (void)configuration { 63 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.7]; 64 | } 65 | 66 | - (void)configDefaultUI { 67 | self.frame = kKeyWindow.bounds; 68 | [self addSubview:self.backView]; 69 | [self.backView addSubview:self.contentView]; 70 | [kKeyWindow addSubview:self]; 71 | } 72 | 73 | #pragma mark - Event 74 | 75 | - (void)backViewClicked { 76 | [self dismiss]; 77 | } 78 | 79 | #pragma mark 显示 80 | - (void)show { 81 | 82 | [kKeyWindow bringSubviewToFront:self]; 83 | self.contentView.frame = CGRectMake(0, kScreenHeight, kScreenWidth, self.contentViewHeight); 84 | WS(weakSelf); 85 | [UIView animateWithDuration:animateDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 86 | weakSelf.contentView.frame = CGRectMake(0, kScreenHeight - weakSelf.contentViewHeight - kSafeAreaBottomHeight, kScreenWidth, weakSelf.contentViewHeight + kSafeAreaBottomHeight); 87 | } completion:^(BOOL finished) { 88 | 89 | }]; 90 | } 91 | 92 | #pragma mark 隐藏 93 | - (void)dismiss { 94 | WS(weakSelf); 95 | [UIView animateWithDuration:animateDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ 96 | weakSelf.backgroundColor = [UIColor clearColor]; 97 | weakSelf.contentView.frame = CGRectMake(0, kScreenHeight, kScreenWidth, weakSelf.contentViewHeight); 98 | } completion:^(BOOL finished) { 99 | [weakSelf.contentView removeFromSuperview]; 100 | [weakSelf.backView removeFromSuperview]; 101 | for (UIView *view in weakSelf.subviews) { 102 | [view removeFromSuperview]; 103 | } 104 | [weakSelf removeFromSuperview]; 105 | if (weakSelf.dimissFinish) { 106 | weakSelf.dimissFinish(); 107 | } 108 | }]; 109 | } 110 | 111 | - (UIButton *)backView { 112 | if (_backView == nil) { 113 | _backView = [[UIButton alloc] initWithFrame:[UIApplication sharedApplication].keyWindow.bounds]; 114 | [_backView addTarget:self action:@selector(backViewClicked) forControlEvents:UIControlEventTouchUpInside]; 115 | } 116 | return _backView; 117 | } 118 | 119 | - (UIView *)contentView { 120 | if (_contentView == nil) { 121 | _contentView = [[UIView alloc] init]; 122 | _contentView.backgroundColor = [UIColor whiteColor]; 123 | } 124 | return _contentView; 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHScrollTitles.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHScrollTitles.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHScrollTitles : UIView 14 | 15 | typedef void (^GHScrollTitlesDidClickTitleBlock)(NSInteger tag); 16 | typedef void (^GHScrollTitlesDidClickLeftBlock)(void); 17 | typedef void (^GHScrollTitlesDidClickRightBlock)(void); 18 | 19 | @property (nonatomic , strong) NSMutableArray *titles; 20 | 21 | @property (nonatomic , copy) GHScrollTitlesDidClickTitleBlock didClickTitleBlock; 22 | 23 | @property (nonatomic , copy) GHScrollTitlesDidClickLeftBlock didClickLeftBlock; 24 | 25 | @property (nonatomic , copy) GHScrollTitlesDidClickRightBlock didClickRightBlock; 26 | 27 | /** 菜单按钮移动位置 */ 28 | - (void)setMenusScrollView:(CGPoint)contentOffset; 29 | /** 滑动停止的时候 */ 30 | - (void)setMenusScrollViewEnd:(CGPoint)endOffset; 31 | 32 | /** 33 | * 刷新数据 34 | */ 35 | - (void)reloadData; 36 | 37 | /** 38 | * 重置所有数据(去掉红点,index = 0,数据清空) 39 | */ 40 | - (void)resetData; 41 | 42 | @end 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHScrollTitles.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHScrollTitles.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHScrollTitles.h" 10 | #import "GHSpecificationSelectionTitleModel.h" 11 | #import "GHSpecificationSelectionModel.h" 12 | #import "UIButton+Extension.h" 13 | 14 | @interface GHScrollTitles() 15 | 16 | /** 17 | * 左侧剪头 18 | */ 19 | @property (nonatomic , strong) UIButton *leftButton; 20 | 21 | /** 22 | * 右侧剪头 23 | */ 24 | @property (nonatomic , strong) UIButton *rightButton; 25 | 26 | @property (nonatomic , strong) UIView *bottomLine; 27 | 28 | @property (nonatomic , strong) UIScrollView *scrollView; 29 | 30 | /** 31 | * 装label的数组 32 | */ 33 | @property (nonatomic , strong) NSMutableArray *labels; 34 | 35 | /** 36 | * 记录当前序号 37 | */ 38 | @property (nonatomic , assign) NSInteger currentIndex; 39 | 40 | /** 41 | * 指示器 42 | */ 43 | @property (nonatomic , strong) UIView *indicator; 44 | 45 | @end 46 | @implementation GHScrollTitles 47 | 48 | - (void)resetData { 49 | // self.currentIndex = 0; 50 | // [self setMenusScrollView:CGPointZero]; 51 | [self reloadData]; 52 | } 53 | 54 | - (void)reloadData { 55 | 56 | for (NSInteger index = 0 ; index < self.titles.count; index++) { 57 | GHSpecificationSelectionTitleModel *titleModel = self.titles[index]; 58 | NSInteger count = 0; 59 | for (NSInteger j = 0 ; j < titleModel.skuList.count; j++) { 60 | GHSpecificationSelectionModel *skuModel = titleModel.skuList[j]; 61 | count += skuModel.count.integerValue; 62 | } 63 | titleModel.count = [NSString stringWithFormat:@"%ld",(long)count]; 64 | UILabel *label = self.labels[index]; 65 | if (titleModel.count.integerValue > 0) { 66 | [label pp_addBadgeWithText:titleModel.count]; 67 | if (titleModel.count.integerValue > 99) { 68 | [label pp_addBadgeWithText:@"99+"]; 69 | } 70 | [label pp_moveBadgeWithX:-20 Y:20]; 71 | [label pp_setBadgeLabelAttributes:^(PPBadgeLabel *badgeLabel) { 72 | badgeLabel.backgroundColor = KMainColor; 73 | }]; 74 | } else { 75 | [label pp_hiddenBadge]; 76 | } 77 | } 78 | } 79 | 80 | - (instancetype)initWithFrame:(CGRect)frame { 81 | if (self == [super initWithFrame:frame]) { 82 | [self addSubview:self.leftButton]; 83 | [self addSubview:self.rightButton]; 84 | [self addSubview:self.bottomLine]; 85 | [self addSubview:self.scrollView]; 86 | } 87 | return self; 88 | } 89 | 90 | - (void)setTitles:(NSMutableArray *)titles { 91 | _titles = titles; 92 | 93 | for (UILabel *label in self.labels) { 94 | [label removeFromSuperview]; 95 | } 96 | [self.labels removeAllObjects]; 97 | CGFloat width = self.scrollView.frame.size.width / 3.01f; 98 | 99 | for (NSInteger index = 0 ; index < titles.count; index++) { 100 | GHSpecificationSelectionTitleModel *titleModel = titles[index]; 101 | UILabel *label = [[UILabel alloc]init]; 102 | label.text = titleModel.color; 103 | label.tag = index; 104 | label.userInteractionEnabled = YES; 105 | if (index == 0) { 106 | label.textColor = KMainColor; 107 | } 108 | label.textAlignment = NSTextAlignmentCenter; 109 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(labelClick:)]; 110 | [label addGestureRecognizer:tap]; 111 | label.frame = CGRectMake(index * width, 0, width, self.scrollView.frame.size.height); 112 | [self.scrollView addSubview:label]; 113 | [self.labels addObject:label]; 114 | } 115 | 116 | self.scrollView.contentSize = CGSizeMake(width * titles.count, 0); 117 | [self.indicator removeFromSuperview]; 118 | UIView *indicator = [[UIView alloc]init]; 119 | self.indicator = indicator; 120 | indicator.backgroundColor = KMainColor; 121 | indicator.frame = CGRectMake((width -width * 0.25) * 0.5,CGRectGetMaxY(self.leftButton.frame) - 1, width * 0.25, 1); 122 | [self.scrollView addSubview:indicator]; 123 | } 124 | 125 | - (void)labelClick:(UITapGestureRecognizer *)tap{ 126 | NSInteger index = (NSInteger)tap.view.tag; 127 | self.currentIndex = index; 128 | if (self.didClickTitleBlock) { 129 | self.didClickTitleBlock(index); 130 | } 131 | } 132 | 133 | - (void)setMenusScrollView:(CGPoint)contentOffset{ 134 | 135 | CGFloat scale = contentOffset.x / kScreenWidth; 136 | if (scale < 0 || scale > self.scrollView.subviews.count - 1 - 1) return; 137 | self.currentIndex = scale; 138 | for (UILabel *label in self.labels) { 139 | label.textColor = [UIColor blackColor]; 140 | } 141 | 142 | UILabel *label = self.labels[self.currentIndex]; 143 | label.textColor = KMainColor; 144 | CGRect frame = self.indicator.frame; 145 | frame.origin.x = label.x + (label.width - self.indicator.width) * 0.5; 146 | self.indicator.frame = frame; 147 | } 148 | 149 | - (void)setMenusScrollViewEnd:(CGPoint)endOffset{ 150 | NSInteger index = endOffset.x / kScreenWidth; 151 | UILabel *label = self.labels[index]; 152 | CGFloat width = self.scrollView.frame.size.width; 153 | CGPoint titleOffset = self.scrollView.contentOffset; 154 | titleOffset.x = label.center.x - width * 0.5; 155 | if (titleOffset.x < 0) titleOffset.x = 0; 156 | CGFloat maxTitleOffsetX = self.scrollView.contentSize.width - width; 157 | if (maxTitleOffsetX < titleOffset.x) titleOffset.x = maxTitleOffsetX; 158 | [self.scrollView setContentOffset:titleOffset animated:YES]; 159 | } 160 | 161 | - (void)layoutSubviews { 162 | [super layoutSubviews]; 163 | 164 | } 165 | 166 | - (void)clicRightButton { 167 | 168 | if (self.currentIndex == self.labels.count - 1) {// 处理向左滚动越界 169 | return; 170 | } 171 | if (self.didClickRightBlock) { 172 | self.didClickRightBlock(); 173 | } 174 | } 175 | 176 | - (void)clickLeftButton { 177 | if (self.currentIndex == 0) {// 处理向右滚动越界 178 | return; 179 | } 180 | if (self.didClickLeftBlock) { 181 | self.didClickLeftBlock(); 182 | } 183 | } 184 | 185 | - (NSMutableArray *)labels { 186 | if (_labels == nil) { 187 | _labels = [NSMutableArray array]; 188 | } 189 | return _labels; 190 | } 191 | 192 | - (UIScrollView *)scrollView { 193 | if (_scrollView == nil) { 194 | _scrollView = [[UIScrollView alloc]init]; 195 | _scrollView.frame = CGRectMake(CGRectGetMaxX(self.leftButton.frame), 0, kScreenWidth - CGRectGetMaxX(self.leftButton.frame) - 50 , 50); 196 | _scrollView.scrollEnabled = NO; 197 | _scrollView.backgroundColor = [UIColor clearColor]; 198 | _scrollView.showsHorizontalScrollIndicator = NO; 199 | } 200 | return _scrollView; 201 | } 202 | 203 | - (UIView *)bottomLine { 204 | if (_bottomLine == nil) { 205 | _bottomLine = [[UIView alloc]init]; 206 | _bottomLine.backgroundColor = [UIColor lightGrayColor]; 207 | _bottomLine.frame = CGRectMake(0,CGRectGetMaxY(self.leftButton.frame) - 1, kScreenWidth, 0.3); 208 | } 209 | return _bottomLine; 210 | } 211 | 212 | - (UIButton *)rightButton { 213 | if (_rightButton == nil) { 214 | _rightButton = [[UIButton alloc]init]; 215 | _rightButton.frame = CGRectMake(kScreenWidth - 50, 0, 50, 50); 216 | UIView *line = [[UIView alloc]init]; 217 | line.frame = CGRectMake(0, 10, 0.3, 30); 218 | line.backgroundColor = [UIColor lightGrayColor]; 219 | [_rightButton addSubview:line]; 220 | [_rightButton setImage:[UIImage imageNamed:@"rightArrow"] forState:UIControlStateNormal]; 221 | [_rightButton addTarget:self action:@selector(clicRightButton) forControlEvents:UIControlEventTouchUpInside]; 222 | _rightButton.acceptEventInterval = 0.5; 223 | } 224 | return _rightButton; 225 | } 226 | 227 | - (UIButton *)leftButton { 228 | if (_leftButton == nil) { 229 | _leftButton = [[UIButton alloc]init]; 230 | [_leftButton setImage:[UIImage imageNamed:@"leftArrow"] forState:UIControlStateNormal]; 231 | _leftButton.frame = CGRectMake(0, 0, 50, 50); 232 | _leftButton.acceptEventInterval = 0.5; 233 | [_leftButton addTarget:self action:@selector(clickLeftButton) forControlEvents:UIControlEventTouchUpInside]; 234 | UIView *line = [[UIView alloc]init]; 235 | line.frame = CGRectMake(50 - 1, 10, 0.3, 30); 236 | line.backgroundColor = [UIColor lightGrayColor]; 237 | [_leftButton addSubview:line]; 238 | } 239 | return _leftButton; 240 | } 241 | 242 | @end 243 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHTableView.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/15. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GHTableView : UITableView 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHTableView.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/15. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHTableView.h" 10 | 11 | @implementation GHTableView 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style { 14 | if (self == [super initWithFrame:frame style:style]) { 15 | if (@available(iOS 11.0, *)) { 16 | self.estimatedRowHeight = 0; 17 | self.estimatedSectionHeaderHeight = 0; 18 | self.estimatedSectionFooterHeight = 0; 19 | } 20 | } 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHTextField.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef void(^GHTextFieldChangeBlock)(NSInteger count); 14 | 15 | 16 | typedef NS_ENUM (NSUInteger, GHCountFieldChangeType) { 17 | GHCountFieldChangeTypeAdd = 1, 18 | GHCountFieldChangeTypeSub, 19 | GHCountFieldChangeTypeNone, 20 | }; 21 | 22 | typedef NS_ENUM (NSUInteger, GHCountFieldMiniOrderType) { 23 | GHCountFieldMiniOrderTypeMultiple = 1, 24 | GHCountFieldMiniOrderTypeStep 25 | }; 26 | 27 | 28 | @interface GHTextField : UITextField 29 | 30 | 31 | /** 32 | 最大值 33 | */ 34 | @property (nonatomic , assign) NSInteger maxCount; 35 | 36 | /** 37 | 最小值 38 | */ 39 | @property (nonatomic , assign) NSInteger minCount; 40 | 41 | /** 42 | 当前值 43 | */ 44 | @property (nonatomic , assign) NSInteger count; 45 | 46 | /** 47 | 按钮类型 +/-/无 48 | */ 49 | @property (nonatomic , assign) GHCountFieldChangeType changeType; 50 | 51 | /** 52 | 起订量类型(非必设置属性,与miniOrder属性配合使用) 53 | */ 54 | @property (nonatomic, assign) GHCountFieldMiniOrderType miniOrderType; 55 | 56 | /** 57 | 最小起订数量(不设置则为普通步进增加,及1、2、3、4) 58 | */ 59 | @property (nonatomic , assign) NSInteger miniOrder; 60 | 61 | 62 | /** 63 | CountDidChangeBlock 64 | */ 65 | @property (nonatomic , copy) GHTextFieldChangeBlock countDidChangeBlock; 66 | 67 | /** 68 | 是否显示边框 69 | */ 70 | @property (nonatomic, assign) BOOL showBorderLine; 71 | 72 | @end 73 | 74 | NS_ASSUME_NONNULL_END 75 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHAlibabaSpecificationSelection/View/GHTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHTextField.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHTextField.h" 10 | 11 | /** 加减按钮字体大小 */ 12 | CGFloat buttonFontSize = 14; 13 | /** 边框宽度 */ 14 | CGFloat borderWidth = 1.0; 15 | 16 | @interface GHTextField () 17 | 18 | /** 左按钮 */ 19 | @property (nonatomic , strong) UIButton *leftButton; 20 | /** 右按钮 */ 21 | @property (nonatomic , strong) UIButton *rightButton; 22 | 23 | @property(nonatomic,strong)UIView *leftContentView; 24 | @property(nonatomic,strong)UIView *rightContentView; 25 | 26 | @end 27 | @implementation GHTextField 28 | 29 | - (void)dealloc { 30 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 31 | } 32 | 33 | #pragma mark - SetData 34 | - (void)setCount:(NSInteger)count { 35 | _count = count; 36 | [self setButtonEnabled:_count]; 37 | self.text = [NSString stringWithFormat:@"%ld",(long)count]; 38 | } 39 | 40 | - (void)setMinCount:(NSInteger)minCount { 41 | _minCount = minCount; 42 | [self setButtonEnabled:_count]; 43 | } 44 | 45 | - (void)setMaxCount:(NSInteger)maxCount { 46 | _maxCount = maxCount; 47 | [self setButtonEnabled:_count]; 48 | } 49 | 50 | - (void)setMiniOrder:(NSInteger)miniOrder { 51 | _miniOrder = miniOrder; 52 | } 53 | 54 | - (void)setMiniOrderType:(GHCountFieldMiniOrderType)miniOrderType { 55 | _miniOrderType = miniOrderType; 56 | } 57 | 58 | - (void)setShowBorderLine:(BOOL)showBorderLine { 59 | _showBorderLine = showBorderLine; 60 | if (_showBorderLine == YES) { 61 | self.layer.borderColor = UIColorFromRGB(0xF3F3F3).CGColor; 62 | self.layer.borderWidth = borderWidth; 63 | } 64 | } 65 | 66 | - (void)setButtonEnabled:(NSInteger)count{ 67 | if (self.minCount == count && self.maxCount == count) { 68 | self.leftButton.enabled = NO; 69 | self.rightButton.enabled = NO; 70 | } else { 71 | if (count <= self.minCount) { 72 | self.leftButton.enabled = NO; 73 | self.rightButton.enabled = YES; 74 | } else if (count >= self.maxCount) { 75 | self.rightButton.enabled = NO; 76 | self.leftButton.enabled = YES; 77 | } else { 78 | self.leftButton.enabled = YES; 79 | self.rightButton.enabled = YES; 80 | } 81 | } 82 | } 83 | 84 | #pragma mark - Event 85 | 86 | - (void)clickButton: (UIButton *)button { 87 | NSInteger oldCount = self.text.integerValue; 88 | 89 | NSInteger count = self.text.integerValue; 90 | GHCountFieldChangeType changeType = 0; 91 | if (button.tag == GHCountFieldChangeTypeAdd) { 92 | changeType = GHCountFieldChangeTypeAdd; 93 | if (self.miniOrder) { 94 | if (self.miniOrderType == GHCountFieldMiniOrderTypeMultiple) { 95 | count += self.miniOrder; 96 | if (count > self.maxCount) { 97 | count = self.maxCount - (self.maxCount % self.miniOrder); 98 | if (count == oldCount) { 99 | count = oldCount; 100 | } 101 | } 102 | }else { 103 | count ++; 104 | } 105 | }else { 106 | count ++; 107 | } 108 | [self setButtonEnabled:count]; 109 | } else if (button.tag == GHCountFieldChangeTypeSub) { 110 | changeType = GHCountFieldChangeTypeSub; 111 | if (self.miniOrder) { 112 | if (self.miniOrderType == GHCountFieldMiniOrderTypeMultiple) { 113 | if (count % self.miniOrder != 0) { 114 | count = count - (count % self.miniOrder); 115 | }else { 116 | count -= self.miniOrder; 117 | } 118 | }else { 119 | count --; 120 | } 121 | }else { 122 | count --; 123 | } 124 | [self setButtonEnabled:count]; 125 | } 126 | 127 | self.text = [NSString stringWithFormat:@"%ld",(long)count]; 128 | if (self.countDidChangeBlock) { 129 | self.countDidChangeBlock(self.text.integerValue); 130 | } 131 | } 132 | 133 | 134 | - (void)textDidChange:(NSNotification *)noti { 135 | 136 | NSInteger count = self.text.integerValue; 137 | 138 | [self setButtonEnabled:count]; 139 | 140 | NSLog(@"输入的数值为:%@", self.text); 141 | 142 | if (count > self.maxCount) { 143 | count = self.maxCount; 144 | if (self.miniOrder) { 145 | if (self.miniOrderType == GHCountFieldMiniOrderTypeMultiple) { 146 | count = self.maxCount - (self.maxCount % self.miniOrder); 147 | }else { 148 | count = self.maxCount; 149 | } 150 | } 151 | } 152 | 153 | 154 | if (count < self.minCount) { 155 | count = self.minCount; 156 | } 157 | 158 | NSLog(@"逻辑计算改变后的数值为:%@", @(count)); 159 | 160 | self.count = count; 161 | 162 | if (self.countDidChangeBlock) { 163 | self.countDidChangeBlock(self.text.integerValue); 164 | } 165 | } 166 | 167 | #pragma mark - Init 168 | 169 | - (instancetype)initWithFrame:(CGRect)frame { 170 | self = [super initWithFrame:frame]; 171 | if (self) { 172 | self.backgroundColor = [UIColor whiteColor]; 173 | self.keyboardType = UIKeyboardTypeNumberPad; 174 | self.font = [UIFont systemFontOfSize:12]; 175 | self.textColor = UIColorFromRGB(0x333333); 176 | self.textAlignment = NSTextAlignmentCenter; 177 | self.leftViewMode = UITextFieldViewModeAlways; 178 | self.rightViewMode = UITextFieldViewModeAlways; 179 | 180 | // 左按钮 181 | UIButton *leftButton = [[UIButton alloc] init]; 182 | leftButton.tag = GHCountFieldChangeTypeSub; 183 | leftButton.imageView.contentMode = UIViewContentModeScaleToFill; 184 | [leftButton setTitle:@"-" forState:UIControlStateNormal]; 185 | leftButton.titleLabel.font = [UIFont systemFontOfSize:14]; 186 | [leftButton setTitleColor:UIColorFromRGB(0x333333) forState:UIControlStateNormal]; 187 | [leftButton setTitleColor:UIColorFromRGB(0xE4E3E4) forState:UIControlStateDisabled]; 188 | 189 | leftButton.layer.borderWidth = borderWidth; 190 | leftButton.layer.borderColor = UIColorFromRGB(0xF3F3F3).CGColor; 191 | [leftButton addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside]; 192 | self.leftButton = leftButton; 193 | 194 | UIView *leftContentView = [[UIView alloc] init]; 195 | leftContentView.backgroundColor = [UIColor whiteColor]; 196 | [leftContentView addSubview:leftButton]; 197 | self.leftContentView = leftContentView; 198 | self.leftView = leftContentView; 199 | 200 | // 右按钮 201 | UIButton *rightButton = [[UIButton alloc] init]; 202 | rightButton.tag = GHCountFieldChangeTypeAdd; 203 | rightButton.imageView.contentMode = UIViewContentModeScaleToFill; 204 | [rightButton setTitle:@"+" forState:UIControlStateNormal]; 205 | rightButton.titleLabel.font = [UIFont systemFontOfSize:14]; 206 | [rightButton setTitleColor:UIColorFromRGB(0x333333) forState:UIControlStateNormal]; 207 | [rightButton setTitleColor:UIColorFromRGB(0xE4E3E4) forState:UIControlStateDisabled]; 208 | // [rightButton setBackgroundColor:[UIColor whiteColor] forState:UIControlStateNormal]; 209 | // [rightButton setBackgroundColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; 210 | rightButton.layer.borderWidth = borderWidth; 211 | rightButton.layer.borderColor = UIColorFromRGB(0xF3F3F3).CGColor; 212 | [rightButton addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside]; 213 | self.rightButton = rightButton; 214 | 215 | UIView *rightContentView = [[UIView alloc] init]; 216 | rightContentView.backgroundColor = [UIColor whiteColor]; 217 | [rightContentView addSubview:rightButton]; 218 | self.rightContentView = rightContentView; 219 | self.rightView = rightContentView; 220 | 221 | [[NSNotificationCenter defaultCenter] addObserver:self 222 | selector:@selector(textDidChange:) 223 | name:UITextFieldTextDidChangeNotification 224 | object:self]; 225 | } 226 | return self; 227 | } 228 | 229 | - (void)layoutSubviews { 230 | [super layoutSubviews]; 231 | 232 | // 重新根据控件的Frame布局设置两个按钮 233 | self.leftButton.frame = CGRectMake(0, 0, self.height+5, self.height); 234 | self.rightButton.frame = CGRectMake(0, 0, self.height+5, self.height); 235 | self.leftContentView.frame = CGRectMake(0, 0, self.height+5, self.height); 236 | self.rightContentView.frame = CGRectMake(0, 0, self.height+5, self.height); 237 | 238 | // 重新根据控件的Frame布局计算两个按钮的文字大小(比例计算为按钮宽高25时,字体为kFont(12)) 239 | self.leftButton.titleLabel.font = [UIFont systemFontOfSize:buttonFontSize * self.height/25]; 240 | self.rightButton.titleLabel.font = [UIFont systemFontOfSize:buttonFontSize * self.height/25]; 241 | 242 | [super layoutSubviews]; 243 | } 244 | 245 | #pragma mark - 去掉长按手势 246 | - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 247 | if ([UIMenuController sharedMenuController]) { 248 | [UIMenuController sharedMenuController].menuVisible = NO; 249 | } 250 | return NO; 251 | } 252 | 253 | 254 | @end 255 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHHTTPSessionManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHHTTPSessionManager.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/18. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef void (^FinishedBlock)(id responseObject, NSError *error); 14 | 15 | @interface GHHTTPSessionManager : AFHTTPSessionManager 16 | 17 | + (instancetype)sharedManager; 18 | 19 | - (void)getGoodDetailsWithUrl:(NSString *)url finishedBlock:(FinishedBlock)finishedBlock; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/GHHTTPSessionManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHHTTPSessionManager.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/18. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "GHHTTPSessionManager.h" 10 | 11 | @implementation GHHTTPSessionManager 12 | 13 | + (instancetype)sharedManager { 14 | 15 | static GHHTTPSessionManager *_instance = nil; 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | NSURL *baseUrl = [NSURL URLWithString:@""]; 19 | NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; 20 | config.timeoutIntervalForRequest = 30; 21 | [_instance.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 22 | _instance = [[self alloc] initWithBaseURL:baseUrl sessionConfiguration:config]; 23 | _instance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json",@"text/html",@"text/plain", @"text/javascript", nil]; 24 | }); 25 | return _instance; 26 | } 27 | 28 | - (void)getGoodDetailsWithUrl:(NSString *)url finishedBlock:(FinishedBlock)finishedBlock { 29 | [[GHHTTPSessionManager sharedManager] GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) { 30 | } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 31 | finishedBlock(responseObject,nil); 32 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 33 | finishedBlock(nil,error); 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | $(DEVELOPMENT_LANGUAGE) 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleVersion 25 | 1 26 | LSRequiresIPhoneOS 27 | 28 | UILaunchStoryboardName 29 | LaunchScreen 30 | UIMainStoryboardFile 31 | Main 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/11/27. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #ifndef PrefixHeader_pch 10 | #define PrefixHeader_pch 11 | 12 | #define StrValid(f) (f!=nil && [f isKindOfClass:[NSString class]] && ![f isEqualToString:@""]) 13 | 14 | #define ValidStr(f) StrValid(f) 15 | #define ValidDict(f) (f!=nil && [f isKindOfClass:[NSDictionary class]] && [f count]>0) 16 | #define ValidArray(f) (f!=nil && [f isKindOfClass:[NSArray class]] && [f count]>0) 17 | 18 | #define kScreenWidth ([UIScreen mainScreen].bounds.size.width) //屏幕宽度 19 | #define kScreenHeight ([UIScreen mainScreen].bounds.size.height) //屏幕高度 20 | #define kNavHeight kSafeAreaTopHeight //导航的高度 21 | #define kSafeAreaBottomHeight (IS_PhoneXAll ? 34.0f : 0.0f) 22 | // StatusbarH + NavigationH 23 | #define kSafeAreaTopHeight (IS_PhoneXAll ? 88.0f : 64.0f) 24 | // StatusBarHeight 25 | #define kStatusBarHeight (IS_PhoneXAll ? 44.0f : 20.0f) 26 | // NavigationBarHeigth 27 | #define kNavBarHeight 44.0f 28 | //kTabBarHeight 29 | #define kTabBarHeight 49.0f 30 | // TabBarHeight+kSafeAreaBottomHeight 31 | #define kBottomAreaHeight (kTabBarHeight + kSafeAreaBottomHeight) 32 | 33 | #define IS_PhoneXAll \ 34 | ({BOOL isPhoneX = NO;\ 35 | if (@available(iOS 11.0, *)) {\ 36 | isPhoneX = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0;\ 37 | }\ 38 | (isPhoneX);}) 39 | 40 | #define UIColorFromRGB(rgbValue) UIColorFromRGBA(rgbValue,1.0) 41 | 42 | #define UIColorFromRGBA(rgbValue,a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:a] 43 | 44 | #define weakself(self) __weak __typeof(self) weakSelf = self 45 | #ifdef DEBUG 46 | #define NSLog(format, ...) printf("%s\n", [[NSString stringWithFormat:(format), ##__VA_ARGS__] UTF8String]); 47 | #else 48 | #define NSLog(...) {} 49 | #endif 50 | 51 | #define KAlert(title,msg) [[[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil] show] 52 | 53 | #define KMainColor UIColorFromRGB(0x017fff) 54 | #import "UIView+Extension.h" 55 | #import "Masonry.h" 56 | #import "ToastTool.h" 57 | #import "PPBadgeView.h" 58 | 59 | #endif /* PrefixHeader_pch */ 60 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "GHAlibabaSpecificationSelection.h" 11 | #import "GHHTTPSessionManager.h" 12 | #import "MJExtension.h" 13 | #import "GHSpecificationSelectionModel.h" 14 | #import "GHSpecificationSelectionTitleModel.h" 15 | #import "GHSpecificationSelectionImageModel.h" 16 | #import "GHPopView.h" 17 | #import "UIView+ActivityIndicator.h" 18 | #import "UIImage+ViewToImage.h" 19 | #import "GHButton.h" 20 | #import "UIView+EmptyPage.h" 21 | 22 | @interface ViewController () 23 | 24 | @property (nonatomic , strong) GHAlibabaSpecificationSelection *alibabaSpecificationSelection; 25 | 26 | @property (nonatomic , strong) UIWebView *webView; 27 | 28 | @property (nonatomic , strong) UIButton *shopCar; 29 | 30 | @property (nonatomic , assign) CGRect shopCarRect; 31 | 32 | @property (nonatomic , assign) NSInteger allCount; 33 | 34 | @property (nonatomic , strong) NSArray *dataArray; 35 | 36 | @property (nonatomic , strong) NSArray *specifications; 37 | 38 | @property (nonatomic , strong) NSArray *colors; 39 | 40 | @property (nonatomic , strong) NSDictionary *sectePrice; 41 | 42 | @end 43 | 44 | @implementation ViewController 45 | 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | self.view.backgroundColor = [UIColor whiteColor]; 49 | [self setupUI]; 50 | 51 | [self loadData]; 52 | } 53 | 54 | - (void)setupUI { 55 | 56 | GHButton *shopCar = [[GHButton alloc]init]; 57 | self.shopCar = shopCar; 58 | [shopCar setImage:[UIImage imageNamed:@"shopCar"] forState:UIControlStateNormal]; 59 | [shopCar sizeToFit]; 60 | [shopCar addTarget:self action:@selector(clickShopCar) forControlEvents:UIControlEventTouchUpInside]; 61 | 62 | GHButton *home = [[GHButton alloc]init]; 63 | [home addTarget:self action:@selector(clickHome) forControlEvents:UIControlEventTouchUpInside]; 64 | [home setImage:[UIImage imageNamed:@"home"] forState:UIControlStateNormal]; 65 | [home sizeToFit]; 66 | 67 | self.navigationItem.leftBarButtonItems = @[[[UIBarButtonItem alloc]initWithCustomView:home],[[UIBarButtonItem alloc]initWithCustomView:shopCar]]; 68 | 69 | GHButton *show = [[GHButton alloc]init]; 70 | [show setTitle:@"弹出" forState:UIControlStateNormal]; 71 | show.titleLabel.font = [UIFont systemFontOfSize:14]; 72 | [show setTitleColor:KMainColor forState:UIControlStateNormal]; 73 | [show sizeToFit]; 74 | [show addTarget:self action:@selector(clickShow) forControlEvents:UIControlEventTouchUpInside]; 75 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:show]; 76 | 77 | self.navigationItem.title = @"GHAlibabaSpecificationSelection"; 78 | UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)]; 79 | self.webView = webView; 80 | webView.scrollView.backgroundColor = [UIColor whiteColor]; 81 | webView.delegate = self; 82 | [self.view addSubview:webView]; 83 | [ToastTool makeToastActivity:webView]; 84 | } 85 | 86 | - (void)viewDidLayoutSubviews { 87 | [super viewDidLayoutSubviews]; 88 | CGRect shopCarRect = [self.navigationController.view convertRect:self.shopCar.frame fromView:self.shopCar.superview]; 89 | self.shopCarRect = shopCarRect; 90 | } 91 | 92 | - (void)clickHome { 93 | NSString *path = [[NSBundle mainBundle] pathForResource:@"GHAlibabaSpecificationSelection" ofType:@"html"]; 94 | [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]]; 95 | } 96 | 97 | - (void)clickShopCar { 98 | 99 | } 100 | 101 | - (void)clickShow { 102 | UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"GHAlibabaSpecificationSelection" message:@"选择类型" preferredStyle:UIAlertControllerStyleActionSheet]; 103 | weakself(self); 104 | UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"带颜色导航器" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 105 | [weakSelf.alibabaSpecificationSelection setSkuList:weakSelf.specifications colors:weakSelf.colors sectePrice:weakSelf.sectePrice]; 106 | [weakSelf.alibabaSpecificationSelection show]; 107 | 108 | }]; 109 | 110 | UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"不带颜色导航器" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 111 | [weakSelf.alibabaSpecificationSelection setSkuList:weakSelf.specifications colors:nil sectePrice:weakSelf.sectePrice]; 112 | [weakSelf.alibabaSpecificationSelection show]; 113 | }]; 114 | 115 | UIAlertAction *action3 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { 116 | }]; 117 | 118 | [actionSheet addAction:action1]; 119 | [actionSheet addAction:action2]; 120 | [actionSheet addAction:action3]; 121 | [self presentViewController:actionSheet animated:YES completion:nil]; 122 | } 123 | 124 | - (void)webViewDidFinishLoad:(UIWebView *)webView API_DEPRECATED("No longer supported.", ios(2.0, 12.0)) { 125 | [ToastTool hideToastActivity:webView]; 126 | } 127 | 128 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error API_DEPRECATED("No longer supported.", ios(2.0, 12.0)) { 129 | [ToastTool hideToastActivity:webView]; 130 | } 131 | 132 | - (void)loadData{ 133 | [self clickHome]; 134 | [self.view hideEmptyPage]; 135 | [ToastTool makeToastActivity:self.view]; 136 | weakself(self); 137 | NSString *url = @"http://mock-api.com/7zxXywz3.mock/data"; 138 | [[GHHTTPSessionManager sharedManager] getGoodDetailsWithUrl:url finishedBlock:^(id _Nonnull responseObject, NSError * _Nonnull error) { 139 | if (!responseObject) { 140 | [weakSelf.view showEmptyPage:kSafeAreaTopHeight imageName:@"emptyPage" imageFrame:CGRectMake((kScreenWidth - 72) * 0.5, (kScreenHeight - 72) * 0.5 - kSafeAreaTopHeight, 72, 72) didClickReloadBlock:^{ 141 | [weakSelf loadData]; 142 | }]; 143 | return ; 144 | } 145 | NSDictionary *dict = (NSDictionary *)responseObject; 146 | NSArray *colors = dict[@"color"]; 147 | NSArray *data = dict[@"data"]; 148 | NSDictionary *sectePrice = dict[@"sectePrice"]; 149 | NSMutableArray *specifications = [NSMutableArray array]; 150 | for (NSDictionary *dataDict in data) { 151 | GHSpecificationSelectionModel *skuModel = [GHSpecificationSelectionModel mj_objectWithKeyValues:dataDict]; 152 | NSArray *images = dataDict[@"images"]; 153 | NSMutableArray *imagesArray = [NSMutableArray array]; 154 | for (NSDictionary *imageDict in images) { 155 | GHSpecificationSelectionImageModel *specificationSelectionImageModel = [GHSpecificationSelectionImageModel mj_objectWithKeyValues:imageDict]; 156 | [imagesArray addObject:specificationSelectionImageModel]; 157 | } 158 | skuModel.images = imagesArray.copy; 159 | [specifications addObject:skuModel]; 160 | } 161 | NSMutableArray *dataArray = [NSMutableArray array]; 162 | for (NSInteger i = 0; i < colors.count; i++) { 163 | GHSpecificationSelectionTitleModel *alibabaSpecificationSelectionModel = [[GHSpecificationSelectionTitleModel alloc]init]; 164 | NSString *colorStr = colors[i]; 165 | for (NSInteger j = 0; j < specifications.count; j++) { 166 | GHSpecificationSelectionModel *skuModel = specifications[j]; 167 | NSMutableArray *dataArray = [NSMutableArray array]; 168 | if ([skuModel.color isEqualToString:colorStr]) { 169 | [dataArray addObject:skuModel]; 170 | } 171 | alibabaSpecificationSelectionModel.skuList = dataArray.copy; 172 | } 173 | alibabaSpecificationSelectionModel.color = colorStr; 174 | [dataArray addObject:alibabaSpecificationSelectionModel]; 175 | } 176 | 177 | [ToastTool makeToastActivity:weakSelf.view toastToolCompleteBlock:^{ 178 | [ToastTool makeToast:@"加载成功" targetView:weakSelf.view]; 179 | weakSelf.specifications = specifications; 180 | weakSelf.sectePrice = sectePrice; 181 | weakSelf.colors = colors; 182 | }]; 183 | 184 | if (error) { 185 | [weakSelf.view showEmptyPage:kSafeAreaTopHeight imageName:@"emptyPage" imageFrame:CGRectMake((kScreenWidth - 72) * 0.5, (kScreenHeight - 72) * 0.5, 72, 72) didClickReloadBlock:^{ 186 | [weakSelf loadData]; 187 | }]; 188 | } 189 | }]; 190 | } 191 | 192 | - (GHAlibabaSpecificationSelection *)alibabaSpecificationSelection { 193 | if (_alibabaSpecificationSelection == nil) { 194 | _alibabaSpecificationSelection = [[GHAlibabaSpecificationSelection alloc]init]; 195 | _alibabaSpecificationSelection.contentViewHeight = 500; 196 | _alibabaSpecificationSelection.shopCarRect = self.shopCarRect; 197 | weakself(self); 198 | _alibabaSpecificationSelection.getDataBlock = ^(NSArray * _Nonnull dataArray) { 199 | for (NSInteger i = 0 ; i < dataArray.count; i ++) { 200 | GHSpecificationSelectionTitleModel *titleModel = dataArray[i]; 201 | for (NSInteger j = 0 ; j < titleModel.skuList.count; j++) { 202 | GHSpecificationSelectionModel *skuModel = titleModel.skuList[j]; 203 | weakSelf.allCount += skuModel.count.integerValue; 204 | } 205 | } 206 | weakSelf.dataArray = dataArray; 207 | [weakSelf.shopCar pp_addBadgeWithText:[NSString stringWithFormat:@"%@",weakSelf.allCount <= 99 ? [NSString stringWithFormat:@"%lu",(unsigned long)weakSelf.allCount]:@"99+"]]; 208 | }; 209 | } 210 | return _alibabaSpecificationSelection; 211 | } 212 | 213 | @end 214 | -------------------------------------------------------------------------------- /GHAlibabaSpecificationSelectionDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GHAlibabaSpecificationSelectionDemo 4 | // 5 | // Created by mac on 2019/10/14. 6 | // Copyright © 2019 macBookPro. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 GHome 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '9.0' 3 | source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git' 4 | inhibit_all_warnings! 5 | 6 | pod 'AFNetworking', '3.1.0' 7 | pod 'MJExtension', '3.0.10' 8 | pod 'MBProgressHUD', '0.9.2' 9 | pod 'SDWebImage', '~> 5.0' 10 | pod 'Masonry', '1.0.0' 11 | pod 'PPBadgeView','2.1.0' 12 | pod 'YYModel' 13 | 14 | target 'GHAlibabaSpecificationSelectionDemo' do 15 | # Comment the next line if you don't want to use dynamic frameworks 16 | use_frameworks! 17 | 18 | # Pods for GHAlibabaSpecificationSelectionDemo 19 | 20 | end 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ![未标题-2.png](https://upload-images.jianshu.io/upload_images/1419035-5554f91741be4c55.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 5 | 6 | #### 前言 7 | 8 | 仿阿里巴巴规格选择器,如果你有更好方案,请联系我,45329453@qq.com 9 | 10 | 如果这个`demo`对你有帮助,请点一个★是对我最大的鼓励,感激不尽! 11 | 12 | 13 | #### Features 14 | 15 | > 初始化确定按钮颜色置灰,不可点击。 16 | > 17 | > 当 `spu` 颜色数量大于**1**个时,显示颜色导航,底部列表可以滚动,反之隐藏,布局自适应。 18 | > 19 | > 如果有颜色导航,输入或点击 `+` `- ` 按钮,颜色导航对应的颜色数字同步变化,如果数量大于**99**显示**99**+;如果数量小于**1**不显示。 20 | > 21 | > 点击`>` `<` 底部列表和颜色导航同步滚动。 22 | > 23 | > 输入或点击 `+` `- ` 按钮,当按 `+ `到最大库存 `+ ` 置灰;当按 `-` 到0 `-` 置灰。 24 | > 25 | > 点击输入框。键盘弹出,[规格选择器](####规格选择器) 上移;点击**完成**,键盘收回,[规格选择器](####规格选择器) 回到原位。 26 | > 27 | > 点击颜色导航条的颜色标签,高亮被点击颜色标签并滚动到屏幕中心,底部列表滑动到对应位置,同时切换 `sku` 图片。 28 | > 29 | > 当输入或者点击数量大于**1**,确定按钮可点击,颜色高亮。 30 | > 31 | > 当库存不足的时候,输入框下显示`库存不足`标签。 32 | > 33 | > 输入框不可输入 `0` ,` .` 等特殊符号。 34 | > 35 | > 列表行自适应高度,布局中心对齐。 36 | > 37 | > 点击背景遮罩或者 `x ` ,收回弹窗。 38 | > 39 | > 动态输入监听,同步显示,根据输入判定确定按钮状态。 40 | > 41 | > 数据模型重新组装。 42 | > 43 | > 适配`IPhoneX`及以上系列。 44 | > 45 | > 增加加入到购物车抛物线动画,购物车同步用户选择 `sku` 数量。 46 | 47 | 48 | 49 | #### 演示 50 | 51 | 52 | ![Untitled.gif](https://upload-images.jianshu.io/upload_images/1419035-8bdb57d69448450d.gif?imageMogr2/auto-orient/strip) 53 | 54 | #### 使用 55 | 56 | `demo` 数据是从接口获取,需要连接`wifi`或蜂窝网络。 57 | 58 | 数据结构 **(点击箭头展开/收起)** 59 |
{ 60 | "data": [ 61 | { 62 | "arrival_cycle": 5, 63 | "sku_code": "000001", 64 | "spu_id": 7280, 65 | "sku_name": "我是测试数据黑色000001", 66 | "virtual_stock": 9999, 67 | "sale_price": "1.80", 68 | "images": [ 69 | { 70 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-0a54dde4c9663e36.png" 71 | } 72 | ], 73 | "specifications": "我是测试数据黑色000001", 74 | "color": "黑", 75 | "mini_order": 1, 76 | "unit": "个", 77 | "sku_id": 1 78 | }, 79 | { 80 | "arrival_cycle": 5, 81 | "sku_code": "000002", 82 | "spu_id": 7280, 83 | "sku_name": "我是测试数据红色000001", 84 | "virtual_stock": 9999, 85 | "sale_price": "28.80", 86 | "images": [ 87 | { 88 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-8739c526d2790690.png" 89 | } 90 | ], 91 | "specifications": "1.5平方我是测试数据红色000001", 92 | "color": "红", 93 | "mini_order": 2, 94 | "unit": "台", 95 | "sku_id": 2 96 | }, 97 | { 98 | "arrival_cycle": 5, 99 | "sku_code": "000003", 100 | "sku_name": "我是测试数据黄色000003", 101 | "virtual_stock": 9999, 102 | "sale_price": "88.80", 103 | "images": [ 104 | { 105 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-4dd868e628b61cc6.png" 106 | } 107 | ], 108 | "specifications": "我是测试数据黄色000003", 109 | "spu_code": "101191", 110 | "color": "黄", 111 | "mini_order": 3, 112 | "unit": "把", 113 | "sku_id": 3 114 | }, 115 | { 116 | "arrival_cycle": 5, 117 | "sku_code": "000004", 118 | "sku_name": "我是测试数据绿色000004", 119 | "virtual_stock": 9999, 120 | "sale_price": "88.80", 121 | "images": [ 122 | { 123 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-44c60adcf6a74843.png" 124 | } 125 | ], 126 | "specifications": "我是测试数据绿色000004", 127 | "spu_code": "000004", 128 | "color": "绿", 129 | "mini_order": 4, 130 | "unit": "只", 131 | "sku_id": 4 132 | }, 133 | { 134 | "arrival_cycle": 5, 135 | "sku_code": "000006", 136 | "sku_name": "我是测试数据蓝色000005", 137 | "virtual_stock": 9999, 138 | "sale_price": "88.80", 139 | "images": [ 140 | { 141 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-08b4629d7bba016c.png" 142 | } 143 | ], 144 | "specifications": "我是测试数据蓝色000005", 145 | "spu_code": "000006", 146 | "color": "蓝", 147 | "mini_order": 5, 148 | "unit": "双", 149 | "sku_id": 5 150 | }, 151 | { 152 | "arrival_cycle": 5, 153 | "sku_code": "000006", 154 | "sku_name": "我是测试数据白色000006", 155 | "virtual_stock": 9999, 156 | "sale_price": "88.80", 157 | "images": [ 158 | { 159 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-f9ecb0bbc4a2a405.png" 160 | } 161 | ], 162 | "specifications": "我是测试数据白色000006", 163 | "spu_code": "000006", 164 | "color": "白", 165 | "mini_order": 6, 166 | "unit": "呵呵", 167 | "sku_id": 6 168 | }, 169 | { 170 | "arrival_cycle": 5, 171 | "sku_code": "000007", 172 | "spu_id": 7280, 173 | "sku_name": "1.5平方我是测试数据黄绿000007", 174 | "virtual_stock": 9999, 175 | "sale_price": "88.80", 176 | "images": [ 177 | { 178 | "img_url": "https://upload-images.jianshu.io/upload_images/1419035-219ce100b765c4e6.png" 179 | } 180 | ], 181 | "specifications": "1.5平方我是测试数据黄绿000007", 182 | "color": "黄绿", 183 | "mini_order": 7, 184 | "unit": "吨", 185 | "sku_id": 7 186 | } 187 | ], 188 | "sectePrice": { 189 | "max_price": "3107.00", 190 | "min_price": "88.80" 191 | }, 192 | "specifications": [ 193 | "1.5平方", 194 | "2.5平方", 195 | "4平方", 196 | "6平方", 197 | "10平方", 198 | "16平方", 199 | "25平方", 200 | "35平方", 201 | "50平方" 202 | ], 203 | "color": [ 204 | "红", 205 | "黄", 206 | "绿", 207 | "蓝", 208 | "黑", 209 | "白", 210 | "黄绿" 211 | ] 212 | }
213 | 214 | `GHSpecificationSelectionTitleModel` 颜色导航器模型 215 | 216 | `GHSpecificationSelectionModel` `sku` 模型 217 | 218 | `GHSpecificationSelectionImageModel` 图片模型 219 | 220 | 221 | 222 | **更新依赖库** 223 | 224 | ``` 225 | cd 项目路径 226 | ``` 227 | 228 | ``` 229 | pod install 230 | ``` 231 | 232 | ![carbon.png](https://upload-images.jianshu.io/upload_images/1419035-879de1e610062d8f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 233 | 234 | 235 | 236 | 如果更新 `Pod` 遇到问题,可以参考这篇[文章](https://www.jianshu.com/p/cd057b2055c0) 237 | 238 | 1.初始化对象 239 | 240 | `GHAlibabaSpecificationSelection`继承 `GHPopView` ,`GHPopView` 已经封装好**弹出**/**收回**动画,外部无需重复处理。 241 | 242 | ```objective-c 243 | - (void)show; 244 | - (void)dismiss 245 | ``` 246 | `GHPopView`暴露一个`contentView`容器视图,子控件可以直接添加到这个视图。 247 | 248 | ```objective-c 249 | @property (nonatomic, strong) UIView *contentView; 250 | ``` 251 | 252 | 其中`contentViewHeight`是`contentView`容器视图的高度,初始化的时候必传 253 | 254 | `#import GHAlibabaSpecificationSelection.h` 255 | 256 | ![carbon.png](https://upload-images.jianshu.io/upload_images/1419035-b4178d2971b737e6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 257 | 258 | 2.传入数据 259 | 260 | 261 | ```objective-c 262 | /** 263 | * 数据源 264 | * @param skuList 装skuModel数组 265 | * @param colors 颜色数组 非必传,如果为空,不显示颜色导航 266 | * @param sectePrice 价格区间字典 267 | */ 268 | ``` 269 | 270 | ![carbon-2.png](https://upload-images.jianshu.io/upload_images/1419035-d19fe88c461f9de7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 271 | 272 | 3.取出用户选择 273 | 274 | ![carbon-4.png](https://upload-images.jianshu.io/upload_images/1419035-0c222359f18ec0b3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 275 | 276 | 277 | 278 | 4.重置数据 279 | 280 | > 在这个方法内部清除所有`count`。 281 | > 282 | > 底部`scrollview` 滚动到初始化状态。 283 | > 284 | > 底部确定按钮初始化状态。 285 | > 286 | > `scrollTitles`初始化。 287 | 288 | 289 | ```objective-c 290 | - (void) resetData; 291 | ``` 292 | 293 | 294 | #### 与我联系 295 | 296 | 45329453@qq.com 297 | 298 | -------------------------------------------------------------------------------- /Untitled.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shabake/GHAlibabaSpecificationSelectionDemo/4d5f7417dffb86b032ed7a2782ac2915de656137/Untitled.gif --------------------------------------------------------------------------------