├── .DS_Store ├── LICENSE.txt ├── MOFSPickerManager.podspec ├── MOFSPickerManagerDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── luoyuan.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── MOFSPickerManagerDemo.xcscheme └── xcuserdata │ └── luoyuan.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── MOFSPickerManagerDemo ├── .DS_Store ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── MOFSPickerManager │ ├── LQYPickerView.h │ ├── LQYPickerView.m │ ├── MOFSAddressModel.h │ ├── MOFSAddressModel.m │ ├── MOFSAddressPickerView.h │ ├── MOFSAddressPickerView.m │ ├── MOFSDatePicker.h │ ├── MOFSDatePicker.m │ ├── MOFSPickerManager.h │ ├── MOFSPickerManager.m │ ├── MOFSPickerView.h │ ├── MOFSPickerView.m │ ├── MOFSToolView.h │ ├── MOFSToolView.m │ ├── province_data.json │ └── province_data.xml ├── ViewController.h ├── ViewController.m └── main.m ├── MOFSPickerManagerDemoTests ├── Info.plist └── MOFSPickerManagerDemoTests.m ├── MOFSPickerManagerDemoUITests ├── Info.plist └── MOFSPickerManagerDemoUITests.m ├── README.md └── images ├── Simulator Screen Shot 2016年9月5日 下午9.17.07.png ├── Simulator Screen Shot 2016年9月5日 下午9.17.31.png ├── Simulator Screen Shot 2016年9月5日 下午9.17.48.png ├── pod_search.png └── tap9.gif /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/.DS_Store -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 luoyuan Corporation, http://www.jianshu.com/u/f4284f2cc646 2 | 3 | MIT LICENSE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /MOFSPickerManager.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint MOFSPickerManager.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "MOFSPickerManager" 19 | s.version = "3.0.1" 20 | s.summary = "PickerManager for iOS" 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | s.description = <<-DESC 28 | iOS PickerView整合,一行代码调用(省市区三级联动+日期选择+普通选择) 29 | DESC 30 | 31 | s.homepage = "https://github.com/memoriesofsnows/MOFSPickerManagerDemo.git" 32 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 33 | 34 | 35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 36 | # 37 | # Licensing your code is important. See http://choosealicense.com for more info. 38 | # CocoaPods will detect a license file if there is a named LICENSE* 39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 40 | # 41 | 42 | s.license = "MIT" 43 | # s.license = { :type => "MIT", :file => "LICENSE" } 44 | 45 | 46 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 47 | # 48 | # Specify the authors of the library, with email addresses. Email addresses 49 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 50 | # accepts just a name if you'd rather not provide an email address. 51 | # 52 | # Specify a social_media_url where others can refer to, for example a twitter 53 | # profile URL. 54 | # 55 | 56 | s.author = { "memoriesofsnows" => "luoyuant@163.com" } 57 | # Or just: s.author = "memoriesofsnows" 58 | # s.authors = { "memoriesofsnows" => "" } 59 | s.social_media_url = "http://www.jianshu.com/u/f4284f2cc646" 60 | 61 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 62 | # 63 | # If this Pod runs only on iOS or OS X, then specify the platform and 64 | # the deployment target. You can optionally include the target after the platform. 65 | # 66 | 67 | # s.platform = :ios 68 | s.platform = :ios, "7.0" 69 | 70 | # When using multiple platforms 71 | # s.ios.deployment_target = "7.0" 72 | # s.osx.deployment_target = "10.7" 73 | # s.watchos.deployment_target = "2.0" 74 | # s.tvos.deployment_target = "9.0" 75 | 76 | 77 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 78 | # 79 | # Specify the location from where the source should be retrieved. 80 | # Supports git, hg, bzr, svn and HTTP. 81 | # 82 | 83 | s.source = { :git => "https://github.com/memoriesofsnows/MOFSPickerManagerDemo.git", :tag => "#{s.version}" } 84 | 85 | 86 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 87 | # 88 | # CocoaPods is smart about how it includes source code. For source files 89 | # giving a folder will include any swift, h, m, mm, c & cpp files. 90 | # For header files it will include any header in the folder. 91 | # Not including the public_header_files will make all headers public. 92 | # 93 | 94 | #-------------------------------1.0.7版本去掉 2018-02-05----------------------- 95 | # s.source_files = "MOFSPickerManagerDemo/MOFSPickerManager/**/*.{h,m}", "MOFSPickerManagerDemo/GDataXMLNode/**/*.{h,m}" 96 | #----------------------------------------------------------------------------- 97 | s.source_files = "MOFSPickerManagerDemo/MOFSPickerManager/**/*.{h,m}" 98 | s.exclude_files = "Classes/Exclude" 99 | 100 | # s.public_header_files = "Classes/**/*.h" 101 | 102 | 103 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 104 | # 105 | # A list of resources included with the Pod. These are copied into the 106 | # target bundle with a build phase script. Anything else will be cleaned. 107 | # You can preserve files from being cleaned, please don't preserve 108 | # non-essential files like tests, examples and documentation. 109 | # 110 | 111 | # s.resource = "icon.png" 112 | # s.resources = "Resources/*.png" 113 | s.resources = "MOFSPickerManagerDemo/MOFSPickerManager/**/*.{xml}", "MOFSPickerManagerDemo/MOFSPickerManager/**/*.{json}" 114 | 115 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 116 | 117 | 118 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 119 | # 120 | # Link your library with frameworks, or libraries. Libraries do not include 121 | # the lib prefix of their name. 122 | # 123 | 124 | # s.framework = "SomeFramework" 125 | # s.frameworks = "SomeFramework", "AnotherFramework" 126 | 127 | #s.library = "xml2.2.tbd" 128 | 129 | #-------------------------------1.0.7版本去掉 2018-02-05----------------------- 130 | # s.libraries = "xml2" 131 | #----------------------------------------------------------------------------- 132 | 133 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 134 | # 135 | # If your library depends on compiler flags you can set them in the xcconfig hash 136 | # where they will only apply to your library. If you depend on other Podspecs 137 | # you can include multiple dependencies to ensure it works. 138 | 139 | #-------------------------------1.0.7版本去掉 2018-02-05----------------------- 140 | # s.requires_arc = false 141 | # s.requires_arc = ["MOFSPickerManagerDemo/MOFSPickerManager/**/*.{h,m}"] 142 | # s.module_name = "MOFSPickerManager" 143 | #----------------------------------------------------------------------------- 144 | 145 | # non_arc_files = 'MOFSPickerManagerDemo/GDataXMLNode/**/*.{h,m}' 146 | 147 | # s.exclude_files = non_arc_files 148 | 149 | # s.subspec 'no-arc' do |sp| 150 | 151 | # sp.source_files = non_arc_files 152 | 153 | # sp.requires_arc = false 154 | 155 | # end 156 | # s.requires_arc = ['MOFSPickerManagerDemo/MOFSPickerManager/**/*.{h,m}'] 157 | 158 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 159 | 160 | #-------------------------------1.0.7版本去掉 2018-02-05----------------------- 161 | #s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2", "OTHER_LINKER_FLAGS" => "-ObjC", "WEAK_REFERENCES_IN_MANUAL_RETAIN_RELEASE" => "Yes" } 162 | #----------------------------------------------------------------------------- 163 | 164 | # s.dependency "GDataXML" 165 | # "ALLOW_NON-MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES" 166 | 167 | end 168 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BF73464622FBD0CA0054281B /* province_data.json in Resources */ = {isa = PBXBuildFile; fileRef = BF73464522FBD0C90054281B /* province_data.json */; }; 11 | BF8ACDD61F557A54006C456A /* MOFSAddressModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8ACDC61F557A54006C456A /* MOFSAddressModel.m */; }; 12 | BF8ACDD81F557A54006C456A /* MOFSAddressPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8ACDCB1F557A54006C456A /* MOFSAddressPickerView.m */; }; 13 | BF8ACDD91F557A54006C456A /* MOFSDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8ACDCD1F557A54006C456A /* MOFSDatePicker.m */; }; 14 | BF8ACDDA1F557A54006C456A /* MOFSPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8ACDD01F557A54006C456A /* MOFSPickerManager.m */; }; 15 | BF8ACDDB1F557A54006C456A /* MOFSPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8ACDD21F557A54006C456A /* MOFSPickerView.m */; }; 16 | BF8ACDDD1F557A54006C456A /* province_data.xml in Resources */ = {isa = PBXBuildFile; fileRef = BF8ACDD51F557A54006C456A /* province_data.xml */; }; 17 | BFB368AC235EDB6600234759 /* LQYPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB368AB235EDB6600234759 /* LQYPickerView.m */; }; 18 | BFE28A971D7D9B7400C87B7D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE28A961D7D9B7400C87B7D /* main.m */; }; 19 | BFE28A9A1D7D9B7400C87B7D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE28A991D7D9B7400C87B7D /* AppDelegate.m */; }; 20 | BFE28A9D1D7D9B7400C87B7D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE28A9C1D7D9B7400C87B7D /* ViewController.m */; }; 21 | BFE28AA01D7D9B7400C87B7D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFE28A9E1D7D9B7400C87B7D /* Main.storyboard */; }; 22 | BFE28AA21D7D9B7400C87B7D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFE28AA11D7D9B7400C87B7D /* Assets.xcassets */; }; 23 | BFE28AA51D7D9B7400C87B7D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFE28AA31D7D9B7400C87B7D /* LaunchScreen.storyboard */; }; 24 | BFE28AB01D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE28AAF1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.m */; }; 25 | BFE28ABB1D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE28ABA1D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.m */; }; 26 | BFE93D09202859D800D4A531 /* MOFSToolView.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE93D08202859D800D4A531 /* MOFSToolView.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | BFE28AAC1D7D9B7400C87B7D /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = BFE28A8A1D7D9B7400C87B7D /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = BFE28A911D7D9B7400C87B7D; 35 | remoteInfo = MOFSPickerManagerDemo; 36 | }; 37 | BFE28AB71D7D9B7400C87B7D /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = BFE28A8A1D7D9B7400C87B7D /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = BFE28A911D7D9B7400C87B7D; 42 | remoteInfo = MOFSPickerManagerDemo; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | BF73464522FBD0C90054281B /* province_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = province_data.json; sourceTree = ""; }; 48 | BF8ACDC51F557A54006C456A /* MOFSAddressModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOFSAddressModel.h; sourceTree = ""; }; 49 | BF8ACDC61F557A54006C456A /* MOFSAddressModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOFSAddressModel.m; sourceTree = ""; }; 50 | BF8ACDCA1F557A54006C456A /* MOFSAddressPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOFSAddressPickerView.h; sourceTree = ""; }; 51 | BF8ACDCB1F557A54006C456A /* MOFSAddressPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOFSAddressPickerView.m; sourceTree = ""; }; 52 | BF8ACDCC1F557A54006C456A /* MOFSDatePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOFSDatePicker.h; sourceTree = ""; }; 53 | BF8ACDCD1F557A54006C456A /* MOFSDatePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOFSDatePicker.m; sourceTree = ""; }; 54 | BF8ACDCF1F557A54006C456A /* MOFSPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOFSPickerManager.h; sourceTree = ""; }; 55 | BF8ACDD01F557A54006C456A /* MOFSPickerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOFSPickerManager.m; sourceTree = ""; }; 56 | BF8ACDD11F557A54006C456A /* MOFSPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOFSPickerView.h; sourceTree = ""; }; 57 | BF8ACDD21F557A54006C456A /* MOFSPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOFSPickerView.m; sourceTree = ""; }; 58 | BF8ACDD51F557A54006C456A /* province_data.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = province_data.xml; sourceTree = ""; }; 59 | BFB368AA235EDB6600234759 /* LQYPickerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LQYPickerView.h; sourceTree = ""; }; 60 | BFB368AB235EDB6600234759 /* LQYPickerView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LQYPickerView.m; sourceTree = ""; }; 61 | BFE28A921D7D9B7400C87B7D /* MOFSPickerManagerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MOFSPickerManagerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | BFE28A961D7D9B7400C87B7D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 63 | BFE28A981D7D9B7400C87B7D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 64 | BFE28A991D7D9B7400C87B7D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 65 | BFE28A9B1D7D9B7400C87B7D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 66 | BFE28A9C1D7D9B7400C87B7D /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 67 | BFE28A9F1D7D9B7400C87B7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 68 | BFE28AA11D7D9B7400C87B7D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 69 | BFE28AA41D7D9B7400C87B7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 70 | BFE28AA61D7D9B7400C87B7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 71 | BFE28AAB1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MOFSPickerManagerDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 72 | BFE28AAF1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MOFSPickerManagerDemoTests.m; sourceTree = ""; }; 73 | BFE28AB11D7D9B7400C87B7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 74 | BFE28AB61D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MOFSPickerManagerDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 75 | BFE28ABA1D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MOFSPickerManagerDemoUITests.m; sourceTree = ""; }; 76 | BFE28ABC1D7D9B7400C87B7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 77 | BFE28AE11D7D9ED700C87B7D /* libxml2.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.2.tbd; path = usr/lib/libxml2.2.tbd; sourceTree = SDKROOT; }; 78 | BFE93D07202859D800D4A531 /* MOFSToolView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MOFSToolView.h; sourceTree = ""; }; 79 | BFE93D08202859D800D4A531 /* MOFSToolView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MOFSToolView.m; sourceTree = ""; }; 80 | /* End PBXFileReference section */ 81 | 82 | /* Begin PBXFrameworksBuildPhase section */ 83 | BFE28A8F1D7D9B7400C87B7D /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | BFE28AA81D7D9B7400C87B7D /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | BFE28AB31D7D9B7400C87B7D /* Frameworks */ = { 98 | isa = PBXFrameworksBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | ); 102 | runOnlyForDeploymentPostprocessing = 0; 103 | }; 104 | /* End PBXFrameworksBuildPhase section */ 105 | 106 | /* Begin PBXGroup section */ 107 | BF8ACDC41F557A54006C456A /* MOFSPickerManager */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | BF8ACDC51F557A54006C456A /* MOFSAddressModel.h */, 111 | BF8ACDC61F557A54006C456A /* MOFSAddressModel.m */, 112 | BF8ACDCA1F557A54006C456A /* MOFSAddressPickerView.h */, 113 | BF8ACDCB1F557A54006C456A /* MOFSAddressPickerView.m */, 114 | BF8ACDCC1F557A54006C456A /* MOFSDatePicker.h */, 115 | BF8ACDCD1F557A54006C456A /* MOFSDatePicker.m */, 116 | BF8ACDCF1F557A54006C456A /* MOFSPickerManager.h */, 117 | BF8ACDD01F557A54006C456A /* MOFSPickerManager.m */, 118 | BF8ACDD11F557A54006C456A /* MOFSPickerView.h */, 119 | BF8ACDD21F557A54006C456A /* MOFSPickerView.m */, 120 | BFE93D07202859D800D4A531 /* MOFSToolView.h */, 121 | BFE93D08202859D800D4A531 /* MOFSToolView.m */, 122 | BFB368AA235EDB6600234759 /* LQYPickerView.h */, 123 | BFB368AB235EDB6600234759 /* LQYPickerView.m */, 124 | BF8ACDD51F557A54006C456A /* province_data.xml */, 125 | BF73464522FBD0C90054281B /* province_data.json */, 126 | ); 127 | path = MOFSPickerManager; 128 | sourceTree = ""; 129 | }; 130 | BFE28A891D7D9B7400C87B7D = { 131 | isa = PBXGroup; 132 | children = ( 133 | BFE28A941D7D9B7400C87B7D /* MOFSPickerManagerDemo */, 134 | BFE28AAE1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests */, 135 | BFE28AB91D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests */, 136 | BFE28A931D7D9B7400C87B7D /* Products */, 137 | ); 138 | sourceTree = ""; 139 | }; 140 | BFE28A931D7D9B7400C87B7D /* Products */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | BFE28A921D7D9B7400C87B7D /* MOFSPickerManagerDemo.app */, 144 | BFE28AAB1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.xctest */, 145 | BFE28AB61D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.xctest */, 146 | ); 147 | name = Products; 148 | sourceTree = ""; 149 | }; 150 | BFE28A941D7D9B7400C87B7D /* MOFSPickerManagerDemo */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | BF8ACDC41F557A54006C456A /* MOFSPickerManager */, 154 | BFE28A981D7D9B7400C87B7D /* AppDelegate.h */, 155 | BFE28A991D7D9B7400C87B7D /* AppDelegate.m */, 156 | BFE28A9B1D7D9B7400C87B7D /* ViewController.h */, 157 | BFE28A9C1D7D9B7400C87B7D /* ViewController.m */, 158 | BFE28A9E1D7D9B7400C87B7D /* Main.storyboard */, 159 | BFE28AA11D7D9B7400C87B7D /* Assets.xcassets */, 160 | BFE28AA31D7D9B7400C87B7D /* LaunchScreen.storyboard */, 161 | BFE28AA61D7D9B7400C87B7D /* Info.plist */, 162 | BFE28A951D7D9B7400C87B7D /* Supporting Files */, 163 | ); 164 | path = MOFSPickerManagerDemo; 165 | sourceTree = ""; 166 | }; 167 | BFE28A951D7D9B7400C87B7D /* Supporting Files */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | BFE28AE11D7D9ED700C87B7D /* libxml2.2.tbd */, 171 | BFE28A961D7D9B7400C87B7D /* main.m */, 172 | ); 173 | name = "Supporting Files"; 174 | sourceTree = ""; 175 | }; 176 | BFE28AAE1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | BFE28AAF1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.m */, 180 | BFE28AB11D7D9B7400C87B7D /* Info.plist */, 181 | ); 182 | path = MOFSPickerManagerDemoTests; 183 | sourceTree = ""; 184 | }; 185 | BFE28AB91D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | BFE28ABA1D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.m */, 189 | BFE28ABC1D7D9B7400C87B7D /* Info.plist */, 190 | ); 191 | path = MOFSPickerManagerDemoUITests; 192 | sourceTree = ""; 193 | }; 194 | /* End PBXGroup section */ 195 | 196 | /* Begin PBXNativeTarget section */ 197 | BFE28A911D7D9B7400C87B7D /* MOFSPickerManagerDemo */ = { 198 | isa = PBXNativeTarget; 199 | buildConfigurationList = BFE28ABF1D7D9B7400C87B7D /* Build configuration list for PBXNativeTarget "MOFSPickerManagerDemo" */; 200 | buildPhases = ( 201 | BFE28A8E1D7D9B7400C87B7D /* Sources */, 202 | BFE28A8F1D7D9B7400C87B7D /* Frameworks */, 203 | BFE28A901D7D9B7400C87B7D /* Resources */, 204 | ); 205 | buildRules = ( 206 | ); 207 | dependencies = ( 208 | ); 209 | name = MOFSPickerManagerDemo; 210 | productName = MOFSPickerManagerDemo; 211 | productReference = BFE28A921D7D9B7400C87B7D /* MOFSPickerManagerDemo.app */; 212 | productType = "com.apple.product-type.application"; 213 | }; 214 | BFE28AAA1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests */ = { 215 | isa = PBXNativeTarget; 216 | buildConfigurationList = BFE28AC21D7D9B7400C87B7D /* Build configuration list for PBXNativeTarget "MOFSPickerManagerDemoTests" */; 217 | buildPhases = ( 218 | BFE28AA71D7D9B7400C87B7D /* Sources */, 219 | BFE28AA81D7D9B7400C87B7D /* Frameworks */, 220 | BFE28AA91D7D9B7400C87B7D /* Resources */, 221 | ); 222 | buildRules = ( 223 | ); 224 | dependencies = ( 225 | BFE28AAD1D7D9B7400C87B7D /* PBXTargetDependency */, 226 | ); 227 | name = MOFSPickerManagerDemoTests; 228 | productName = MOFSPickerManagerDemoTests; 229 | productReference = BFE28AAB1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.xctest */; 230 | productType = "com.apple.product-type.bundle.unit-test"; 231 | }; 232 | BFE28AB51D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests */ = { 233 | isa = PBXNativeTarget; 234 | buildConfigurationList = BFE28AC51D7D9B7400C87B7D /* Build configuration list for PBXNativeTarget "MOFSPickerManagerDemoUITests" */; 235 | buildPhases = ( 236 | BFE28AB21D7D9B7400C87B7D /* Sources */, 237 | BFE28AB31D7D9B7400C87B7D /* Frameworks */, 238 | BFE28AB41D7D9B7400C87B7D /* Resources */, 239 | ); 240 | buildRules = ( 241 | ); 242 | dependencies = ( 243 | BFE28AB81D7D9B7400C87B7D /* PBXTargetDependency */, 244 | ); 245 | name = MOFSPickerManagerDemoUITests; 246 | productName = MOFSPickerManagerDemoUITests; 247 | productReference = BFE28AB61D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.xctest */; 248 | productType = "com.apple.product-type.bundle.ui-testing"; 249 | }; 250 | /* End PBXNativeTarget section */ 251 | 252 | /* Begin PBXProject section */ 253 | BFE28A8A1D7D9B7400C87B7D /* Project object */ = { 254 | isa = PBXProject; 255 | attributes = { 256 | LastUpgradeCheck = 1030; 257 | ORGANIZATIONNAME = luoyuan; 258 | TargetAttributes = { 259 | BFE28A911D7D9B7400C87B7D = { 260 | CreatedOnToolsVersion = 7.3.1; 261 | DevelopmentTeam = 2K26LU5HS2; 262 | ProvisioningStyle = Automatic; 263 | }; 264 | BFE28AAA1D7D9B7400C87B7D = { 265 | CreatedOnToolsVersion = 7.3.1; 266 | TestTargetID = BFE28A911D7D9B7400C87B7D; 267 | }; 268 | BFE28AB51D7D9B7400C87B7D = { 269 | CreatedOnToolsVersion = 7.3.1; 270 | TestTargetID = BFE28A911D7D9B7400C87B7D; 271 | }; 272 | }; 273 | }; 274 | buildConfigurationList = BFE28A8D1D7D9B7400C87B7D /* Build configuration list for PBXProject "MOFSPickerManagerDemo" */; 275 | compatibilityVersion = "Xcode 3.2"; 276 | developmentRegion = en; 277 | hasScannedForEncodings = 0; 278 | knownRegions = ( 279 | en, 280 | Base, 281 | ); 282 | mainGroup = BFE28A891D7D9B7400C87B7D; 283 | productRefGroup = BFE28A931D7D9B7400C87B7D /* Products */; 284 | projectDirPath = ""; 285 | projectRoot = ""; 286 | targets = ( 287 | BFE28A911D7D9B7400C87B7D /* MOFSPickerManagerDemo */, 288 | BFE28AAA1D7D9B7400C87B7D /* MOFSPickerManagerDemoTests */, 289 | BFE28AB51D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests */, 290 | ); 291 | }; 292 | /* End PBXProject section */ 293 | 294 | /* Begin PBXResourcesBuildPhase section */ 295 | BFE28A901D7D9B7400C87B7D /* Resources */ = { 296 | isa = PBXResourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | BFE28AA51D7D9B7400C87B7D /* LaunchScreen.storyboard in Resources */, 300 | BF73464622FBD0CA0054281B /* province_data.json in Resources */, 301 | BFE28AA21D7D9B7400C87B7D /* Assets.xcassets in Resources */, 302 | BFE28AA01D7D9B7400C87B7D /* Main.storyboard in Resources */, 303 | BF8ACDDD1F557A54006C456A /* province_data.xml in Resources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | BFE28AA91D7D9B7400C87B7D /* Resources */ = { 308 | isa = PBXResourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | BFE28AB41D7D9B7400C87B7D /* Resources */ = { 315 | isa = PBXResourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | /* End PBXResourcesBuildPhase section */ 322 | 323 | /* Begin PBXSourcesBuildPhase section */ 324 | BFE28A8E1D7D9B7400C87B7D /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | BF8ACDD91F557A54006C456A /* MOFSDatePicker.m in Sources */, 329 | BF8ACDDB1F557A54006C456A /* MOFSPickerView.m in Sources */, 330 | BFE93D09202859D800D4A531 /* MOFSToolView.m in Sources */, 331 | BF8ACDD81F557A54006C456A /* MOFSAddressPickerView.m in Sources */, 332 | BF8ACDD61F557A54006C456A /* MOFSAddressModel.m in Sources */, 333 | BFE28A9D1D7D9B7400C87B7D /* ViewController.m in Sources */, 334 | BF8ACDDA1F557A54006C456A /* MOFSPickerManager.m in Sources */, 335 | BFE28A9A1D7D9B7400C87B7D /* AppDelegate.m in Sources */, 336 | BFE28A971D7D9B7400C87B7D /* main.m in Sources */, 337 | BFB368AC235EDB6600234759 /* LQYPickerView.m in Sources */, 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | }; 341 | BFE28AA71D7D9B7400C87B7D /* Sources */ = { 342 | isa = PBXSourcesBuildPhase; 343 | buildActionMask = 2147483647; 344 | files = ( 345 | BFE28AB01D7D9B7400C87B7D /* MOFSPickerManagerDemoTests.m in Sources */, 346 | ); 347 | runOnlyForDeploymentPostprocessing = 0; 348 | }; 349 | BFE28AB21D7D9B7400C87B7D /* Sources */ = { 350 | isa = PBXSourcesBuildPhase; 351 | buildActionMask = 2147483647; 352 | files = ( 353 | BFE28ABB1D7D9B7400C87B7D /* MOFSPickerManagerDemoUITests.m in Sources */, 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | /* End PBXSourcesBuildPhase section */ 358 | 359 | /* Begin PBXTargetDependency section */ 360 | BFE28AAD1D7D9B7400C87B7D /* PBXTargetDependency */ = { 361 | isa = PBXTargetDependency; 362 | target = BFE28A911D7D9B7400C87B7D /* MOFSPickerManagerDemo */; 363 | targetProxy = BFE28AAC1D7D9B7400C87B7D /* PBXContainerItemProxy */; 364 | }; 365 | BFE28AB81D7D9B7400C87B7D /* PBXTargetDependency */ = { 366 | isa = PBXTargetDependency; 367 | target = BFE28A911D7D9B7400C87B7D /* MOFSPickerManagerDemo */; 368 | targetProxy = BFE28AB71D7D9B7400C87B7D /* PBXContainerItemProxy */; 369 | }; 370 | /* End PBXTargetDependency section */ 371 | 372 | /* Begin PBXVariantGroup section */ 373 | BFE28A9E1D7D9B7400C87B7D /* Main.storyboard */ = { 374 | isa = PBXVariantGroup; 375 | children = ( 376 | BFE28A9F1D7D9B7400C87B7D /* Base */, 377 | ); 378 | name = Main.storyboard; 379 | sourceTree = ""; 380 | }; 381 | BFE28AA31D7D9B7400C87B7D /* LaunchScreen.storyboard */ = { 382 | isa = PBXVariantGroup; 383 | children = ( 384 | BFE28AA41D7D9B7400C87B7D /* Base */, 385 | ); 386 | name = LaunchScreen.storyboard; 387 | sourceTree = ""; 388 | }; 389 | /* End PBXVariantGroup section */ 390 | 391 | /* Begin XCBuildConfiguration section */ 392 | BFE28ABD1D7D9B7400C87B7D /* Debug */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | ALWAYS_SEARCH_USER_PATHS = NO; 396 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 397 | CLANG_ANALYZER_NONNULL = YES; 398 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 399 | CLANG_CXX_LIBRARY = "libc++"; 400 | CLANG_ENABLE_MODULES = YES; 401 | CLANG_ENABLE_OBJC_ARC = YES; 402 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 403 | CLANG_WARN_BOOL_CONVERSION = YES; 404 | CLANG_WARN_COMMA = YES; 405 | CLANG_WARN_CONSTANT_CONVERSION = YES; 406 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 408 | CLANG_WARN_EMPTY_BODY = YES; 409 | CLANG_WARN_ENUM_CONVERSION = YES; 410 | CLANG_WARN_INFINITE_RECURSION = YES; 411 | CLANG_WARN_INT_CONVERSION = YES; 412 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 413 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 414 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 415 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 416 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 417 | CLANG_WARN_STRICT_PROTOTYPES = YES; 418 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 419 | CLANG_WARN_UNREACHABLE_CODE = YES; 420 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 421 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 422 | COPY_PHASE_STRIP = NO; 423 | DEBUG_INFORMATION_FORMAT = dwarf; 424 | ENABLE_STRICT_OBJC_MSGSEND = YES; 425 | ENABLE_TESTABILITY = YES; 426 | GCC_C_LANGUAGE_STANDARD = gnu99; 427 | GCC_DYNAMIC_NO_PIC = NO; 428 | GCC_NO_COMMON_BLOCKS = YES; 429 | GCC_OPTIMIZATION_LEVEL = 0; 430 | GCC_PREPROCESSOR_DEFINITIONS = ( 431 | "DEBUG=1", 432 | "$(inherited)", 433 | ); 434 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 435 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 436 | GCC_WARN_UNDECLARED_SELECTOR = YES; 437 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 438 | GCC_WARN_UNUSED_FUNCTION = YES; 439 | GCC_WARN_UNUSED_VARIABLE = YES; 440 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 441 | MTL_ENABLE_DEBUG_INFO = YES; 442 | ONLY_ACTIVE_ARCH = YES; 443 | SDKROOT = iphoneos; 444 | TARGETED_DEVICE_FAMILY = "1,2"; 445 | }; 446 | name = Debug; 447 | }; 448 | BFE28ABE1D7D9B7400C87B7D /* Release */ = { 449 | isa = XCBuildConfiguration; 450 | buildSettings = { 451 | ALWAYS_SEARCH_USER_PATHS = NO; 452 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 453 | CLANG_ANALYZER_NONNULL = YES; 454 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 455 | CLANG_CXX_LIBRARY = "libc++"; 456 | CLANG_ENABLE_MODULES = YES; 457 | CLANG_ENABLE_OBJC_ARC = YES; 458 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 459 | CLANG_WARN_BOOL_CONVERSION = YES; 460 | CLANG_WARN_COMMA = YES; 461 | CLANG_WARN_CONSTANT_CONVERSION = YES; 462 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 463 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 464 | CLANG_WARN_EMPTY_BODY = YES; 465 | CLANG_WARN_ENUM_CONVERSION = YES; 466 | CLANG_WARN_INFINITE_RECURSION = YES; 467 | CLANG_WARN_INT_CONVERSION = YES; 468 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 469 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 470 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 471 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 472 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 473 | CLANG_WARN_STRICT_PROTOTYPES = YES; 474 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 475 | CLANG_WARN_UNREACHABLE_CODE = YES; 476 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 477 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 478 | COPY_PHASE_STRIP = NO; 479 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 480 | ENABLE_NS_ASSERTIONS = NO; 481 | ENABLE_STRICT_OBJC_MSGSEND = YES; 482 | GCC_C_LANGUAGE_STANDARD = gnu99; 483 | GCC_NO_COMMON_BLOCKS = YES; 484 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 485 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 486 | GCC_WARN_UNDECLARED_SELECTOR = YES; 487 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 488 | GCC_WARN_UNUSED_FUNCTION = YES; 489 | GCC_WARN_UNUSED_VARIABLE = YES; 490 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 491 | MTL_ENABLE_DEBUG_INFO = NO; 492 | SDKROOT = iphoneos; 493 | TARGETED_DEVICE_FAMILY = "1,2"; 494 | VALIDATE_PRODUCT = YES; 495 | }; 496 | name = Release; 497 | }; 498 | BFE28AC01D7D9B7400C87B7D /* Debug */ = { 499 | isa = XCBuildConfiguration; 500 | buildSettings = { 501 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 502 | CLANG_ENABLE_OBJC_WEAK = YES; 503 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 504 | DEVELOPMENT_TEAM = 2K26LU5HS2; 505 | HEADER_SEARCH_PATHS = ""; 506 | INFOPLIST_FILE = MOFSPickerManagerDemo/Info.plist; 507 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 508 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 509 | OTHER_LDFLAGS = ""; 510 | PRODUCT_BUNDLE_IDENTIFIER = com.memoriesofsnow.mofspickermanager; 511 | PRODUCT_NAME = "$(TARGET_NAME)"; 512 | PROVISIONING_PROFILE = ""; 513 | PROVISIONING_PROFILE_SPECIFIER = ""; 514 | TARGETED_DEVICE_FAMILY = 1; 515 | }; 516 | name = Debug; 517 | }; 518 | BFE28AC11D7D9B7400C87B7D /* Release */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 522 | CLANG_ENABLE_OBJC_WEAK = YES; 523 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 524 | DEVELOPMENT_TEAM = 2K26LU5HS2; 525 | HEADER_SEARCH_PATHS = ""; 526 | INFOPLIST_FILE = MOFSPickerManagerDemo/Info.plist; 527 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 528 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 529 | OTHER_LDFLAGS = ""; 530 | PRODUCT_BUNDLE_IDENTIFIER = com.memoriesofsnow.mofspickermanager; 531 | PRODUCT_NAME = "$(TARGET_NAME)"; 532 | PROVISIONING_PROFILE = ""; 533 | PROVISIONING_PROFILE_SPECIFIER = ""; 534 | TARGETED_DEVICE_FAMILY = 1; 535 | }; 536 | name = Release; 537 | }; 538 | BFE28AC31D7D9B7400C87B7D /* Debug */ = { 539 | isa = XCBuildConfiguration; 540 | buildSettings = { 541 | BUNDLE_LOADER = "$(TEST_HOST)"; 542 | INFOPLIST_FILE = MOFSPickerManagerDemoTests/Info.plist; 543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 544 | PRODUCT_BUNDLE_IDENTIFIER = memoriesofsnows.MOFSPickerManagerDemoTests; 545 | PRODUCT_NAME = "$(TARGET_NAME)"; 546 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MOFSPickerManagerDemo.app/MOFSPickerManagerDemo"; 547 | }; 548 | name = Debug; 549 | }; 550 | BFE28AC41D7D9B7400C87B7D /* Release */ = { 551 | isa = XCBuildConfiguration; 552 | buildSettings = { 553 | BUNDLE_LOADER = "$(TEST_HOST)"; 554 | INFOPLIST_FILE = MOFSPickerManagerDemoTests/Info.plist; 555 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 556 | PRODUCT_BUNDLE_IDENTIFIER = memoriesofsnows.MOFSPickerManagerDemoTests; 557 | PRODUCT_NAME = "$(TARGET_NAME)"; 558 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MOFSPickerManagerDemo.app/MOFSPickerManagerDemo"; 559 | }; 560 | name = Release; 561 | }; 562 | BFE28AC61D7D9B7400C87B7D /* Debug */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | ENABLE_BITCODE = YES; 566 | INFOPLIST_FILE = MOFSPickerManagerDemoUITests/Info.plist; 567 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 568 | OTHER_LDFLAGS = "-lxml2"; 569 | PRODUCT_BUNDLE_IDENTIFIER = memoriesofsnows.MOFSPickerManagerDemoUITests; 570 | PRODUCT_NAME = "$(TARGET_NAME)"; 571 | TEST_TARGET_NAME = MOFSPickerManagerDemo; 572 | }; 573 | name = Debug; 574 | }; 575 | BFE28AC71D7D9B7400C87B7D /* Release */ = { 576 | isa = XCBuildConfiguration; 577 | buildSettings = { 578 | ENABLE_BITCODE = YES; 579 | INFOPLIST_FILE = MOFSPickerManagerDemoUITests/Info.plist; 580 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 581 | OTHER_LDFLAGS = "-lxml2"; 582 | PRODUCT_BUNDLE_IDENTIFIER = memoriesofsnows.MOFSPickerManagerDemoUITests; 583 | PRODUCT_NAME = "$(TARGET_NAME)"; 584 | TEST_TARGET_NAME = MOFSPickerManagerDemo; 585 | }; 586 | name = Release; 587 | }; 588 | /* End XCBuildConfiguration section */ 589 | 590 | /* Begin XCConfigurationList section */ 591 | BFE28A8D1D7D9B7400C87B7D /* Build configuration list for PBXProject "MOFSPickerManagerDemo" */ = { 592 | isa = XCConfigurationList; 593 | buildConfigurations = ( 594 | BFE28ABD1D7D9B7400C87B7D /* Debug */, 595 | BFE28ABE1D7D9B7400C87B7D /* Release */, 596 | ); 597 | defaultConfigurationIsVisible = 0; 598 | defaultConfigurationName = Release; 599 | }; 600 | BFE28ABF1D7D9B7400C87B7D /* Build configuration list for PBXNativeTarget "MOFSPickerManagerDemo" */ = { 601 | isa = XCConfigurationList; 602 | buildConfigurations = ( 603 | BFE28AC01D7D9B7400C87B7D /* Debug */, 604 | BFE28AC11D7D9B7400C87B7D /* Release */, 605 | ); 606 | defaultConfigurationIsVisible = 0; 607 | defaultConfigurationName = Release; 608 | }; 609 | BFE28AC21D7D9B7400C87B7D /* Build configuration list for PBXNativeTarget "MOFSPickerManagerDemoTests" */ = { 610 | isa = XCConfigurationList; 611 | buildConfigurations = ( 612 | BFE28AC31D7D9B7400C87B7D /* Debug */, 613 | BFE28AC41D7D9B7400C87B7D /* Release */, 614 | ); 615 | defaultConfigurationIsVisible = 0; 616 | defaultConfigurationName = Release; 617 | }; 618 | BFE28AC51D7D9B7400C87B7D /* Build configuration list for PBXNativeTarget "MOFSPickerManagerDemoUITests" */ = { 619 | isa = XCConfigurationList; 620 | buildConfigurations = ( 621 | BFE28AC61D7D9B7400C87B7D /* Debug */, 622 | BFE28AC71D7D9B7400C87B7D /* Release */, 623 | ); 624 | defaultConfigurationIsVisible = 0; 625 | defaultConfigurationName = Release; 626 | }; 627 | /* End XCConfigurationList section */ 628 | }; 629 | rootObject = BFE28A8A1D7D9B7400C87B7D /* Project object */; 630 | } 631 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/project.xcworkspace/xcuserdata/luoyuan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/MOFSPickerManagerDemo.xcodeproj/project.xcworkspace/xcuserdata/luoyuan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/xcshareddata/xcschemes/MOFSPickerManagerDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/xcuserdata/luoyuan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo.xcodeproj/xcuserdata/luoyuan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MOFSPickerManagerDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | BFE28A911D7D9B7400C87B7D 16 | 17 | primary 18 | 19 | 20 | BFE28AAA1D7D9B7400C87B7D 21 | 22 | primary 23 | 24 | 25 | BFE28AB51D7D9B7400C87B7D 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/MOFSPickerManagerDemo/.DS_Store -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/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 | 56 | 74 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | MOFSPickerManager 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/LQYPickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LQYPickerView.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 2019/10/22. 6 | // Copyright © 2019 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MOFSToolView.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LQYPickerViewLayout : NSObject 15 | 16 | @property (nonatomic, assign) CGFloat marginLeft; 17 | @property (nonatomic, assign) CGFloat marginRight; 18 | @property (nonatomic, assign) CGFloat marginBottom; 19 | 20 | //高度,默认216 21 | @property (nonatomic, assign) CGFloat height; 22 | //默认 44 23 | @property (nonatomic, assign) CGFloat toolBarHeight; 24 | 25 | @end 26 | 27 | 28 | 29 | @interface LQYPickerView : UIPickerView 30 | 31 | @property (nonatomic, readonly) NSString *objectPointer; 32 | 33 | @property (nonatomic, strong) LQYPickerViewLayout *layout; 34 | //背景透明度, 默认0.4 35 | @property (nonatomic, assign) CGFloat maskAlpha; 36 | @property (nonatomic, strong) NSDictionary *textAttributes; 37 | 38 | @property (nonatomic, strong, readonly) MOFSToolView *toolBar; 39 | @property (nonatomic, strong, readonly) UIView *containerView; 40 | @property (nonatomic, strong, readonly) UIView *maskView; 41 | 42 | @property (nonatomic, weak) UIView *parentView; 43 | 44 | /** 45 | * 是否为动态,即联动 46 | */ 47 | @property (nonatomic, assign) BOOL isDynamic; 48 | 49 | /** 50 | * 级数 51 | * isDynamic = true有效 52 | * 默认值 1 53 | */ 54 | @property (nonatomic, assign) NSInteger numberOfSection; 55 | 56 | /** 57 | * 下一层数据源 key值 58 | * isDynamic = true有效 59 | * @{component : key} 60 | */ 61 | @property (nonatomic, strong) NSDictionary *dataKeys; 62 | 63 | /** 64 | * 数据内容key值 65 | * 格式 @{component : key} 66 | * 当数据源类型为NSDictionary或NSObject时调用 67 | * 例如 [@[@{@"name_0" : @"kamio"}, @{@"name_1" : @"nagisa"}]]时,其值应该为@{@0 : @"name_0", @1 : @"name_1"};如果key值都相同,可以只设置一个,例如@{@0 : @"name"} 68 | */ 69 | @property (nonatomic, strong) NSDictionary *dataTextKeys; 70 | 71 | 72 | /** 73 | * 数据 74 | * 内容可以是NSString、NSDictionary和NSObject;其中 NSDictionary和NSObject需要提供dataTextKeys来取出内容 75 | * 静态格式:1. @[@"kamio", @"nagisa", @"misuzu"] (一级) 76 | * 2. @[@{@"name" : @"kamio"}, @{@"name" : @"nagisa"}] (一级) 77 | * 3. @[@[@"a", @"b", @"c"], @[@"1", @"2", @"3"]] (多级,取决于最外层数组长度) 78 | * 动态格式:@[@{@"name" : @"广东", @"list" : @[@"深圳", @"广州"]}, @{@"name" : @"广西", @"list" : @[@"南宁", @"桂林"]}]; 79 | */ 80 | @property (nonatomic, strong) NSArray *dataArray; 81 | 82 | 83 | /** 84 | * 确认block 85 | * json格式为 component : component所选中的数据 86 | */ 87 | @property (nonatomic, copy) void (^commitBlock)(NSDictionary * _Nullable json); 88 | 89 | /** 90 | * 获取某个component下的 数组 91 | */ 92 | - (nullable NSArray *)getDataArrayForComponent:(NSInteger)component; 93 | 94 | - (void)show; 95 | 96 | 97 | - (void)dismiss; 98 | 99 | @end 100 | 101 | typedef NS_ENUM(NSUInteger, LQYDateComponent) { 102 | LQYDateComponentYear = 0, 103 | LQYDateComponentMonth = 1, 104 | LQYDateComponentDay = 2, 105 | LQYDateComponentHour = 3, 106 | LQYDateComponentMinute = 4, 107 | LQYDateComponentSecond = 5 108 | }; 109 | 110 | typedef NS_ENUM(NSInteger, LQYFormatType) { 111 | LQYFormatTypeBefore = 1, //加在相应字符串前边 112 | LQYFormatTypeAfter = 2, //加在相应字符串后边 113 | }; 114 | 115 | @interface LQYDatePickerView : LQYPickerView 116 | 117 | /**注意:minimumComponent不是LQYDateComponentYear时,请保持minimumDate、maximumDate前面略去的值一致 118 | * 例如 minimumComponent是LQYDateComponentDay,那么请保持最小minimumDate、最大日期maximumDate 119 | * 的年份、月份一致 120 | * 如果不一致,则以小的minimumDate为准 121 | */ 122 | 123 | /** 124 | * 最小日期 125 | * 默认:2000-01-01 126 | */ 127 | @property (nullable, nonatomic, strong) NSDate *minimumDate; 128 | 129 | /** 130 | * 最大日期 131 | * 默认:当前时间 132 | */ 133 | @property (nullable, nonatomic, strong) NSDate *maximumDate; 134 | 135 | /** 136 | * 显示的最小component 137 | * 默认LQYDateComponentYear,从年份开始显示 138 | */ 139 | @property (nonatomic, assign) LQYDateComponent minimumComponent; 140 | 141 | /** 142 | * 显示的最大component 143 | * 默认为LQYDateComponentDay,显示到 天 为止 144 | */ 145 | @property (nonatomic, assign) LQYDateComponent maximumComponent; 146 | 147 | @property (nonatomic, copy) void (^cancelBlock)(void); 148 | @property (nonatomic, copy) void (^dateCommitBlock)(NSDateComponents *components); 149 | 150 | /** 151 | * 设置显示时间格式 152 | */ 153 | - (void)setDateFormat:(NSString *)dateFormat formatType:(LQYFormatType)formatType component:(LQYDateComponent)component; 154 | 155 | - (void)showWithCommitBlock:(void(^)(NSDateComponents *components))commitBlock cancelBlock:(void(^)(void))cancelBlock; 156 | 157 | @end 158 | 159 | 160 | 161 | NS_ASSUME_NONNULL_END 162 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/LQYPickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LQYPickerView.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 2019/10/22. 6 | // Copyright © 2019 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "LQYPickerView.h" 10 | 11 | @implementation LQYPickerViewLayout 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | _height = 216; 17 | _toolBarHeight = 44; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | 24 | 25 | @interface LQYPickerView () 26 | 27 | @end 28 | 29 | @implementation LQYPickerView 30 | 31 | #pragma mark - setter 32 | 33 | - (void)setParentView:(UIView *)parentView { 34 | _parentView = parentView; 35 | if (_parentView) { 36 | [self updateFrame]; 37 | } 38 | } 39 | 40 | - (void)setDataArray:(NSArray *)dataArray { 41 | _dataArray = dataArray; 42 | dispatch_async(dispatch_get_main_queue(), ^{ 43 | [self reloadAllComponents]; 44 | }); 45 | } 46 | 47 | #pragma mark - getter 48 | 49 | - (LQYPickerViewLayout *)layout { 50 | if (!_layout) { 51 | _layout = [LQYPickerViewLayout new]; 52 | } 53 | return _layout; 54 | } 55 | 56 | - (NSString *)objectPointer { 57 | return [NSString stringWithFormat:@"%p", self]; 58 | } 59 | 60 | #pragma mark - init 61 | 62 | - (instancetype)init { 63 | self = [super init]; 64 | if (self) { 65 | 66 | _numberOfSection = 1; 67 | 68 | _maskAlpha = 0.4; 69 | 70 | _maskView = [UIView new]; 71 | _maskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:_maskAlpha]; 72 | _maskView.userInteractionEnabled = true; 73 | [_maskView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]]; 74 | 75 | _containerView = [UIView new]; 76 | _containerView.backgroundColor = [UIColor whiteColor]; 77 | 78 | _toolBar = [MOFSToolView new]; 79 | _toolBar.backgroundColor = [UIColor whiteColor]; 80 | [_containerView addSubview:_toolBar]; 81 | 82 | [_toolBar.cancelBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelAction)]]; 83 | [_toolBar.commitBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(commitAction)]]; 84 | 85 | self.delegate = self; 86 | self.dataSource = self; 87 | 88 | //iOS 10及以上需要添加 这一行代码,否则第一次不显示中间两条分割线 89 | if ([self numberOfRowsInComponent:0] > 0) {} 90 | 91 | } 92 | return self; 93 | } 94 | 95 | #pragma mark - update frame 96 | 97 | - (void)updateFrame { 98 | CGRect frame = _parentView.bounds; 99 | _maskView.frame = frame; 100 | 101 | CGRect rect = _containerView.frame; 102 | rect.origin.x = self.layout.marginLeft; 103 | rect.size.width = frame.size.width - self.layout.marginLeft - self.layout.marginRight; 104 | rect.size.height = self.layout.height; 105 | _containerView.frame = rect; 106 | 107 | _toolBar.frame = CGRectMake(0, 0, rect.size.width, self.layout.toolBarHeight); 108 | 109 | self.frame = CGRectMake(0, self.layout.toolBarHeight, rect.size.width, rect.size.height - self.layout.toolBarHeight); 110 | 111 | } 112 | 113 | #pragma mark - ToolBar Action 114 | 115 | - (void)cancelAction { 116 | [self dismiss]; 117 | } 118 | 119 | - (void)commitAction { 120 | [self dismiss]; 121 | 122 | if (self.commitBlock) { 123 | 124 | NSMutableDictionary *json = [NSMutableDictionary dictionary]; 125 | 126 | NSInteger numberPfComponent = self.numberOfComponents;; 127 | 128 | for (NSInteger component = 0; component < numberPfComponent; component++) { 129 | NSInteger row = [self selectedRowInComponent:component]; 130 | 131 | if (self.isDynamic) { 132 | id arr = [self getDataArrayForComponent:component]; 133 | id obj = arr[row]; 134 | json[@(component)] = @{@"row" : @(row), @"data" : obj}; 135 | } else { 136 | if ([self.dataArray.firstObject isKindOfClass:[NSArray class]]) { 137 | NSArray *arr = self.dataArray[component]; 138 | id obj = arr[row]; 139 | json[@(component)] = @{@"row" : @(row), @"data" : obj}; 140 | } else { 141 | id obj = self.dataArray[row]; 142 | json[@(component)] = @{@"row" : @(row), @"data" : obj}; 143 | } 144 | } 145 | } 146 | 147 | self.commitBlock(json); 148 | } 149 | } 150 | 151 | #pragma mark - search data 152 | 153 | /** 154 | * 获取某个component下的 数组 155 | */ 156 | - (nullable NSArray *)getDataArrayForComponent:(NSInteger)component { 157 | if (_isDynamic) { 158 | if (component == 0) { 159 | return self.dataArray; 160 | } 161 | NSInteger index = 1; 162 | NSInteger row = [self selectedRowInComponent:0]; 163 | id obj = nil; 164 | if (row < self.dataArray.count) { 165 | obj = self.dataArray[row]; 166 | while (index <= component) { 167 | if (!obj) { 168 | break; 169 | } 170 | row = [self selectedRowInComponent:index - 1]; 171 | if ([obj isKindOfClass:[NSArray class]]) { 172 | if (row < [obj count]) { 173 | obj = obj[row]; 174 | } else { 175 | obj = [obj firstObject]; 176 | break; 177 | } 178 | } else if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSObject class]]) { 179 | obj = [self getArrayForObject:obj inComponent:index - 1]; 180 | if (!obj) { 181 | break; 182 | } 183 | } else { 184 | obj = nil; 185 | break; 186 | } 187 | if (![obj isKindOfClass:[NSArray class]]) { 188 | obj = [self getArrayForObject:obj inComponent:index]; 189 | } 190 | index++; 191 | } 192 | } 193 | 194 | if (![obj isKindOfClass:[NSArray class]]) { 195 | obj = [self getArrayForObject:obj inComponent:component]; 196 | } 197 | 198 | return obj; 199 | } else { 200 | if ([self.dataArray.firstObject isKindOfClass:[NSArray class]]) { 201 | if (component < self.dataArray.count) { 202 | NSArray *arr = self.dataArray[component]; 203 | return arr; 204 | } 205 | return nil; 206 | } else { 207 | return self.dataArray; 208 | } 209 | } 210 | 211 | } 212 | 213 | - (nullable NSArray *)getArrayForObject:(id)obj inComponent:(NSInteger)component { 214 | if (!obj) { 215 | return nil; 216 | } 217 | if ([obj isKindOfClass:[NSArray class]]) { 218 | return obj; 219 | } 220 | id result; 221 | NSString *key = self.dataKeys ? self.dataKeys[@(component)] : nil; 222 | if (!key) { 223 | key = self.dataKeys[@(0)]; 224 | } 225 | if (key) { 226 | if ([obj isKindOfClass:[NSDictionary class]]) { 227 | result = obj[key]; 228 | } else if ([obj isKindOfClass:[NSObject class]]) { 229 | result = [obj valueForKey:key]; 230 | } 231 | } else { 232 | result = nil; 233 | } 234 | return result; 235 | } 236 | 237 | /** 238 | * 获取某个 component 下的 obj的 文字内容 239 | */ 240 | - (nullable NSString *)textForComponent:(NSInteger)component object:(id)object { 241 | NSString *text; 242 | 243 | if ([object isKindOfClass:[NSString class]]) { 244 | text = object; 245 | } else if ([object isKindOfClass:[NSDictionary class]] || [object isKindOfClass:[NSObject class]]) { 246 | NSString *key = self.dataTextKeys ? self.dataTextKeys[@(component)] : nil; 247 | if (!key) { 248 | key = self.dataTextKeys[@0]; 249 | } 250 | if (key) { 251 | if ([object isKindOfClass:[NSDictionary class]]) { 252 | text = object[key]; 253 | } else { 254 | text = [object valueForKey:key]; 255 | } 256 | } else { 257 | text = @"undefined"; 258 | } 259 | } else { 260 | text = @"undefined"; 261 | } 262 | 263 | return [text isKindOfClass:[NSString class]] ? text : @"undefined"; 264 | } 265 | 266 | #pragma mark - UIPickerViewDelegate, UIPickerViewDataSource 267 | 268 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 269 | return _isDynamic ? _numberOfSection : ([self.dataArray.firstObject isKindOfClass:[NSArray class]] ? self.dataArray.count : 1); 270 | } 271 | 272 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 273 | 274 | if (_isDynamic) { 275 | id obj = [self getDataArrayForComponent:component]; 276 | return [obj isKindOfClass:[NSArray class]] ? [obj count] : 0; 277 | } else { 278 | id obj = self.dataArray[component]; 279 | if ([obj isKindOfClass:[NSArray class]]) { 280 | return [obj count]; 281 | } else if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSObject class]]) { 282 | return self.dataArray.count; 283 | } else { 284 | return 0; 285 | } 286 | } 287 | 288 | } 289 | 290 | - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { 291 | return 44; 292 | } 293 | 294 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 295 | 296 | if (_isDynamic) { 297 | id arr = [self getDataArrayForComponent:component]; 298 | id obj = arr[row]; 299 | return [self textForComponent:component object:obj]; 300 | } else { 301 | NSArray *arr = [self getDataArrayForComponent:component]; 302 | if (row < arr.count) { 303 | id obj = arr[row]; 304 | return [self textForComponent:component object:obj]; 305 | } else { 306 | return @"undefined"; 307 | } 308 | } 309 | } 310 | 311 | - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 312 | UILabel* pickerLabel = (UILabel*)view; 313 | if (!pickerLabel){ 314 | pickerLabel = [[UILabel alloc] init];; 315 | pickerLabel.textAlignment = NSTextAlignmentCenter; 316 | pickerLabel.font = [UIFont systemFontOfSize:16]; 317 | pickerLabel.textColor = [UIColor blackColor]; 318 | } 319 | 320 | NSString *text = [self pickerView:pickerView titleForRow:row forComponent:component]; 321 | 322 | pickerLabel.attributedText = [[NSAttributedString alloc] initWithString:text attributes:_textAttributes]; 323 | 324 | return pickerLabel; 325 | } 326 | 327 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 328 | if (_isDynamic) { 329 | if (component < _numberOfSection - 1) { 330 | for (NSInteger i = component + 1; i < _numberOfSection; i++) { 331 | [pickerView reloadComponent:i]; 332 | [pickerView selectRow:0 inComponent:i animated:false]; 333 | } 334 | } 335 | } 336 | } 337 | 338 | - (void)show { 339 | 340 | if (!_parentView) { 341 | self.parentView = [UIApplication sharedApplication].keyWindow; 342 | } 343 | 344 | [self updateFrame]; 345 | 346 | [_containerView addSubview:self]; 347 | [self.parentView addSubview:_maskView]; 348 | [self.parentView addSubview:_containerView]; 349 | 350 | CGFloat height = self.parentView.frame.size.height; 351 | 352 | __block CGRect frame = _containerView.frame; 353 | frame.origin.y = height; 354 | _containerView.frame = frame; 355 | _maskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0]; 356 | 357 | [UIView animateWithDuration:0.3 animations:^{ 358 | frame.origin.y = height - self.containerView.frame.size.height - self.layout.marginBottom; 359 | self.containerView.frame = frame; 360 | self.maskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:self.maskAlpha]; 361 | } completion:^(BOOL finished) { 362 | 363 | }]; 364 | 365 | } 366 | 367 | - (void)dismiss { 368 | CGFloat height = self.parentView.frame.size.height; 369 | __block CGRect frame = _containerView.frame; 370 | frame.origin.y = height; 371 | [UIView animateWithDuration:0.3 animations:^{ 372 | self.containerView.frame = frame; 373 | self.maskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0]; 374 | } completion:^(BOOL finished) { 375 | [self removeFromSuperview]; 376 | [self.maskView removeFromSuperview]; 377 | [self.containerView removeFromSuperview]; 378 | }]; 379 | } 380 | 381 | #pragma mark - Dealloc 382 | 383 | - (void)dealloc { 384 | 385 | } 386 | 387 | @end 388 | 389 | @interface LQYDatePickerView () 390 | 391 | @property (nonatomic, strong) NSMutableDictionary *> *dataJson; 392 | @property (nonatomic, strong) NSMutableArray *months; 393 | @property (nonatomic, strong) NSMutableArray *days_28; 394 | @property (nonatomic, strong) NSMutableArray *days_29; 395 | @property (nonatomic, strong) NSMutableArray *days_30; 396 | @property (nonatomic, strong) NSMutableArray *days_31; 397 | @property (nonatomic, strong) NSMutableArray *hours; 398 | @property (nonatomic, strong) NSMutableArray *minutes; 399 | @property (nonatomic, strong) NSMutableArray *seconds; 400 | @property (nonatomic, strong) NSDictionary *> *filterJson; 401 | @property (nonatomic, strong) NSMutableDictionary *> *dateFormatJson; 402 | 403 | @property (nonatomic, strong) NSCalendar *calendar; 404 | //@property (nonatomic, strong) NSDateComponents *dateComponents; 405 | @property (nonatomic, strong) NSDateComponents *minComponents; 406 | @property (nonatomic, strong) NSDateComponents *maxComponents; 407 | @property (nonatomic, strong) NSArray *unitFlags; 408 | @property (nonatomic, strong) NSArray *dateComponentKeys; 409 | 410 | @property (nonatomic, strong) NSMutableDictionary *delegatesDict; 411 | @property (readwrite, nonatomic, strong) NSLock *lock; 412 | 413 | @end 414 | 415 | const NSString *LQYFormatTypeBeforeKey = @"LQYFormatTypeBeforeKey"; 416 | const NSString *LQYFormatTypeAfterKey = @"LQYFormatTypeAfterKey"; 417 | 418 | @implementation LQYDatePickerView 419 | 420 | #pragma mark - setter 421 | 422 | - (void)setMinimumDate:(NSDate *)minimumDate { 423 | _minimumDate = minimumDate; 424 | [self getDataArray]; 425 | } 426 | 427 | - (void)setMaximumDate:(NSDate *)maximumDate { 428 | _maximumDate = maximumDate; 429 | [self getDataArray]; 430 | } 431 | 432 | #pragma mark - getter 433 | 434 | - (NSLock *)lock { 435 | if (!_lock) { 436 | _lock = [[NSLock alloc] init]; 437 | _lock.name = @"com.ly.datePicker.lock"; 438 | } 439 | return _lock; 440 | } 441 | 442 | - (NSMutableDictionary *)delegatesDict { 443 | if (!_delegatesDict) { 444 | _delegatesDict = [NSMutableDictionary dictionary]; 445 | } 446 | return _delegatesDict; 447 | } 448 | 449 | - (NSMutableDictionary *> *)dataJson { 450 | if (!_dataJson) { 451 | _dataJson = [NSMutableDictionary dictionary]; 452 | } 453 | return _dataJson; 454 | } 455 | 456 | - (NSMutableArray *)months { 457 | if (!_months) { 458 | _months = [NSMutableArray array]; 459 | for (NSInteger month = 1; month <= 12; month++) { 460 | [_months addObject:@(month)]; 461 | } 462 | } 463 | return _months; 464 | } 465 | 466 | - (NSMutableArray *)days_28 { 467 | if (!_days_28) { 468 | _days_28 = [NSMutableArray array]; 469 | for (NSInteger day = 1; day <= 28; day++) { 470 | [_days_28 addObject:@(day)]; 471 | } 472 | } 473 | return _days_28; 474 | } 475 | 476 | - (NSMutableArray *)days_29 { 477 | if (!_days_29) { 478 | _days_29 = [NSMutableArray array]; 479 | for (NSInteger day = 1; day <= 29; day++) { 480 | [_days_29 addObject:@(day)]; 481 | } 482 | } 483 | return _days_29; 484 | } 485 | 486 | - (NSMutableArray *)days_30 { 487 | if (!_days_30) { 488 | _days_30 = [NSMutableArray array]; 489 | for (NSInteger day = 1; day <= 30; day++) { 490 | [_days_30 addObject:@(day)]; 491 | } 492 | } 493 | return _days_30; 494 | } 495 | 496 | - (NSMutableArray *)days_31 { 497 | if (!_days_31) { 498 | _days_31 = [NSMutableArray array]; 499 | for (NSInteger day = 1; day <= 31; day++) { 500 | [_days_31 addObject:@(day)]; 501 | } 502 | } 503 | return _days_31; 504 | } 505 | 506 | - (NSMutableArray *)hours { 507 | if (!_hours) { 508 | _hours = [NSMutableArray array]; 509 | for (NSInteger hour = 0; hour < 24; hour++) { 510 | [_hours addObject:@(hour)]; 511 | } 512 | } 513 | return _hours; 514 | } 515 | 516 | - (NSMutableArray *)minutes { 517 | if (!_minutes) { 518 | _minutes = [NSMutableArray array]; 519 | for (NSInteger minute = 0; minute < 60; minute++) { 520 | [_minutes addObject:@(minute)]; 521 | } 522 | } 523 | return _minutes; 524 | } 525 | 526 | - (NSMutableArray *)seconds { 527 | if (!_seconds) { 528 | _seconds = [NSMutableArray array]; 529 | for (NSInteger second = 0; second < 60; second++) { 530 | [_seconds addObject:@(second)]; 531 | } 532 | } 533 | return _seconds; 534 | } 535 | 536 | - (NSDictionary *> *)filterJson { 537 | if (!_filterJson) { 538 | _filterJson = @{@(LQYDateComponentMonth) : @{@"min" : @"minMonths", @"max" : @"maxMonths"}, 539 | @(LQYDateComponentDay) : @{@"min" : @"minDays", @"max" : @"maxDays"}, 540 | @(LQYDateComponentHour) : @{@"min" : @"minHours", @"max" : @"maxHours"}, 541 | @(LQYDateComponentMinute) : @{@"min" : @"minMinutes", @"max" : @"maxMinutes"}, 542 | @(LQYDateComponentSecond) : @{@"min" : @"minSeconds", @"max" : @"maxSeconds"} 543 | }; 544 | } 545 | return _filterJson; 546 | } 547 | 548 | - (NSMutableDictionary *> *)dateFormatJson { 549 | if (!_dateFormatJson) { 550 | NSMutableDictionary *yearDict = [NSMutableDictionary dictionaryWithObject:@"年" forKey:LQYFormatTypeAfterKey]; 551 | NSMutableDictionary *monthDict = [NSMutableDictionary dictionaryWithObject:@"月" forKey:LQYFormatTypeAfterKey]; 552 | NSMutableDictionary *dayDict = [NSMutableDictionary dictionaryWithObject:@"日" forKey:LQYFormatTypeAfterKey]; 553 | NSMutableDictionary *hourDict = [NSMutableDictionary dictionaryWithObject:@"点" forKey:LQYFormatTypeAfterKey]; 554 | NSMutableDictionary *minuteyDict = [NSMutableDictionary dictionaryWithObject:@"分" forKey:LQYFormatTypeAfterKey]; 555 | NSMutableDictionary *secondDict = [NSMutableDictionary dictionaryWithObject:@"秒" forKey:LQYFormatTypeAfterKey]; 556 | 557 | _dateFormatJson = [[NSMutableDictionary alloc] initWithDictionary:@{@(LQYDateComponentYear) : yearDict, 558 | @(LQYDateComponentMonth) : monthDict, 559 | @(LQYDateComponentDay) : dayDict, 560 | @(LQYDateComponentHour) : hourDict, 561 | @(LQYDateComponentMinute) : minuteyDict, 562 | @(LQYDateComponentSecond) : secondDict 563 | }]; 564 | } 565 | return _dateFormatJson; 566 | } 567 | 568 | - (NSCalendar *)calendar { 569 | if (!_calendar) { 570 | _calendar = [NSCalendar currentCalendar]; 571 | } 572 | return _calendar; 573 | } 574 | 575 | - (NSArray *)unitFlags { 576 | if (!_unitFlags) { 577 | _unitFlags = @[@(NSCalendarUnitYear), 578 | @(NSCalendarUnitMonth), 579 | @(NSCalendarUnitDay), 580 | @(NSCalendarUnitHour), 581 | @(NSCalendarUnitMinute), 582 | @(NSCalendarUnitSecond)]; 583 | } 584 | return _unitFlags; 585 | } 586 | 587 | - (NSArray *)dateComponentKeys { 588 | if (!_dateComponentKeys) { 589 | _dateComponentKeys = @[@"year", @"month", @"day", @"hour", @"minute", @"second"]; 590 | } 591 | return _dateComponentKeys; 592 | } 593 | 594 | 595 | #pragma mark - init 596 | 597 | - (instancetype)init { 598 | self = [super init]; 599 | if (self) { 600 | NSDateFormatter *df = [NSDateFormatter new]; 601 | df.dateFormat = @"yyyy-MM-dd"; 602 | _minimumDate = [df dateFromString:@"2000-01-01"]; 603 | _maximumDate = [NSDate date]; 604 | _minimumComponent = LQYDateComponentYear; 605 | _maximumComponent = LQYDateComponentDay; 606 | 607 | [self.toolBar.cancelBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelAction)]]; 608 | [self.toolBar.commitBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(commitAction)]]; 609 | 610 | [self getDataArray]; 611 | } 612 | return self; 613 | } 614 | 615 | #pragma mark - ToolBar Action 616 | 617 | - (void)cancelAction { 618 | [self dismiss]; 619 | if (self.cancelBlock) { 620 | self.cancelBlock(); 621 | } 622 | 623 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 624 | if (delegate) { 625 | if (delegate.cancelBlock) { 626 | delegate.cancelBlock(); 627 | } 628 | [self removeDelegate:delegate]; 629 | } 630 | 631 | } 632 | 633 | - (void)commitAction { 634 | [self dismiss]; 635 | if (self.dateCommitBlock) { 636 | self.dateCommitBlock([self dateComponentsInComponent:self.numberOfSection - 1]); 637 | } 638 | 639 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 640 | if (delegate) { 641 | if (delegate.commitLYQDateBlock) { 642 | delegate.commitLYQDateBlock([self dateComponentsInComponent:self.numberOfSection - 1]); 643 | } 644 | [self removeDelegate:delegate]; 645 | } 646 | } 647 | 648 | #pragma mark - get data 649 | 650 | - (void)getDataArray { 651 | if (_minimumDate && _maximumDate) { 652 | NSComparisonResult result = [_minimumDate compare:_maximumDate]; 653 | if (result != NSOrderedAscending) { 654 | return; 655 | } 656 | 657 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 658 | 659 | if (self.minimumComponent > self.maximumComponent) { 660 | self.minimumComponent = LQYDateComponentYear; 661 | self.maximumComponent = LQYDateComponentSecond; 662 | } 663 | 664 | self.numberOfSection = self.maximumComponent - self.minimumComponent + 1; 665 | 666 | // 废弃(耗性能) 667 | // NSMutableArray *arr = [NSMutableArray array]; 668 | // NSCalendarUnit unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 669 | // NSDateComponents *minComponents = [self.calendar components:unitFlags fromDate:self.minimumDate]; 670 | // NSDateComponents *maxComponents = [self.calendar components:unitFlags fromDate:self.maximumDate]; 671 | // switch (self.minimumComponent) { 672 | // case LQYDateComponentMonth: 673 | // maxComponents.year = minComponents.year; 674 | // break; 675 | // case LQYDateComponentDay: 676 | // maxComponents.year = minComponents.year; 677 | // maxComponents.month = minComponents.month; 678 | // break; 679 | // case LQYDateComponentHour: 680 | // maxComponents.year = minComponents.year; 681 | // maxComponents.month = minComponents.month; 682 | // maxComponents.day = minComponents.day; 683 | // break; 684 | // case LQYDateComponentMinute: 685 | // maxComponents.year = minComponents.year; 686 | // maxComponents.month = minComponents.month; 687 | // maxComponents.day = minComponents.day; 688 | // maxComponents.hour = minComponents.hour; 689 | // break; 690 | // case LQYDateComponentSecond: 691 | // maxComponents.year = minComponents.year; 692 | // maxComponents.month = minComponents.month; 693 | // maxComponents.day = minComponents.day; 694 | // maxComponents.hour = minComponents.hour; 695 | // maxComponents.minute = minComponents.minute; 696 | // break; 697 | // default: 698 | // break; 699 | // } 700 | // /** 701 | // * 数据格式: @[{@"name" : "2019" : list: @[@{@"name" : @"1"}]}] 702 | // */ 703 | // [self handleData:arr minComponents:minComponents maxComponents:maxComponents components:[NSDateComponents new] currentComponent:self.minimumComponent dataDict:nil]; 704 | // self.dataArray = arr; 705 | 706 | NSCalendarUnit unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 707 | 708 | self.minComponents = [self.calendar components:unitFlags fromDate:self.minimumDate]; 709 | self.maxComponents = [self.calendar components:unitFlags fromDate:self.maximumDate]; 710 | 711 | NSDateComponents *minComponents = [self.calendar components:unitFlags fromDate:self.minimumDate]; 712 | NSDateComponents *maxComponents = [self.calendar components:unitFlags fromDate:self.maximumDate]; 713 | 714 | switch (self.minimumComponent) { 715 | case LQYDateComponentMonth: 716 | maxComponents.year = minComponents.year; 717 | break; 718 | case LQYDateComponentDay: 719 | maxComponents.year = minComponents.year; 720 | maxComponents.month = minComponents.month; 721 | break; 722 | case LQYDateComponentHour: 723 | maxComponents.year = minComponents.year; 724 | maxComponents.month = minComponents.month; 725 | maxComponents.day = minComponents.day; 726 | break; 727 | case LQYDateComponentMinute: 728 | maxComponents.year = minComponents.year; 729 | maxComponents.month = minComponents.month; 730 | maxComponents.day = minComponents.day; 731 | maxComponents.hour = minComponents.hour; 732 | break; 733 | case LQYDateComponentSecond: 734 | maxComponents.year = minComponents.year; 735 | maxComponents.month = minComponents.month; 736 | maxComponents.day = minComponents.day; 737 | maxComponents.hour = minComponents.hour; 738 | maxComponents.minute = minComponents.minute; 739 | break; 740 | default: 741 | break; 742 | } 743 | 744 | [self.dataJson removeAllObjects]; 745 | 746 | //年份 747 | NSMutableArray *years = [NSMutableArray array]; 748 | for (NSInteger year = minComponents.year; year <= maxComponents.year; year++) { 749 | [years addObject:@(year)]; 750 | } 751 | [self.dataJson setValue:years forKey:@"years"]; 752 | 753 | for (NSNumber *component in self.filterJson) { 754 | LQYDateComponent currentComponent = component.unsignedIntegerValue; 755 | NSString *minKey = self.filterJson[component][@"min"]; 756 | NSString *maxKey = self.filterJson[component][@"max"]; 757 | NSMutableArray *minArr = [self getLimitDataForCurrentComponent:currentComponent components:minComponents isMinimum:true]; 758 | NSMutableArray *maxArr = [self getLimitDataForCurrentComponent:currentComponent components:maxComponents isMinimum:false]; 759 | [self.dataJson setValue:minArr forKey:minKey]; 760 | [self.dataJson setValue:maxArr forKey:maxKey]; 761 | } 762 | 763 | dispatch_async(dispatch_get_main_queue(), ^{ 764 | [self reloadAllComponents]; 765 | }); 766 | 767 | }); 768 | 769 | } 770 | } 771 | 772 | - (NSMutableArray *)getLimitDataForCurrentComponent:(LQYDateComponent)currentComponent components:(NSDateComponents *)components isMinimum:(BOOL)isMinimum { 773 | NSRange range = [self.calendar rangeOfUnit:self.unitFlags[currentComponent].unsignedIntegerValue inUnit:self.unitFlags[currentComponent - 1].unsignedIntegerValue forDate:[self.calendar dateFromComponents:components]]; 774 | NSInteger first = isMinimum ? [[components valueForKey:self.dateComponentKeys[currentComponent]] integerValue] : (currentComponent > LQYDateComponentDay) ? 0 : 1; 775 | NSInteger last = !isMinimum ? [[components valueForKey:self.dateComponentKeys[currentComponent]] integerValue] : (currentComponent > LQYDateComponentDay) ? (range.length - 1) : range.length; 776 | NSMutableArray *arr = [NSMutableArray array]; 777 | for (NSInteger i = first; i <= last; i++) { 778 | [arr addObject:@(i)]; 779 | } 780 | return arr; 781 | } 782 | 783 | /** 784 | * (废弃,耗性能)数据处理 785 | */ 786 | - (void)handleData:(const NSMutableArray *)dataArr minComponents:(NSDateComponents *)minComponents maxComponents:(NSDateComponents *)maxComponents components:(NSDateComponents *)components currentComponent:(LQYDateComponent)currentComponent dataDict:(const NSMutableDictionary * _Nullable)dataDict { 787 | NSInteger first = 0; 788 | NSInteger last = 0; 789 | if (currentComponent == LQYDateComponentYear) { 790 | first = minComponents.year; 791 | last = maxComponents.year; 792 | } else { 793 | NSRange range = [self.calendar rangeOfUnit:self.unitFlags[currentComponent].unsignedIntegerValue inUnit:self.unitFlags[currentComponent - 1].unsignedIntegerValue forDate:[self.calendar dateFromComponents:components]]; 794 | first = [self dateComponents:minComponents isEqualToDateComponents:components fromComponent:self.minimumComponent toComponent:currentComponent - 1] ? [[minComponents valueForKey:self.dateComponentKeys[currentComponent]] integerValue] : 1; 795 | last = [self dateComponents:maxComponents isEqualToDateComponents:components fromComponent:self.minimumComponent toComponent:currentComponent - 1] ? [[maxComponents valueForKey:self.dateComponentKeys[currentComponent]] integerValue] : range.length; 796 | } 797 | for (NSInteger i = first; i <= last; i++) { 798 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 799 | [dict setValue:[NSString stringWithFormat:@"%ld", i] forKey:@"name"]; 800 | if (self.minimumComponent < currentComponent) { 801 | [dataDict[@"list"] addObject:dict]; 802 | } else if (self.minimumComponent == currentComponent) { 803 | [dataArr addObject:dict]; 804 | } 805 | if (currentComponent < self.maximumComponent) { 806 | dict[@"list"] = [NSMutableArray array]; 807 | [components setValue:@(i) forKey:self.dateComponentKeys[currentComponent]]; 808 | [self handleData:dataArr minComponents:minComponents maxComponents:maxComponents components:components currentComponent:currentComponent + 1 dataDict:dict]; 809 | } 810 | } 811 | } 812 | 813 | - (BOOL)dateComponents:(NSDateComponents *)aComponents isEqualToDateComponents:(NSDateComponents *)bComponents fromComponent:(NSInteger)fromComponent toComponent:(NSInteger)toComponent { 814 | BOOL flag = true; 815 | for (NSInteger i = fromComponent; i <= toComponent; i++) { 816 | NSString *key = self.dateComponentKeys[i]; 817 | if ([aComponents valueForKey:key] != [bComponents valueForKey:key]) { 818 | flag = false; 819 | break; 820 | } 821 | } 822 | return flag; 823 | } 824 | 825 | - (BOOL)isMinimumBeforeComponent:(NSInteger)component { 826 | BOOL flag = true; 827 | for (NSInteger i = 0; i < component; i++) { 828 | NSInteger row = [self selectedRowInComponent:i]; 829 | if (row != 0) { 830 | flag = false; 831 | break; 832 | } 833 | } 834 | return flag; 835 | } 836 | 837 | - (BOOL)isMaximumBeforeComponent:(NSInteger)component { 838 | if (component == 0) { 839 | return false; 840 | } 841 | BOOL flag = true; 842 | for (NSInteger i = 0; i < component; i++) { 843 | NSInteger row = [self selectedRowInComponent:i]; 844 | NSInteger totalRows = [self numberOfRowsInComponent:i]; 845 | if (row < totalRows - 1) { 846 | flag = false; 847 | break; 848 | } 849 | } 850 | if (self.minimumComponent > LQYDateComponentYear && flag) { 851 | if ([self dateComponents:self.minComponents isEqualToDateComponents:self.maxComponents fromComponent:LQYDateComponentYear toComponent:component - self.minimumComponent]) { 852 | flag = true; 853 | } else { 854 | flag = false; 855 | } 856 | } 857 | return flag; 858 | } 859 | 860 | - (NSDateComponents *)dateComponentsInComponent:(NSInteger)component { 861 | NSCalendarUnit unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 862 | NSDateComponents *dateComponents = [self.calendar components:unitFlags fromDate:self.minimumDate]; 863 | for (NSInteger i = 0; i <= component; i++) { 864 | NSArray *arr = [self dataArrayInComponent:i]; 865 | NSInteger row = [self selectedRowInComponent:i]; 866 | NSNumber *number = row < arr.count ? arr[row] : @0; 867 | [dateComponents setValue:number forKey:self.dateComponentKeys[i + self.minimumComponent]]; 868 | } 869 | return dateComponents; 870 | } 871 | 872 | - (NSArray *)dataArrayInComponent:(NSInteger)component { 873 | LQYDateComponent currentComponent = component + self.minimumComponent; 874 | BOOL isMin = [self isMinimumBeforeComponent:component]; 875 | BOOL isMax = [self isMaximumBeforeComponent:component]; 876 | switch (currentComponent) { 877 | case LQYDateComponentYear: 878 | return self.dataJson[@"years"]; 879 | break; 880 | case LQYDateComponentMonth: 881 | return isMin ? self.dataJson[@"minMonths"] : (isMax ? self.dataJson[@"maxMonths"] : self.months); 882 | break; 883 | case LQYDateComponentDay: { 884 | NSDateComponents *components = [self dateComponentsInComponent:component - 1]; 885 | NSRange range = [self.calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:[self.calendar dateFromComponents:components]]; 886 | if (isMin) { 887 | return self.dataJson[@"minDays"]; 888 | } 889 | if (isMax) { 890 | return self.dataJson[@"maxDays"]; 891 | } 892 | switch (range.length) { 893 | case 28: 894 | return self.days_28; 895 | break; 896 | case 29: 897 | return self.days_29; 898 | break; 899 | case 30: 900 | return self.days_30; 901 | break; 902 | case 31: 903 | return self.days_31; 904 | default: 905 | return 0; 906 | break; 907 | } 908 | } 909 | break; 910 | case LQYDateComponentHour: 911 | return isMin ? self.dataJson[@"minHours"] : (isMax ? self.dataJson[@"maxHours"] : self.hours); 912 | break; 913 | case LQYDateComponentMinute: 914 | return isMin ? self.dataJson[@"minMinutes"] : (isMax ? self.dataJson[@"maxMinutes"] : self.minutes); 915 | break; 916 | case LQYDateComponentSecond: 917 | return isMin ? self.dataJson[@"minSeconds"] : (isMax ? self.dataJson[@"maxSeconds"] : self.seconds); 918 | break; 919 | default: 920 | return 0; 921 | break; 922 | } 923 | } 924 | 925 | #pragma mark - UIPickerViewDelegate, UIPickerViewDataSource 926 | 927 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 928 | return self.numberOfSection; 929 | } 930 | 931 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 932 | NSArray *dataArr = [self dataArrayInComponent:component]; 933 | return dataArr.count; 934 | } 935 | 936 | - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { 937 | return 44; 938 | } 939 | 940 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 941 | NSArray *dataArr = [self dataArrayInComponent:component]; 942 | NSDictionary *formatJson = self.dateFormatJson[@(component + self.minimumComponent)]; 943 | NSString *beforeText = formatJson && formatJson[LQYFormatTypeBeforeKey] ? formatJson[LQYFormatTypeBeforeKey] : @""; 944 | NSString *afterText = formatJson && formatJson[LQYFormatTypeAfterKey] ? formatJson[LQYFormatTypeAfterKey] : @""; 945 | NSNumber *number = row < dataArr.count ? dataArr[row] : dataArr.firstObject; 946 | NSString *text = [NSString stringWithFormat:@"%@%@%@", beforeText, number, afterText]; 947 | return text; 948 | } 949 | 950 | - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 951 | UILabel* pickerLabel = (UILabel*)view; 952 | if (!pickerLabel){ 953 | pickerLabel = [[UILabel alloc] init];; 954 | pickerLabel.textAlignment = NSTextAlignmentCenter; 955 | pickerLabel.font = [UIFont systemFontOfSize:16]; 956 | pickerLabel.textColor = [UIColor blackColor]; 957 | } 958 | 959 | NSString *text = [self pickerView:pickerView titleForRow:row forComponent:component]; 960 | 961 | pickerLabel.attributedText = [[NSAttributedString alloc] initWithString:text attributes:self.textAttributes]; 962 | 963 | return pickerLabel; 964 | } 965 | 966 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 967 | if (component < self.numberOfSection - 1) { 968 | for (NSInteger i = component + 1; i < self.numberOfSection; i++) { 969 | [pickerView reloadComponent:i]; 970 | } 971 | } 972 | } 973 | 974 | #pragma mark - delegate 975 | 976 | - (void)addDelegate:(MOFSPickerDelegateObject *)delegate { 977 | [self.lock lock]; 978 | self.delegatesDict[self.objectPointer] = delegate; 979 | [self.lock unlock]; 980 | } 981 | 982 | - (void)removeDelegate:(MOFSPickerDelegateObject *)delegate { 983 | [self.lock lock]; 984 | [self.delegatesDict removeObjectForKey:self.objectPointer]; 985 | [self.lock unlock]; 986 | } 987 | 988 | #pragma mark - public method 989 | 990 | - (void)setDateFormat:(NSString *)dateFormat formatType:(LQYFormatType)formatType component:(LQYDateComponent)component { 991 | const NSString *key = formatType == LQYFormatTypeBefore ? LQYFormatTypeBeforeKey : LQYFormatTypeAfterKey; 992 | if (self.dateFormatJson[@(component)]) { 993 | self.dateFormatJson[@(component)][key] = dateFormat; 994 | } else { 995 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject:dateFormat forKey:key]; 996 | self.dateFormatJson[@(component)] = dict; 997 | } 998 | NSInteger section = component = self.minimumComponent; 999 | if (section >= 0) { 1000 | [self reloadComponent:section]; 1001 | } 1002 | } 1003 | 1004 | - (void)showWithCommitBlock:(void (^)(NSDateComponents * _Nonnull))commitBlock cancelBlock:(void (^)(void))cancelBlock { 1005 | MOFSPickerDelegateObject *delegate = [MOFSPickerDelegateObject initWithCancelBlock:cancelBlock commitLQYDateBlock:commitBlock]; 1006 | [self addDelegate:delegate]; 1007 | [self show]; 1008 | } 1009 | 1010 | #pragma mark - Dealloc 1011 | 1012 | - (void)dealloc { 1013 | 1014 | } 1015 | 1016 | @end 1017 | 1018 | 1019 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSAddressModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSAddressModel.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/31. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class GDataXMLElement; 12 | @interface MOFSAddressModel : NSObject 13 | 14 | @property (nonatomic, strong) NSString *name; 15 | @property (nonatomic, strong) NSString *zipcode; 16 | @property (nonatomic, assign) NSInteger index; 17 | @property (nonatomic, strong) NSMutableArray *list; 18 | 19 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary; 20 | 21 | @end 22 | 23 | @interface MOFSAddressSelectedModel : NSObject 24 | 25 | /** 26 | * 省 27 | */ 28 | @property (nonatomic, strong) NSString *provinceName; 29 | @property (nonatomic, strong) NSString *provinceZipcode; 30 | @property (nonatomic, assign) NSInteger provinceIndex; 31 | 32 | /** 33 | * 市 34 | */ 35 | @property (nonatomic, strong) NSString *cityName; 36 | @property (nonatomic, strong) NSString *cityZipcode; 37 | @property (nonatomic, assign) NSInteger cityIndex; 38 | 39 | /** 40 | * 区 41 | */ 42 | @property (nonatomic, strong) NSString *districtName; 43 | @property (nonatomic, strong) NSString *districtZipcode; 44 | @property (nonatomic, assign) NSInteger districtIndex; 45 | 46 | - (instancetype)initWithProvinceName:(NSString *)provinceName cityName:(NSString *)cityName districtName:(NSString *)districtName; 47 | 48 | + (instancetype)initWithProvinceName:(NSString *)provinceName cityName:(NSString *)cityName districtName:(NSString *)districtName; 49 | 50 | - (instancetype)initWithProvinceZipcode:(NSString *)provinceZipcode cityZipcode:(NSString *)cityZipcode districtZipcode:(NSString *)districtZipcode; 51 | 52 | + (instancetype)initWithProvinceZipcode:(NSString *)provinceZipcode cityZipcode:(NSString *)cityZipcode districtZipcode:(NSString *)districtZipcode; 53 | 54 | - (instancetype)initWithProvinceIndex:(NSInteger)provinceIndex cityIndex:(NSInteger)cityIndex districtIndex:(NSInteger)districtIndex; 55 | 56 | + (instancetype)initWithProvinceIndex:(NSInteger)provinceIndex cityIndex:(NSInteger)cityIndex districtIndex:(NSInteger)districtIndex; 57 | 58 | - (void)copyModel:(MOFSAddressSelectedModel *)model; 59 | 60 | @end 61 | 62 | 63 | FOUNDATION_EXPORT NSErrorDomain const MOFSSearchErrorDomain; 64 | 65 | typedef NS_ENUM(NSInteger, MOFSSearchErrorCode) { 66 | MOFSSearchErrorCodeProvinceNotFound = 700, 67 | MOFSSearchErrorCodeCityNotFound = 701, 68 | MOFSSearchErrorCodeDistrictNotFound = 702, 69 | }; 70 | 71 | @interface MOFSSearchAddressModel : MOFSAddressSelectedModel 72 | 73 | @property (nonatomic, strong) NSError *error; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSAddressModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSAddressModel.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/31. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "MOFSAddressModel.h" 10 | 11 | NSErrorDomain const MOFSSearchErrorDomain = @"MOFSSearchErrorDomain"; 12 | 13 | @implementation MOFSAddressModel 14 | 15 | - (NSMutableArray *)list { 16 | if (!_list) { 17 | _list = [NSMutableArray array]; 18 | } 19 | return _list; 20 | } 21 | 22 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary { 23 | self = [super init]; 24 | if (self) { 25 | if (dictionary) { 26 | self.name = dictionary[@"name"]; 27 | self.zipcode = dictionary[@"zipcode"]; 28 | } 29 | } 30 | return self; 31 | } 32 | 33 | @end 34 | 35 | 36 | @implementation MOFSAddressSelectedModel 37 | 38 | - (instancetype)initWithProvinceName:(NSString *)provinceName cityName:(NSString *)cityName districtName:(NSString *)districtName { 39 | if (self = [super init]) { 40 | _provinceName = provinceName; 41 | _cityName = cityName; 42 | _districtName = districtName; 43 | } 44 | return self; 45 | } 46 | 47 | + (instancetype)initWithProvinceName:(NSString *)provinceName cityName:(NSString *)cityName districtName:(NSString *)districtName { 48 | MOFSAddressSelectedModel *model = [MOFSAddressSelectedModel new]; 49 | model.provinceName = provinceName; 50 | model.cityName = cityName; 51 | model.districtName = districtName; 52 | return model; 53 | } 54 | 55 | - (instancetype)initWithProvinceZipcode:(NSString *)provinceZipcode cityZipcode:(NSString *)cityZipcode districtZipcode:(NSString *)districtZipcode { 56 | if (self = [super init]) { 57 | _provinceZipcode = provinceZipcode; 58 | _cityZipcode = cityZipcode; 59 | _districtZipcode = districtZipcode; 60 | } 61 | return self; 62 | } 63 | 64 | + (instancetype)initWithProvinceZipcode:(NSString *)provinceZipcode cityZipcode:(NSString *)cityZipcode districtZipcode:(NSString *)districtZipcode { 65 | MOFSAddressSelectedModel *model = [MOFSAddressSelectedModel new]; 66 | model.provinceZipcode = provinceZipcode; 67 | model.cityZipcode = cityZipcode; 68 | model.districtZipcode = districtZipcode; 69 | return model; 70 | } 71 | 72 | - (instancetype)initWithProvinceIndex:(NSInteger)provinceIndex cityIndex:(NSInteger)cityIndex districtIndex:(NSInteger)districtIndex { 73 | if (self = [super init]) { 74 | _provinceIndex = provinceIndex; 75 | _cityIndex = cityIndex; 76 | _districtIndex = districtIndex; 77 | } 78 | return self; 79 | } 80 | 81 | + (instancetype)initWithProvinceIndex:(NSInteger)provinceIndex cityIndex:(NSInteger)cityIndex districtIndex:(NSInteger)districtIndex { 82 | MOFSAddressSelectedModel *model = [MOFSAddressSelectedModel new]; 83 | model.provinceIndex = provinceIndex; 84 | model.cityIndex = cityIndex; 85 | model.districtIndex = districtIndex; 86 | return model; 87 | } 88 | 89 | - (void)copyModel:(MOFSAddressSelectedModel *)model { 90 | _provinceName = model.provinceName; 91 | _provinceZipcode = model.provinceZipcode; 92 | 93 | _cityName = model.cityName; 94 | _cityZipcode = model.cityZipcode; 95 | 96 | _districtName = model.districtName; 97 | _districtZipcode = model.districtZipcode; 98 | } 99 | 100 | @end 101 | 102 | 103 | @implementation MOFSSearchAddressModel 104 | 105 | 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSAddressPickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSAddressPickerView.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/31. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MOFSToolView.h" 11 | #import "MOFSAddressModel.h" 12 | 13 | typedef NS_ENUM(NSInteger, MOFSAddressSearchType) { 14 | MOFSAddressSearchTypeByAddress = 0, //根据地址,查询其他信息 15 | MOFSAddressSearchTypeByZipcode = 1, //根据zipcode,查询其他信息 16 | MOFSAddressSearchTypeByIndex = 2, //根据下标,查询其他信息 17 | }; 18 | 19 | @interface MOFSAddressPickerView : UIPickerView 20 | 21 | @property (nullable, nonatomic, readonly) NSMutableArray *addressDataArray; 22 | 23 | @property (nullable, nonatomic, strong) MOFSToolView *toolBar; 24 | @property (nullable, nonatomic, strong) UIView *containerView; 25 | @property (nullable, nonatomic, strong) void (^containerViewClickedBlock)(void); 26 | @property (nonatomic, assign) NSInteger numberOfSection; 27 | @property (nonatomic, assign) BOOL usedXML; 28 | 29 | @property (nullable, nonatomic, strong) NSDictionary *attributes; 30 | 31 | 32 | /** 33 | * 显示选择器 34 | * @param title 选择器toolBar中间标题 35 | * @param commitTitle 确定标题 36 | * @param cancelTitle 取消标题 37 | */ 38 | - (void)showWithTitle:(NSString * _Nullable)title 39 | commitTitle:(NSString * _Nullable)commitTitle 40 | cancelTitle:(NSString * _Nullable)cancelTitle 41 | commitBlock:(void(^ _Nullable)(MOFSAddressSelectedModel * _Nullable selectedModel))commitBlock 42 | cancelBlock:(void(^_Nullable)(void))cancelBlock; 43 | 44 | /** 45 | * 显示选择器 46 | * @param selectedAddress 默认选中的地址 47 | * @param title 选择器toolBar中间标题 48 | * @param commitTitle 确定标题 49 | * @param cancelTitle 取消标题 50 | */ 51 | - (void)showWithSelectedAddress:(MOFSAddressSelectedModel * _Nullable)selectedAddress 52 | title:(NSString * _Nullable)title 53 | commitTitle:(NSString * _Nullable)commitTitle 54 | cancelTitle:(NSString * _Nullable)cancelTitle 55 | commitBlock:(void(^ _Nullable)(MOFSAddressSelectedModel * _Nullable selectedModel))commitBlock 56 | cancelBlock:(void(^_Nullable)(void))cancelBlock; 57 | 58 | /** 59 | * 显示选择器 60 | * @param selectedZipcode 默认选中的地址代码 61 | * @param title 选择器toolBar中间标题 62 | * @param commitTitle 确定标题 63 | * @param cancelTitle 取消标题 64 | */ 65 | - (void)showWithSelectedZipcode:(MOFSAddressSelectedModel * _Nullable)selectedZipcode 66 | title:(NSString * _Nullable)title 67 | commitTitle:(NSString * _Nullable)commitTitle 68 | cancelTitle:(NSString * _Nullable)cancelTitle 69 | commitBlock:(void(^ _Nullable)(MOFSAddressSelectedModel * _Nullable selectedModel))commitBlock 70 | cancelBlock:(void(^_Nullable)(void))cancelBlock; 71 | 72 | 73 | - (void)searchType:(MOFSAddressSearchType)searchType keyModel:(MOFSAddressSelectedModel *_Nullable)keyModel block:(void(^_Nullable)(MOFSSearchAddressModel * _Nullable result))block; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSAddressPickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSAddressPickerView.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/31. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "MOFSAddressPickerView.h" 10 | 11 | #define UISCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 12 | #define UISCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 13 | 14 | @interface MOFSAddressPickerView() 15 | 16 | @property (nonatomic, strong) NSXMLParser *parser; 17 | 18 | @property (nonatomic, strong) UIView *bgView; 19 | @property (nonatomic, strong) NSMutableArray *dataArr; 20 | 21 | @property (nonatomic, assign) NSInteger selectedIndex_province; 22 | @property (nonatomic, assign) NSInteger selectedIndex_city; 23 | @property (nonatomic, assign) NSInteger selectedIndex_area; 24 | 25 | @property (nonatomic, assign) BOOL isGettingData; 26 | @property (nonatomic, strong) void (^getDataCompleteBlock)(void); 27 | 28 | @property (nonatomic, strong) dispatch_semaphore_t semaphore; 29 | 30 | @property (nonatomic, strong) NSMutableDictionary *delegatesDict; 31 | @property (readwrite, nonatomic, strong) NSLock *lock; 32 | 33 | @property (nonatomic, strong) NSString *objectPointer; 34 | 35 | @end 36 | 37 | @implementation MOFSAddressPickerView 38 | 39 | #pragma mark - setter 40 | 41 | - (void)setAttributes:(NSDictionary *)attributes { 42 | _attributes = attributes; 43 | dispatch_async(dispatch_get_main_queue(), ^{ 44 | [self reloadAllComponents]; 45 | }); 46 | } 47 | 48 | - (void)setNumberOfSection:(NSInteger)numberOfSection { 49 | if (numberOfSection <= 0 || numberOfSection > 3) { 50 | _numberOfSection = 3; 51 | } else { 52 | _numberOfSection = numberOfSection; 53 | } 54 | dispatch_async(dispatch_get_main_queue(), ^{ 55 | [self reloadAllComponents]; 56 | }); 57 | } 58 | 59 | - (void)setUsedXML:(BOOL)usedXML { 60 | if (usedXML != _usedXML) { 61 | _usedXML = usedXML; 62 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 63 | 64 | [self getData]; 65 | dispatch_queue_t queue = dispatch_queue_create("my.current.queue", DISPATCH_QUEUE_CONCURRENT); 66 | dispatch_barrier_async(queue, ^{ 67 | dispatch_async(dispatch_get_main_queue(), ^{ 68 | [self reloadAllComponents]; 69 | }); 70 | }); 71 | }); 72 | } 73 | } 74 | 75 | #pragma mark - getter 76 | 77 | - (NSLock *)lock { 78 | if (!_lock) { 79 | _lock = [[NSLock alloc] init]; 80 | _lock.name = @"com.ly.addressPicker.lock"; 81 | } 82 | return _lock; 83 | } 84 | 85 | - (NSMutableDictionary *)delegatesDict { 86 | if (!_delegatesDict) { 87 | _delegatesDict = [NSMutableDictionary dictionary]; 88 | } 89 | return _delegatesDict; 90 | } 91 | 92 | - (NSMutableArray *)addressDataArray { 93 | return _dataArr; 94 | } 95 | 96 | - (NSString *)objectPointer { 97 | return [NSString stringWithFormat:@"%p", self]; 98 | } 99 | 100 | #pragma mark - create UI 101 | 102 | - (instancetype)initWithFrame:(CGRect)frame { 103 | 104 | self.semaphore = dispatch_semaphore_create(1); 105 | 106 | [self initToolBar]; 107 | [self initContainerView]; 108 | 109 | CGRect initialFrame; 110 | if (CGRectIsEmpty(frame)) { 111 | initialFrame = CGRectMake(0, self.toolBar.frame.size.height, UISCREEN_WIDTH, 216); 112 | } else { 113 | initialFrame = frame; 114 | } 115 | self = [super initWithFrame:initialFrame]; 116 | if (self) { 117 | self.backgroundColor = [UIColor whiteColor]; 118 | 119 | self.delegate = self; 120 | self.dataSource = self; 121 | 122 | [self initBgView]; 123 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 124 | 125 | [self getData]; 126 | dispatch_queue_t queue = dispatch_queue_create("my.current.queue", DISPATCH_QUEUE_CONCURRENT); 127 | dispatch_barrier_async(queue, ^{ 128 | dispatch_async(dispatch_get_main_queue(), ^{ 129 | [self reloadAllComponents]; 130 | }); 131 | }); 132 | }); 133 | } 134 | return self; 135 | } 136 | 137 | - (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated { 138 | if (component >= self.numberOfComponents) { 139 | return; 140 | } 141 | [super selectRow:row inComponent:component animated:animated]; 142 | switch (component) { 143 | case 0: 144 | self.selectedIndex_province = row; 145 | self.selectedIndex_city = 0; 146 | self.selectedIndex_area = 0; 147 | if (self.numberOfSection > 1) { 148 | [self reloadComponent:1]; 149 | } 150 | if (self.numberOfSection > 2) { 151 | [self reloadComponent:2]; 152 | } 153 | break; 154 | case 1: 155 | self.selectedIndex_city = row; 156 | self.selectedIndex_area = 0; 157 | if (self.numberOfSection > 2) { 158 | [self reloadComponent:2]; 159 | } 160 | break; 161 | case 2: 162 | self.selectedIndex_area = row; 163 | break; 164 | default: 165 | break; 166 | } 167 | } 168 | 169 | - (void)initToolBar { 170 | self.toolBar = [[MOFSToolView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, 44)]; 171 | self.toolBar.backgroundColor = [UIColor whiteColor]; 172 | [self.toolBar.cancelBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelAction)]]; 173 | [self.toolBar.commitBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(commitAction)]]; 174 | } 175 | 176 | - (void)initContainerView { 177 | self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, UISCREEN_HEIGHT)]; 178 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 179 | self.containerView.userInteractionEnabled = YES; 180 | [self.containerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(containerViewClickedAction)]]; 181 | } 182 | 183 | - (void)initBgView { 184 | self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, UISCREEN_HEIGHT - self.frame.size.height - 44, UISCREEN_WIDTH, self.frame.size.height + self.toolBar.frame.size.height)]; 185 | } 186 | 187 | #pragma mark - ToolBar Action 188 | 189 | - (void)cancelAction { 190 | [self hiddenWithAnimation]; 191 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 192 | if (delegate.cancelBlock) { 193 | delegate.cancelBlock(); 194 | } 195 | 196 | [self removeDelegate:delegate]; 197 | } 198 | 199 | - (void)commitAction { 200 | [self hiddenWithAnimation]; 201 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 202 | if (delegate.commitAddressBlock) { 203 | 204 | if (self.dataArr.count > 0) { 205 | MOFSAddressModel *provinceModel = self.dataArr[self.selectedIndex_province]; 206 | MOFSAddressModel *cityModel; 207 | MOFSAddressModel *districtModel; 208 | if (provinceModel.list.count > 0 && self.numberOfComponents > 1) { 209 | cityModel = provinceModel.list[self.selectedIndex_city]; 210 | } 211 | if (cityModel && cityModel.list.count > 0 && self.numberOfComponents > 2) { 212 | districtModel = cityModel.list[self.selectedIndex_area]; 213 | } 214 | 215 | MOFSAddressSelectedModel *selectedModel = [MOFSAddressSelectedModel new]; 216 | selectedModel.provinceName = provinceModel.name; 217 | selectedModel.provinceZipcode = provinceModel.zipcode; 218 | selectedModel.provinceIndex = provinceModel.index; 219 | selectedModel.cityName = cityModel.name; 220 | selectedModel.cityZipcode = cityModel.zipcode; 221 | selectedModel.cityIndex = cityModel.index; 222 | selectedModel.districtName = districtModel.name; 223 | selectedModel.districtZipcode = districtModel.zipcode; 224 | selectedModel.districtIndex = districtModel.index; 225 | 226 | delegate.commitAddressBlock(selectedModel); 227 | } 228 | } 229 | [self removeDelegate:delegate]; 230 | } 231 | 232 | #pragma mark - delegate 233 | 234 | - (void)addDelegate:(MOFSPickerDelegateObject *)delegate { 235 | [self.lock lock]; 236 | self.delegatesDict[self.objectPointer] = delegate; 237 | [self.lock unlock]; 238 | } 239 | 240 | - (void)removeDelegate:(MOFSPickerDelegateObject *)delegate { 241 | [self.lock lock]; 242 | [self.delegatesDict removeObjectForKey:self.objectPointer]; 243 | [self.lock unlock]; 244 | } 245 | 246 | #pragma mark - Action 247 | 248 | /** 249 | * 显示选择器 250 | * @param title 选择器toolBar中间标题 251 | * @param commitTitle 确定标题 252 | * @param cancelTitle 取消标题 253 | */ 254 | - (void)showWithTitle:(NSString * _Nullable)title 255 | commitTitle:(NSString * _Nullable)commitTitle 256 | cancelTitle:(NSString * _Nullable)cancelTitle 257 | commitBlock:(void (^ _Nullable)(MOFSAddressSelectedModel * _Nullable selectedModel))commitBlock 258 | cancelBlock:(void (^ _Nullable)(void))cancelBlock { 259 | [self showWithSelectedAddress:nil title:title commitTitle:commitTitle cancelTitle:cancelTitle commitBlock:commitBlock cancelBlock:cancelBlock]; 260 | } 261 | 262 | /** 263 | * 显示选择器 264 | * @param selectedAddress 默认选中的地址 265 | * @param title 选择器toolBar中间标题 266 | * @param commitTitle 确定标题 267 | * @param cancelTitle 取消标题 268 | */ 269 | - (void)showWithSelectedAddress:(MOFSAddressSelectedModel * _Nullable)selectedAddress 270 | title:(NSString * _Nullable)title 271 | commitTitle:(NSString * _Nullable)commitTitle 272 | cancelTitle:(NSString * _Nullable)cancelTitle 273 | commitBlock:(void (^ _Nullable)(MOFSAddressSelectedModel * _Nullable selectedModel))commitBlock 274 | cancelBlock:(void (^ _Nullable)(void))cancelBlock { 275 | if (self.numberOfSection <= 0 || self.numberOfComponents > 3) { 276 | self.numberOfSection = 3; 277 | } 278 | 279 | self.toolBar.titleBarTitle = title; 280 | self.toolBar.commitBarTitle = commitTitle; 281 | self.toolBar.cancelBarTitle = cancelTitle; 282 | 283 | //iOS 10及以上需要添加 这一行代码,否则第一次不显示中间两条分割线 284 | if ([self numberOfRowsInComponent:0] > 0) {} 285 | 286 | [self showWithAnimation]; 287 | 288 | MOFSPickerDelegateObject *delegate = [MOFSPickerDelegateObject initWithCancelBlock:cancelBlock commitAddressBlock:commitBlock]; 289 | [self addDelegate:delegate]; 290 | 291 | if (selectedAddress) { 292 | [self searchType:MOFSAddressSearchTypeByAddress keyModel:selectedAddress block:^(MOFSSearchAddressModel * _Nullable result) { 293 | if (!result.error) { 294 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 295 | [self selectRow:result.provinceIndex inComponent:0 animated:NO]; 296 | [self selectRow:result.cityIndex inComponent:1 animated:NO]; 297 | [self selectRow:result.districtIndex inComponent:2 animated:NO]; 298 | }); 299 | } 300 | }]; 301 | } 302 | 303 | } 304 | 305 | /** 306 | * 显示选择器 307 | * @param selectedZipcode 默认选中的地址代码 308 | * @param title 选择器toolBar中间标题 309 | * @param commitTitle 确定标题 310 | * @param cancelTitle 取消标题 311 | */ 312 | - (void)showWithSelectedZipcode:(MOFSAddressSelectedModel * _Nullable)selectedZipcode 313 | title:(NSString * _Nullable)title 314 | commitTitle:(NSString * _Nullable)commitTitle 315 | cancelTitle:(NSString * _Nullable)cancelTitle 316 | commitBlock:(void(^ _Nullable)(MOFSAddressSelectedModel * _Nullable selectedModel))commitBlock 317 | cancelBlock:(void(^_Nullable)(void))cancelBlock { 318 | if (self.numberOfSection <= 0 || self.numberOfComponents > 3) { 319 | self.numberOfSection = 3; 320 | } 321 | 322 | self.toolBar.titleBarTitle = title; 323 | self.toolBar.commitBarTitle = commitTitle; 324 | self.toolBar.cancelBarTitle = cancelTitle; 325 | 326 | //iOS 10及以上需要添加 这一行代码,否则第一次不显示中间两条分割线 327 | if ([self numberOfRowsInComponent:0] > 0) {} 328 | 329 | [self showWithAnimation]; 330 | 331 | MOFSPickerDelegateObject *delegate = [MOFSPickerDelegateObject initWithCancelBlock:cancelBlock commitAddressBlock:commitBlock]; 332 | [self addDelegate:delegate]; 333 | 334 | if (selectedZipcode) { 335 | [self searchType:MOFSAddressSearchTypeByZipcode keyModel:selectedZipcode block:^(MOFSSearchAddressModel * _Nullable result) { 336 | if (!result.error) { 337 | @try { 338 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 339 | [self selectRow:result.provinceIndex inComponent:0 animated:NO]; 340 | [self selectRow:result.cityIndex inComponent:1 animated:NO]; 341 | [self selectRow:result.districtIndex inComponent:2 animated:NO]; 342 | }); 343 | } @catch (NSException *exception) { 344 | 345 | } @finally { 346 | 347 | } 348 | } 349 | }]; 350 | } 351 | } 352 | 353 | - (void)showWithAnimation { 354 | [self addViews]; 355 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; 356 | CGFloat height = self.bgView.frame.size.height; 357 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2); 358 | [UIView animateWithDuration:0.25 animations:^{ 359 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT - height / 2); 360 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 361 | }]; 362 | 363 | } 364 | 365 | - (void)hiddenWithAnimation { 366 | CGFloat height = self.bgView.frame.size.height; 367 | [UIView animateWithDuration:0.25 animations:^{ 368 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2); 369 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; 370 | } completion:^(BOOL finished) { 371 | [self hiddenViews]; 372 | }]; 373 | } 374 | 375 | - (void)containerViewClickedAction { 376 | if (self.containerViewClickedBlock) { 377 | self.containerViewClickedBlock(); 378 | } 379 | [self hiddenWithAnimation]; 380 | } 381 | 382 | - (void)addViews { 383 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 384 | [window addSubview:self.containerView]; 385 | [window addSubview:self.bgView]; 386 | [self.bgView addSubview:self.toolBar]; 387 | [self.bgView addSubview:self]; 388 | } 389 | 390 | - (void)hiddenViews { 391 | [self removeFromSuperview]; 392 | [self.toolBar removeFromSuperview]; 393 | [self.bgView removeFromSuperview]; 394 | [self.containerView removeFromSuperview]; 395 | } 396 | 397 | #pragma mark - get data 398 | 399 | - (void)getData { 400 | if (self.isGettingData) { 401 | return; 402 | } 403 | self.isGettingData = YES; 404 | NSString *extName = _usedXML ? @"xml" : @"json"; 405 | NSString *path = [[NSBundle mainBundle] pathForResource:@"province_data" ofType:extName]; 406 | if (path == nil) { 407 | for (NSBundle *bundle in [NSBundle allFrameworks]) { 408 | path = [bundle pathForResource:@"province_data" ofType:extName]; 409 | if (path != nil) { 410 | break; 411 | } 412 | } 413 | } 414 | 415 | if (path == nil) { 416 | self.isGettingData = NO; 417 | if (self.getDataCompleteBlock) { 418 | self.getDataCompleteBlock(); 419 | } 420 | return; 421 | } 422 | 423 | if (!_dataArr) { 424 | _dataArr = [NSMutableArray array]; 425 | } 426 | if (_dataArr.count != 0) { 427 | [_dataArr removeAllObjects]; 428 | } 429 | 430 | if (_usedXML) { 431 | self.parser = [[NSXMLParser alloc] initWithData:[NSData dataWithContentsOfFile:path]]; 432 | self.parser.delegate = self; 433 | [self.parser parse]; 434 | } else { 435 | NSData *data = [[NSData alloc] initWithContentsOfFile:path]; 436 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; 437 | if (dict[@"province"] && [dict[@"province"] isKindOfClass:[NSArray class]]) { 438 | NSArray *arr = dict[@"province"]; 439 | for (NSDictionary *provinceJson in arr) { 440 | MOFSAddressModel *provinceModel = [[MOFSAddressModel alloc] initWithDictionary:provinceJson]; 441 | provinceModel.index = self.dataArr.count; 442 | if (provinceJson[@"city"] && [provinceJson[@"city"] isKindOfClass:[NSArray class]]) { 443 | for (NSDictionary *cityJson in provinceJson[@"city"]) { 444 | MOFSAddressModel *cityModel = [[MOFSAddressModel alloc] initWithDictionary:cityJson]; 445 | cityModel.index = provinceModel.list.count; 446 | [provinceModel.list addObject:cityModel]; 447 | if (cityJson[@"district"] && [cityJson[@"district"] isKindOfClass:[NSArray class]]) { 448 | for (NSDictionary *districtJson in cityJson[@"district"]) { 449 | MOFSAddressModel *model = [[MOFSAddressModel alloc] initWithDictionary:districtJson]; 450 | model.index = cityModel.list.count; 451 | [cityModel.list addObject:model]; 452 | } 453 | } 454 | } 455 | } 456 | [self.dataArr addObject:provinceModel]; 457 | } 458 | } 459 | 460 | self.isGettingData = NO; 461 | if (self.getDataCompleteBlock) { 462 | self.getDataCompleteBlock(); 463 | } 464 | 465 | } 466 | } 467 | 468 | 469 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { 470 | if ([elementName isEqualToString:@"province"]) { 471 | MOFSAddressModel *model = [[MOFSAddressModel alloc] initWithDictionary:attributeDict]; 472 | model.index = self.dataArr.count; 473 | [self.dataArr addObject:model]; 474 | } else if ([elementName isEqualToString:@"city"]) { 475 | MOFSAddressModel *model = [[MOFSAddressModel alloc] initWithDictionary:attributeDict]; 476 | model.index = self.dataArr.lastObject.list.count; 477 | [self.dataArr.lastObject.list addObject:model]; 478 | } else if ([elementName isEqualToString:@"district"]) { 479 | MOFSAddressModel *model = [[MOFSAddressModel alloc] initWithDictionary:attributeDict]; 480 | model.index = self.dataArr.lastObject.list.lastObject.list.count; 481 | [self.dataArr.lastObject.list.lastObject.list addObject: model]; 482 | } 483 | } 484 | 485 | - (void)parserDidEndDocument:(NSXMLParser *)parser { 486 | self.isGettingData = NO; 487 | if (self.getDataCompleteBlock) { 488 | self.getDataCompleteBlock(); 489 | } 490 | } 491 | 492 | #pragma mark - search 493 | 494 | - (void)searchType:(MOFSAddressSearchType)searchType keyModel:(MOFSAddressSelectedModel *)keyModel block:(void (^)(MOFSSearchAddressModel * _Nullable))block { 495 | 496 | dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER); 497 | 498 | NSString *searchKeyName = @""; 499 | 500 | switch (searchType) { 501 | case MOFSAddressSearchTypeByAddress: 502 | searchKeyName = @"name"; 503 | break; 504 | case MOFSAddressSearchTypeByZipcode: 505 | searchKeyName = @"zipcode"; 506 | break; 507 | case MOFSAddressSearchTypeByIndex: 508 | searchKeyName = @"index"; 509 | break; 510 | default: 511 | break; 512 | } 513 | 514 | if (self.isGettingData || !self.dataArr || self.dataArr.count == 0) { 515 | __weak typeof(self) weakSelf = self; 516 | self.getDataCompleteBlock = ^{ 517 | if (block) { 518 | 519 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 520 | block([weakSelf searchByKeyModel:keyModel searchType:searchType keyName:searchKeyName]); 521 | }); 522 | 523 | dispatch_semaphore_signal(weakSelf.semaphore); 524 | } 525 | }; 526 | } else { 527 | if (block) { 528 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 529 | block([self searchByKeyModel:keyModel searchType:searchType keyName:searchKeyName]); 530 | }); 531 | dispatch_semaphore_signal(self.semaphore); 532 | } 533 | } 534 | 535 | } 536 | 537 | 538 | - (MOFSSearchAddressModel * _Nullable)searchByKeyModel:(MOFSAddressSelectedModel *)keyModel searchType:(MOFSAddressSearchType)searchType keyName:(NSString *)keyName { 539 | 540 | if (!keyModel) { 541 | return nil; 542 | } 543 | 544 | MOFSSearchAddressModel *resultModel = [MOFSSearchAddressModel new]; 545 | [resultModel copyModel:keyModel]; 546 | 547 | id provinceValue, cityValue, districtValue; 548 | switch (searchType) { 549 | case MOFSAddressSearchTypeByAddress: 550 | provinceValue = keyModel.provinceName; 551 | cityValue = keyModel.cityName; 552 | districtValue = keyModel.districtName; 553 | break; 554 | case MOFSAddressSearchTypeByZipcode: 555 | provinceValue = keyModel.provinceZipcode; 556 | cityValue = keyModel.cityZipcode; 557 | districtValue = keyModel.districtZipcode; 558 | break; 559 | case MOFSAddressSearchTypeByIndex: 560 | provinceValue = @(keyModel.provinceIndex); 561 | cityValue = @(keyModel.cityIndex); 562 | districtValue = @(keyModel.districtIndex); 563 | break; 564 | default: 565 | break; 566 | } 567 | 568 | MOFSAddressModel *provinceModel = (MOFSAddressModel *)[self searchModelInArr:_dataArr key:keyName value:provinceValue]; 569 | if (provinceModel) { 570 | resultModel.provinceName = provinceModel.name; 571 | resultModel.provinceZipcode = provinceModel.zipcode; 572 | resultModel.provinceIndex = provinceModel.index; 573 | 574 | MOFSAddressModel *cityModel = (MOFSAddressModel *)[self searchModelInArr:provinceModel.list key:keyName value:cityValue]; 575 | if (cityModel) { 576 | resultModel.cityName = cityModel.name; 577 | resultModel.cityZipcode = cityModel.zipcode; 578 | resultModel.cityIndex = cityModel.index; 579 | 580 | MOFSAddressModel *districtModel = (MOFSAddressModel *)[self searchModelInArr:cityModel.list key:keyName value:districtValue]; 581 | if (districtModel) { 582 | resultModel.districtName = districtModel.name; 583 | resultModel.districtZipcode = districtModel.zipcode; 584 | resultModel.districtIndex = districtModel.index; 585 | } else { 586 | resultModel.error = [NSError errorWithDomain:MOFSSearchErrorDomain code:MOFSSearchErrorCodeDistrictNotFound userInfo:nil]; 587 | } 588 | } else { 589 | resultModel.error = [NSError errorWithDomain:MOFSSearchErrorDomain code:MOFSSearchErrorCodeCityNotFound userInfo:nil]; 590 | } 591 | } else { 592 | resultModel.error = [NSError errorWithDomain:MOFSSearchErrorDomain code:MOFSSearchErrorCodeProvinceNotFound userInfo:nil]; 593 | } 594 | 595 | return resultModel; 596 | } 597 | 598 | - (NSObject *)searchModelInArr:(NSArray *)arr key:(NSString *)key value:(id)value { 599 | NSArray *filterArr = [arr filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF.%@ = %@", key, value]]; 600 | return filterArr.firstObject; 601 | } 602 | 603 | 604 | #pragma mark - UIPickerViewDelegate,UIPickerViewDataSource 605 | 606 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 607 | return self.numberOfSection; 608 | } 609 | 610 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 611 | MOFSAddressModel *provinceModel; 612 | if (self.dataArr.count > 0) { 613 | provinceModel = self.dataArr[self.selectedIndex_province]; 614 | } 615 | 616 | MOFSAddressModel *cityModel; 617 | if (provinceModel && provinceModel.list.count > 0) { 618 | cityModel = provinceModel.list[self.selectedIndex_city]; 619 | } 620 | if (self.dataArr.count != 0) { 621 | if (component == 0) { 622 | return self.dataArr.count; 623 | } else if (component == 1) { 624 | return provinceModel == nil ? 0 : provinceModel.list.count; 625 | } else if (component == 2) { 626 | return cityModel == nil ? 0 : cityModel.list.count; 627 | } else { 628 | return 0; 629 | } 630 | } else { 631 | return 0; 632 | } 633 | 634 | } 635 | 636 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 637 | 638 | if (component == 0) { 639 | MOFSAddressModel *provinceModel = self.dataArr[row]; 640 | return provinceModel.name; 641 | } else if (component == 1) { 642 | MOFSAddressModel *provinceModel = self.dataArr[self.selectedIndex_province]; 643 | MOFSAddressModel *cityModel = provinceModel.list[row]; 644 | return cityModel.name; 645 | } else if (component == 2) { 646 | MOFSAddressModel *provinceModel = self.dataArr[self.selectedIndex_province]; 647 | MOFSAddressModel *cityModel = provinceModel.list[self.selectedIndex_city]; 648 | MOFSAddressModel *districtModel = cityModel.list[row]; 649 | return districtModel.name; 650 | } else { 651 | return nil; 652 | } 653 | } 654 | 655 | - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 656 | UILabel* pickerLabel = (UILabel*)view; 657 | if (!pickerLabel){ 658 | pickerLabel = [[UILabel alloc] init];; 659 | pickerLabel.textAlignment = NSTextAlignmentCenter; 660 | pickerLabel.font = [UIFont systemFontOfSize:16]; 661 | pickerLabel.textColor = [UIColor colorWithRed:12.f/255.f green:14.f/255.f blue:14.f/255.f alpha:1]; 662 | } 663 | 664 | NSString *text = [self pickerView:pickerView titleForRow:row forComponent:component]; 665 | 666 | pickerLabel.attributedText = [[NSAttributedString alloc] initWithString:text attributes:_attributes]; 667 | 668 | return pickerLabel; 669 | } 670 | 671 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 672 | switch (component) { 673 | case 0: 674 | self.selectedIndex_province = row; 675 | self.selectedIndex_city = 0; 676 | self.selectedIndex_area = 0; 677 | if (self.numberOfSection > 1) { 678 | [pickerView reloadComponent:1]; 679 | [pickerView selectRow:0 inComponent:1 animated:NO]; 680 | } 681 | if (self.numberOfSection > 2) { 682 | [pickerView reloadComponent:2]; 683 | [pickerView selectRow:0 inComponent:2 animated:NO]; 684 | } 685 | break; 686 | case 1: 687 | self.selectedIndex_city = row; 688 | self.selectedIndex_area = 0; 689 | if (self.numberOfSection > 2) { 690 | [pickerView reloadComponent:2]; 691 | [pickerView selectRow:0 inComponent:2 animated:NO]; 692 | } 693 | break; 694 | case 2: 695 | self.selectedIndex_area = row; 696 | break; 697 | default: 698 | break; 699 | } 700 | } 701 | 702 | #pragma mark - Dealloc 703 | 704 | - (void)dealloc { 705 | 706 | } 707 | 708 | @end 709 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSDatePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSDatePicker.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/26. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MOFSToolView.h" 11 | 12 | typedef void (^CommitBlock)(NSDate * _Nullable date); 13 | typedef void (^CancelBlock)(void); 14 | 15 | @interface MOFSDatePicker : UIDatePicker 16 | 17 | @property (nullable, nonatomic, strong) MOFSToolView *toolBar; 18 | @property (nullable,nonatomic, strong) UIView *containerView; 19 | 20 | @property (nullable,nonatomic, strong) void (^containerViewClickedBlock)(void); 21 | 22 | /** 23 | * 显示日期选择器 24 | * @param selectedDate 默认选中的日期 25 | */ 26 | - (void)showWithSelectedDate:(NSDate * _Nullable)selectedDate 27 | commit:(CommitBlock _Nullable)commitBlock 28 | cancel:(CancelBlock _Nullable)cancelBlock; 29 | 30 | /** 31 | * 显示日期选择器 32 | * @param title 选择器toolBar中间标题 33 | * @param commitTitle 确定标题 34 | * @param cancelTitle 取消标题 35 | * @param selectedDate 默认选中的日期 36 | * @param minDate 选择器最小日期 37 | * @param maxDate 选择器最大日期 38 | * @param mode 选择器模式 39 | */ 40 | - (void)showWithTitle:(NSString * _Nullable)title 41 | commitTitle:(NSString * _Nullable)commitTitle 42 | cancelTitle:(NSString * _Nullable)cancelTitle 43 | selectedDate:(NSDate * _Nullable)selectedDate 44 | minDate:(NSDate * _Nullable)minDate 45 | maxDate:(NSDate * _Nullable)maxDate 46 | datePickerMode:(UIDatePickerMode)mode 47 | commitBlock:(CommitBlock _Nullable )commitBlock 48 | cancelBlock:(CancelBlock _Nullable )cancelBlock; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSDatePicker.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSDatePicker.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/26. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "MOFSDatePicker.h" 10 | 11 | #define UISCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 12 | #define UISCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 13 | 14 | @interface MOFSDatePicker() 15 | 16 | @property (nonatomic, strong) UIView *bgView; 17 | 18 | @property (nonatomic, strong) NSMutableDictionary *delegatesDict; 19 | @property (readwrite, nonatomic, strong) NSLock *lock; 20 | 21 | @property (nonatomic, strong) NSString *objectPointer; 22 | 23 | @end 24 | 25 | 26 | @implementation MOFSDatePicker 27 | 28 | #pragma mark - Getter 29 | 30 | - (NSLock *)lock { 31 | if (!_lock) { 32 | _lock = [[NSLock alloc] init]; 33 | _lock.name = @"com.ly.datePicker.lock"; 34 | } 35 | return _lock; 36 | } 37 | 38 | - (NSMutableDictionary *)delegatesDict { 39 | if (!_delegatesDict) { 40 | _delegatesDict = [NSMutableDictionary dictionary]; 41 | } 42 | return _delegatesDict; 43 | } 44 | 45 | - (NSString *)objectPointer { 46 | return [NSString stringWithFormat:@"%p", self]; 47 | } 48 | 49 | #pragma mark - create UI 50 | 51 | - (instancetype)initWithFrame:(CGRect)frame { 52 | 53 | [self initToolBar]; 54 | [self initContainerView]; 55 | 56 | CGRect initialFrame; 57 | if (CGRectIsEmpty(frame)) { 58 | initialFrame = CGRectMake(0, self.toolBar.frame.size.height, UISCREEN_WIDTH, 216); 59 | } else { 60 | initialFrame = frame; 61 | } 62 | self = [super initWithFrame:initialFrame]; 63 | if (self) { 64 | self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth; 65 | self.backgroundColor = [UIColor whiteColor]; 66 | self.tintColor = [UIColor whiteColor]; 67 | self.datePickerMode = UIDatePickerModeDate; 68 | self.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]; 69 | if (@available(iOS 13.4, *)) { 70 | self.preferredDatePickerStyle = UIDatePickerStyleWheels; 71 | } else { 72 | // Fallback on earlier versions 73 | } 74 | 75 | [self initBgView]; 76 | } 77 | return self; 78 | } 79 | 80 | - (void)layoutSubviews { 81 | [super layoutSubviews]; 82 | 83 | CGRect frame = self.frame; 84 | frame.origin.x = 0; 85 | frame.origin.y = self.bgView.bounds.size.height - frame.size.height; 86 | frame.size.width = self.bgView.frame.size.width; 87 | self.frame = frame; 88 | 89 | } 90 | 91 | - (void)initToolBar { 92 | self.toolBar = [[MOFSToolView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, 44)]; 93 | self.toolBar.backgroundColor = [UIColor whiteColor]; 94 | [self.toolBar.cancelBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelAction)]]; 95 | [self.toolBar.commitBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(commitAction)]]; 96 | } 97 | 98 | - (void)initContainerView { 99 | self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, UISCREEN_HEIGHT)]; 100 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 101 | self.containerView.userInteractionEnabled = YES; 102 | [self.containerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(containerViewClickedAction)]]; 103 | } 104 | 105 | - (void)initBgView { 106 | self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, UISCREEN_HEIGHT - self.frame.size.height - 44, UISCREEN_WIDTH, self.frame.size.height + self.toolBar.frame.size.height)]; 107 | self.bgView.backgroundColor = [UIColor whiteColor]; 108 | } 109 | 110 | #pragma mark - public method 111 | 112 | /** 113 | * 显示日期选择器 114 | * @param selectedDate 默认选中的日期 115 | */ 116 | - (void)showWithSelectedDate:(NSDate * _Nullable)selectedDate 117 | commit:(CommitBlock _Nullable)commitBlock 118 | cancel:(CancelBlock _Nullable)cancelBlock { 119 | MOFSPickerDelegateObject *delegate = [MOFSPickerDelegateObject initWithCancelBlock:cancelBlock commitDateBlock:commitBlock]; 120 | [self showWithDelegate:delegate date:selectedDate]; 121 | } 122 | 123 | 124 | /** 125 | * 显示日期选择器 126 | * @param title 选择器toolBar中间标题 127 | * @param commitTitle 确定标题 128 | * @param cancelTitle 取消标题 129 | * @param selectedDate 默认选中的日期 130 | * @param minDate 选择器最小日期 131 | * @param maxDate 选择器最大日期 132 | * @param mode 选择器模式 133 | */ 134 | - (void)showWithTitle:(NSString * _Nullable)title 135 | commitTitle:(NSString * _Nullable)commitTitle 136 | cancelTitle:(NSString * _Nullable)cancelTitle 137 | selectedDate:(NSDate * _Nullable)selectedDate 138 | minDate:(NSDate * _Nullable)minDate 139 | maxDate:(NSDate * _Nullable)maxDate 140 | datePickerMode:(UIDatePickerMode)mode 141 | commitBlock:(CommitBlock _Nullable )commitBlock 142 | cancelBlock:(CancelBlock _Nullable )cancelBlock { 143 | 144 | self.toolBar.titleBarTitle = title; 145 | self.toolBar.commitBarTitle = commitTitle; 146 | self.toolBar.cancelBarTitle = cancelTitle; 147 | 148 | self.minimumDate = minDate; 149 | self.maximumDate = maxDate; 150 | 151 | self.datePickerMode = mode; 152 | 153 | MOFSPickerDelegateObject *delegate = [MOFSPickerDelegateObject initWithCancelBlock:cancelBlock commitDateBlock:commitBlock]; 154 | [self showWithDelegate:delegate date:selectedDate]; 155 | } 156 | 157 | #pragma mark - private method 158 | 159 | - (void)showWithDelegate:(MOFSPickerDelegateObject *)delegate date:(NSDate *)date { 160 | if (!delegate) { 161 | return; 162 | } 163 | if (date) { 164 | self.date = date; 165 | } 166 | 167 | [self showWithAnimation]; 168 | 169 | [self addDelegate:delegate]; 170 | } 171 | 172 | #pragma mark - delegate 173 | 174 | - (void)addDelegate:(MOFSPickerDelegateObject *)delegate { 175 | [self.lock lock]; 176 | self.delegatesDict[self.objectPointer] = delegate; 177 | [self.lock unlock]; 178 | } 179 | 180 | - (void)removeDelegate:(MOFSPickerDelegateObject *)delegate { 181 | [self.lock lock]; 182 | [self.delegatesDict removeObjectForKey:self.objectPointer]; 183 | [self.lock unlock]; 184 | } 185 | 186 | #pragma mark - ToolBar Action 187 | 188 | - (void)cancelAction { 189 | [self hiddenWithAnimation]; 190 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 191 | if (delegate.cancelBlock) { 192 | delegate.cancelBlock(); 193 | } 194 | [self removeDelegate:delegate]; 195 | } 196 | 197 | - (void)commitAction { 198 | [self hiddenWithAnimation]; 199 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 200 | if (delegate.commitDateBlock) { 201 | delegate.commitDateBlock(self.date); 202 | } 203 | 204 | [self removeDelegate:delegate]; 205 | } 206 | 207 | #pragma mark - Action 208 | 209 | - (void)showWithAnimation { 210 | [self addViews]; 211 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; 212 | CGFloat height = self.bgView.frame.size.height; 213 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2); 214 | [UIView animateWithDuration:0.25 animations:^{ 215 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT - height / 2); 216 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 217 | }]; 218 | 219 | } 220 | 221 | - (void)hiddenWithAnimation { 222 | CGFloat height = self.bgView.frame.size.height; 223 | [UIView animateWithDuration:0.25 animations:^{ 224 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2); 225 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; 226 | } completion:^(BOOL finished) { 227 | [self hiddenViews]; 228 | }]; 229 | } 230 | 231 | - (void)containerViewClickedAction { 232 | if (self.containerViewClickedBlock) { 233 | self.containerViewClickedBlock(); 234 | } 235 | [self hiddenWithAnimation]; 236 | } 237 | 238 | - (void)addViews { 239 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 240 | [window addSubview:self.containerView]; 241 | [window addSubview:self.bgView]; 242 | [self.bgView addSubview:self.toolBar]; 243 | [self.bgView addSubview:self]; 244 | } 245 | 246 | - (void)hiddenViews { 247 | [self removeFromSuperview]; 248 | [self.toolBar removeFromSuperview]; 249 | [self.bgView removeFromSuperview]; 250 | [self.containerView removeFromSuperview]; 251 | } 252 | 253 | #pragma mark - Dealloc 254 | 255 | - (void)dealloc { 256 | 257 | } 258 | 259 | @end 260 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSPickerManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSPickerManager.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/26. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MOFSDatePicker.h" 11 | #import "MOFSPickerView.h" 12 | #import "MOFSAddressPickerView.h" 13 | #import "LQYPickerView.h" 14 | 15 | @interface MOFSPickerManager : NSObject 16 | 17 | + (MOFSPickerManager *_Nonnull)shareManger; 18 | 19 | @property (nonnull, nonatomic, strong) MOFSDatePicker *datePicker; 20 | 21 | @property (nonnull, nonatomic, strong) MOFSPickerView *pickView; 22 | 23 | @property (nonnull, nonatomic, strong) MOFSAddressPickerView *addressPicker; 24 | 25 | @property (nonnull, nonatomic, strong) LQYDatePickerView *lqyDatePicker; 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSPickerManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSPickerManager.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/26. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "MOFSPickerManager.h" 10 | 11 | @implementation MOFSPickerManager 12 | 13 | + (MOFSPickerManager *)shareManger { 14 | static MOFSPickerManager *manager = nil; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | manager = [self new]; 18 | }); 19 | return manager; 20 | } 21 | 22 | - (MOFSDatePicker *)datePicker { 23 | if (!_datePicker) { 24 | _datePicker = [MOFSDatePicker new]; 25 | } 26 | return _datePicker; 27 | } 28 | 29 | - (MOFSPickerView *)pickView { 30 | if (!_pickView) { 31 | _pickView = [MOFSPickerView new]; 32 | } 33 | return _pickView; 34 | } 35 | 36 | - (MOFSAddressPickerView *)addressPicker { 37 | if (!_addressPicker) { 38 | _addressPicker = [MOFSAddressPickerView new]; 39 | } 40 | return _addressPicker; 41 | } 42 | 43 | - (LQYDatePickerView *)lqyDatePicker { 44 | if (!_lqyDatePicker) { 45 | _lqyDatePicker = [LQYDatePickerView new]; 46 | } 47 | return _lqyDatePicker; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSPickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSPickerView.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/30. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MOFSToolView.h" 11 | 12 | @interface MOFSPickerView : UIPickerView 13 | 14 | @property (nullable, nonatomic, strong) MOFSToolView *toolBar; 15 | @property (nullable, nonatomic, strong) UIView *containerView; 16 | @property (nullable, nonatomic, strong) void (^containerViewClickedBlock)(void); 17 | 18 | @property (nullable, nonatomic, strong) NSDictionary *attributes; 19 | 20 | /** 21 | * 显示选择器 22 | * @param array 字符数组 23 | * @param title 标题 24 | */ 25 | - (void)showWithDataArray:(NSArray * _Nonnull)array 26 | title:(NSString * _Nullable)title 27 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 28 | cancelBlock:(void(^ _Nullable)(void))cancelBlock; 29 | 30 | /** 31 | * 显示选择器 32 | * @param array 数据源数组 33 | * @param title 标题 34 | * @param commitTitle 确定标题 35 | * @param cancelTitle 取消标题 36 | */ 37 | - (void)showWithDataArray:(NSArray * _Nonnull)array 38 | title:(NSString * _Nullable)title 39 | commitTitle:(NSString * _Nullable)commitTitle 40 | cancelTitle:(NSString * _Nullable)cancelTitle 41 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 42 | cancelBlock:(void(^ _Nullable)(void))cancelBlock; 43 | 44 | /** 45 | * 显示选择器 46 | * @param array 数据源数组 47 | * @param keyMapper 数据源中的Model或者JSON对应的key 48 | * @param title 标题 49 | */ 50 | - (void)showWithDataArray:(NSArray * _Nonnull)array 51 | keyMapper:(NSString * _Nullable)keyMapper 52 | title:(NSString * _Nullable)title 53 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 54 | cancelBlock:(void(^ _Nullable)(void))cancelBlock; 55 | 56 | /** 57 | * 显示选择器 58 | * @param array 数据源数组 59 | * @param keyMapper 数据源中的Model或者JSON对应的key 60 | * @param title 标题 61 | * @param commitTitle 确定标题 62 | * @param cancelTitle 取消标题 63 | */ 64 | - (void)showWithDataArray:(NSArray * _Nonnull)array 65 | keyMapper:(NSString * _Nullable)keyMapper 66 | title:(NSString * _Nullable)title 67 | commitTitle:(NSString * _Nullable)commitTitle 68 | cancelTitle:(NSString * _Nullable)cancelTitle 69 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 70 | cancelBlock:(void(^ _Nullable)(void))cancelBlock; 71 | 72 | 73 | @end 74 | 75 | 76 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSPickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSPickerView.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/8/30. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "MOFSPickerView.h" 10 | #import 11 | 12 | #define UISCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 13 | #define UISCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 14 | 15 | @interface MOFSPickerView() 16 | 17 | @property (nonatomic, strong) NSArray *dataArr; 18 | @property (nonatomic, strong) UIView *bgView; 19 | 20 | @property (nonatomic, assign) NSInteger selectedRow; 21 | 22 | @property (nonatomic, copy) NSString *keyMapper; //自定义解析Key 23 | 24 | @property (nonatomic, strong) NSMutableDictionary *delegatesDict; 25 | @property (readwrite, nonatomic, strong) NSLock *lock; 26 | 27 | @property (nonatomic, strong) NSString *objectPointer; 28 | 29 | @end 30 | 31 | @implementation MOFSPickerView 32 | 33 | #pragma mark - setter 34 | 35 | - (void)setAttributes:(NSDictionary *)attributes { 36 | _attributes = attributes; 37 | dispatch_async(dispatch_get_main_queue(), ^{ 38 | [self reloadAllComponents]; 39 | }); 40 | } 41 | 42 | #pragma mark - gettter 43 | 44 | - (NSLock *)lock { 45 | if (!_lock) { 46 | _lock = [[NSLock alloc] init]; 47 | _lock.name = @"com.ly.picker.lock"; 48 | } 49 | return _lock; 50 | } 51 | 52 | - (NSMutableDictionary *)delegatesDict { 53 | if (!_delegatesDict) { 54 | _delegatesDict = [NSMutableDictionary dictionary]; 55 | } 56 | return _delegatesDict; 57 | } 58 | 59 | - (NSString *)objectPointer { 60 | return [NSString stringWithFormat:@"%p", self]; 61 | } 62 | 63 | #pragma mark - create UI 64 | 65 | - (instancetype)initWithFrame:(CGRect)frame { 66 | 67 | [self initToolBar]; 68 | [self initContainerView]; 69 | 70 | CGRect initialFrame; 71 | if (CGRectIsEmpty(frame)) { 72 | initialFrame = CGRectMake(0, self.toolBar.frame.size.height, UISCREEN_WIDTH, 216); 73 | } else { 74 | initialFrame = frame; 75 | } 76 | self = [super initWithFrame:initialFrame]; 77 | if (self) { 78 | self.backgroundColor = [UIColor whiteColor]; 79 | 80 | self.delegate = self; 81 | self.dataSource = self; 82 | 83 | [self initBgView]; 84 | } 85 | return self; 86 | } 87 | 88 | - (void)initToolBar { 89 | self.toolBar = [[MOFSToolView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, 44)]; 90 | self.toolBar.backgroundColor = [UIColor whiteColor]; 91 | [self.toolBar.cancelBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelAction)]]; 92 | [self.toolBar.commitBar addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(commitAction)]]; 93 | } 94 | 95 | - (void)initContainerView { 96 | self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, UISCREEN_HEIGHT)]; 97 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 98 | self.containerView.userInteractionEnabled = YES; 99 | [self.containerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(containerViewClickedAction)]]; 100 | } 101 | 102 | - (void)initBgView { 103 | self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, UISCREEN_HEIGHT - self.frame.size.height - 44, UISCREEN_WIDTH, self.frame.size.height + self.toolBar.frame.size.height)]; 104 | } 105 | 106 | #pragma mark - Action 107 | 108 | /** 109 | * 显示选择器 110 | * @param array 字符数组 111 | * @param title 标题 112 | */ 113 | - (void)showWithDataArray:(NSArray * _Nonnull)array 114 | title:(NSString * _Nullable)title 115 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 116 | cancelBlock:(void(^ _Nullable)(void))cancelBlock { 117 | [self showWithDataArray:array title:title commitTitle:@"确定" cancelTitle:@"取消" commitBlock:commitBlock cancelBlock:cancelBlock]; 118 | } 119 | 120 | /** 121 | * 显示选择器 122 | * @param array 数据源数组 123 | * @param title 标题 124 | * @param commitTitle 确定标题 125 | * @param cancelTitle 取消标题 126 | */ 127 | - (void)showWithDataArray:(NSArray * _Nonnull)array 128 | title:(NSString * _Nullable)title 129 | commitTitle:(NSString * _Nullable)commitTitle 130 | cancelTitle:(NSString * _Nullable)cancelTitle 131 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 132 | cancelBlock:(void(^ _Nullable)(void))cancelBlock { 133 | [self showWithDataArray:array keyMapper:nil title:title commitTitle:commitTitle cancelTitle:cancelTitle commitBlock:commitBlock cancelBlock:cancelBlock]; 134 | } 135 | 136 | /** 137 | * 显示选择器 138 | * @param array 数据源数组 139 | * @param keyMapper 数据源中的Model或者JSON对应的key 140 | * @param title 标题 141 | */ 142 | - (void)showWithDataArray:(NSArray * _Nonnull)array 143 | keyMapper:(NSString * _Nullable)keyMapper 144 | title:(NSString * _Nullable)title 145 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 146 | cancelBlock:(void(^ _Nullable)(void))cancelBlock { 147 | [self showWithDataArray:array keyMapper:keyMapper title:title commitTitle:@"确定" cancelTitle:@"取消" commitBlock:commitBlock cancelBlock:cancelBlock]; 148 | } 149 | 150 | /** 151 | * 显示选择器 152 | * @param array 数据源数组 153 | * @param keyMapper 数据源中的Model或者JSON对应的key 154 | * @param title 标题 155 | * @param commitTitle 确定标题 156 | * @param cancelTitle 取消标题 157 | */ 158 | - (void)showWithDataArray:(NSArray * _Nonnull)array 159 | keyMapper:(NSString * _Nullable)keyMapper 160 | title:(NSString * _Nullable)title 161 | commitTitle:(NSString * _Nullable)commitTitle 162 | cancelTitle:(NSString * _Nullable)cancelTitle 163 | commitBlock:(void(^ _Nullable)(id _Nullable model))commitBlock 164 | cancelBlock:(void(^ _Nullable)(void))cancelBlock { 165 | if (array.count <= 0) { 166 | return; 167 | } 168 | self.dataArr = array.copy; 169 | self.keyMapper = keyMapper; 170 | 171 | self.toolBar.titleBarTitle = title; 172 | self.toolBar.commitBarTitle = commitTitle; 173 | self.toolBar.cancelBarTitle = cancelTitle; 174 | 175 | [self reloadAllComponents]; 176 | // self.selectedRow = 0; 177 | // if (tag != NSNotFound) { 178 | // self.selectedRow = [self.recordDict[@(tag)] integerValue]; 179 | // } 180 | // if (tag > 0) { 181 | // @try { 182 | // [self selectRow:self.selectedRow inComponent:0 animated:NO]; 183 | // } @catch (NSException *exception) { 184 | // 185 | // } @finally { 186 | // 187 | // } 188 | // } 189 | 190 | [self showWithAnimation]; 191 | 192 | MOFSPickerDelegateObject *delegate = [MOFSPickerDelegateObject initWithCancelBlock:cancelBlock commitPickerBlock:commitBlock]; 193 | [self addDelegate:delegate]; 194 | } 195 | 196 | - (void)showWithAnimation { 197 | [self addViews]; 198 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; 199 | CGFloat height = self.bgView.frame.size.height; 200 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2); 201 | [UIView animateWithDuration:0.25 animations:^{ 202 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT - height / 2); 203 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 204 | }]; 205 | 206 | } 207 | 208 | - (void)hiddenWithAnimation { 209 | CGFloat height = self.bgView.frame.size.height; 210 | [UIView animateWithDuration:0.25 animations:^{ 211 | self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2); 212 | self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0]; 213 | } completion:^(BOOL finished) { 214 | [self hiddenViews]; 215 | }]; 216 | } 217 | 218 | - (void)containerViewClickedAction { 219 | if (self.containerViewClickedBlock) { 220 | self.containerViewClickedBlock(); 221 | } 222 | [self hiddenWithAnimation]; 223 | } 224 | 225 | - (void)addViews { 226 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 227 | [window addSubview:self.containerView]; 228 | [window addSubview:self.bgView]; 229 | [self.bgView addSubview:self.toolBar]; 230 | [self.bgView addSubview:self]; 231 | } 232 | 233 | - (void)hiddenViews { 234 | [self removeFromSuperview]; 235 | [self.toolBar removeFromSuperview]; 236 | [self.bgView removeFromSuperview]; 237 | [self.containerView removeFromSuperview]; 238 | } 239 | 240 | #pragma mark - ToolBar Action 241 | 242 | - (void)cancelAction { 243 | [self hiddenWithAnimation]; 244 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 245 | if (delegate.cancelBlock) { 246 | delegate.cancelBlock(); 247 | } 248 | [self removeDelegate:delegate]; 249 | } 250 | 251 | - (void)commitAction { 252 | [self hiddenWithAnimation]; 253 | MOFSPickerDelegateObject *delegate = self.delegatesDict[self.objectPointer]; 254 | if (delegate.commitPickerBlock && self.selectedRow < self.dataArr.count) { 255 | delegate.commitPickerBlock(self.dataArr[self.selectedRow]); 256 | } 257 | 258 | [self removeDelegate:delegate]; 259 | } 260 | 261 | #pragma mark - delegate 262 | 263 | - (void)addDelegate:(MOFSPickerDelegateObject *)delegate { 264 | [self.lock lock]; 265 | self.delegatesDict[self.objectPointer] = delegate; 266 | [self.lock unlock]; 267 | } 268 | 269 | - (void)removeDelegate:(MOFSPickerDelegateObject *)delegate { 270 | [self.lock lock]; 271 | [self.delegatesDict removeObjectForKey:self.objectPointer]; 272 | [self.lock unlock]; 273 | } 274 | 275 | #pragma mark - UIPickerViewDelegate,UIPickerViewDataSource 276 | 277 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 278 | return 1; 279 | } 280 | 281 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 282 | return self.dataArr.count; 283 | } 284 | 285 | - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { 286 | return 44; 287 | } 288 | 289 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 290 | if (self.keyMapper) { 291 | id value = [self.dataArr[row] valueForKey:self.keyMapper]; 292 | if ([value isKindOfClass:[NSString class]]) { 293 | return value; 294 | } else { 295 | return @"解析出错"; 296 | } 297 | } 298 | return self.dataArr[row]; 299 | } 300 | 301 | - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 302 | UILabel* pickerLabel = (UILabel*)view; 303 | if (!pickerLabel){ 304 | pickerLabel = [[UILabel alloc] init];; 305 | pickerLabel.textAlignment = NSTextAlignmentCenter; 306 | pickerLabel.font = [UIFont systemFontOfSize:16]; 307 | pickerLabel.textColor = [UIColor colorWithRed:12.f/255.f green:14.f/255.f blue:14.f/255.f alpha:1]; 308 | } 309 | 310 | NSString *text = [self pickerView:pickerView titleForRow:row forComponent:component]; 311 | 312 | pickerLabel.attributedText = [[NSAttributedString alloc] initWithString:text attributes:_attributes]; 313 | 314 | return pickerLabel; 315 | } 316 | 317 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 318 | self.selectedRow = row; 319 | } 320 | 321 | #pragma mark - Dealloc 322 | 323 | - (void)dealloc { 324 | 325 | } 326 | 327 | @end 328 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSToolView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSToolView.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 2018/2/5. 6 | // Copyright © 2018年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MOFSAddressModel.h" 11 | 12 | @interface MOFSToolView : UIView 13 | 14 | @property (nonatomic, strong) UILabel *cancelBar; 15 | @property (nonatomic, strong) UILabel *commitBar; 16 | @property (nonatomic, strong) UILabel *titleBar; 17 | 18 | /** 19 | default Title: "取消" 20 | */ 21 | @property (nonatomic, strong) NSString *cancelBarTitle; 22 | 23 | /** 24 | default Color: [UIColor colorWithRed:0.090 green:0.463 blue:0.906 alpha:1] 25 | */ 26 | @property (nonatomic, strong) UIColor *cancelBarTintColor; 27 | 28 | /** 29 | default Title: "确定" 30 | */ 31 | @property (nonatomic, strong) NSString *commitBarTitle; 32 | 33 | /** 34 | default Color: [UIColor colorWithRed:0.090 green:0.463 blue:0.906 alpha:1] 35 | */ 36 | @property (nonatomic, strong) UIColor *commitBarTintColor; 37 | 38 | /** 39 | default Title: "" 40 | */ 41 | @property (nonatomic, strong) NSString *titleBarTitle; 42 | 43 | /** 44 | default Color: [UIColor colorWithRed:0.804 green:0.804 blue:0.804 alpha:1] 45 | */ 46 | @property (nonatomic, strong) UIColor *titleBarTextColor; 47 | 48 | @end 49 | 50 | 51 | @interface MOFSPickerDelegateObject : NSObject 52 | 53 | @property (nonatomic, copy) void (^cancelBlock)(void); 54 | 55 | @property (nonatomic, copy) void (^commitDateBlock)(NSDate *date); 56 | @property (nonatomic, copy) void (^commitAddressBlock)(MOFSAddressSelectedModel *selectedModel); 57 | @property (nonatomic, copy) void (^commitPickerBlock)(id obj); 58 | @property (nonatomic, copy) void (^commitLYQDateBlock)(NSDateComponents *dateComponents); 59 | 60 | /** 61 | * 日期 62 | */ 63 | + (instancetype)initWithCancelBlock:(void(^)(void))cancelBlock commitDateBlock:(void (^)(NSDate * date))commitBlock; 64 | 65 | /** 66 | * 地址 67 | */ 68 | + (instancetype)initWithCancelBlock:(void(^)(void))cancelBlock commitAddressBlock:(void (^)(MOFSAddressSelectedModel *selectedModel))commitBlock; 69 | 70 | /** 71 | * 普通选择器 72 | */ 73 | + (instancetype)initWithCancelBlock:(void(^)(void))cancelBlock commitPickerBlock:(void (^)(id obj))commitBlock; 74 | 75 | + (instancetype)initWithCancelBlock:(void(^)(void))cancelBlock commitLQYDateBlock:(void (^)(NSDateComponents *dateComponents))commitBlock; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/MOFSPickerManager/MOFSToolView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSToolView.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 2018/2/5. 6 | // Copyright © 2018年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "MOFSToolView.h" 10 | 11 | #define TEXT_COLOR [UIColor colorWithRed:0.090 green:0.463 blue:0.906 alpha:1] 12 | #define LINE_COLOR [UIColor colorWithRed:0.804 green:0.804 blue:0.804 alpha:1] 13 | #define UISCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 14 | #define UISCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 15 | 16 | @implementation MOFSToolView 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame { 19 | self = [super initWithFrame:frame]; 20 | if (self) { 21 | 22 | //self.translatesAutoresizingMaskIntoConstraints = false; 23 | 24 | _cancelBar = [UILabel new]; 25 | _cancelBar.font = [UIFont systemFontOfSize:14]; 26 | _cancelBar.textColor = TEXT_COLOR; 27 | _cancelBar.text = @"取消"; 28 | _cancelBar.textAlignment = NSTextAlignmentLeft; 29 | _cancelBar.userInteractionEnabled = true; 30 | [self addSubview:_cancelBar]; 31 | [_cancelBar setTranslatesAutoresizingMaskIntoConstraints:false]; 32 | [_cancelBar setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; 33 | [_cancelBar setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; 34 | 35 | _titleBar = [UILabel new]; 36 | _titleBar.font = [UIFont systemFontOfSize:14]; 37 | _titleBar.textAlignment = NSTextAlignmentCenter; 38 | _titleBar.textColor = LINE_COLOR; 39 | [self addSubview:_titleBar]; 40 | [_titleBar setTranslatesAutoresizingMaskIntoConstraints:false]; 41 | [_titleBar setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; 42 | 43 | _commitBar = [UILabel new]; 44 | _commitBar.font = [UIFont systemFontOfSize:14]; 45 | _commitBar.textColor = TEXT_COLOR; 46 | _commitBar.text = @"确定"; 47 | _commitBar.textAlignment = NSTextAlignmentRight; 48 | _commitBar.userInteractionEnabled = true; 49 | [self addSubview:_commitBar]; 50 | [_commitBar setTranslatesAutoresizingMaskIntoConstraints:false]; 51 | [_commitBar setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; 52 | [_commitBar setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; 53 | 54 | UIView *topLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, 0.5)]; 55 | topLineView.backgroundColor = LINE_COLOR; 56 | [self addSubview:topLineView]; 57 | [topLineView setTranslatesAutoresizingMaskIntoConstraints:false]; 58 | 59 | UIView *bottomLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 43.5, UISCREEN_WIDTH, 0.5)]; 60 | bottomLineView.backgroundColor = LINE_COLOR; 61 | [self addSubview:bottomLineView]; 62 | [bottomLineView setTranslatesAutoresizingMaskIntoConstraints:false]; 63 | 64 | NSLayoutConstraint *constrant_a = [NSLayoutConstraint constraintWithItem:_cancelBar attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10]; 65 | NSLayoutConstraint *constrant_b = [NSLayoutConstraint constraintWithItem:_cancelBar attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 66 | NSLayoutConstraint *constrant_c = [NSLayoutConstraint constraintWithItem:_cancelBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; 67 | [self addConstraints:@[constrant_a, constrant_b, constrant_c]]; 68 | 69 | NSLayoutConstraint *constrant_d = [NSLayoutConstraint constraintWithItem:_titleBar attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_cancelBar attribute:NSLayoutAttributeRight multiplier:1.0 constant:10]; 70 | NSLayoutConstraint *constrant_e = [NSLayoutConstraint constraintWithItem:_titleBar attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 71 | NSLayoutConstraint *constrant_f = [NSLayoutConstraint constraintWithItem:_titleBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; 72 | [self addConstraints:@[constrant_d, constrant_e, constrant_f]]; 73 | 74 | NSLayoutConstraint *constrant_g = [NSLayoutConstraint constraintWithItem:_commitBar attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_titleBar attribute:NSLayoutAttributeRight multiplier:1.0 constant:10]; 75 | NSLayoutConstraint *constrant_h = [NSLayoutConstraint constraintWithItem:_commitBar attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 76 | NSLayoutConstraint *constrant_i = [NSLayoutConstraint constraintWithItem:_commitBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; 77 | NSLayoutConstraint *constrant_j = [NSLayoutConstraint constraintWithItem:_commitBar attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:-10]; 78 | [self addConstraints:@[constrant_g, constrant_h, constrant_i, constrant_j]]; 79 | 80 | NSLayoutConstraint *constrant_k = [NSLayoutConstraint constraintWithItem:topLineView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]; 81 | NSLayoutConstraint *constrant_l = [NSLayoutConstraint constraintWithItem:topLineView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; 82 | NSLayoutConstraint *constrant_m = [NSLayoutConstraint constraintWithItem:topLineView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]; 83 | NSLayoutConstraint *constrant_n = [NSLayoutConstraint constraintWithItem:topLineView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0.5]; 84 | [self addConstraints:@[constrant_k, constrant_l, constrant_m, constrant_n]]; 85 | 86 | NSLayoutConstraint *constrant_o = [NSLayoutConstraint constraintWithItem:bottomLineView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]; 87 | NSLayoutConstraint *constrant_p = [NSLayoutConstraint constraintWithItem:bottomLineView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; 88 | NSLayoutConstraint *constrant_q = [NSLayoutConstraint constraintWithItem:bottomLineView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]; 89 | NSLayoutConstraint *constrant_r = [NSLayoutConstraint constraintWithItem:bottomLineView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0.5]; 90 | [self addConstraints:@[constrant_o, constrant_p, constrant_q, constrant_r]]; 91 | 92 | 93 | } 94 | return self; 95 | } 96 | 97 | #pragma mark - install 98 | 99 | - (void)setCancelBarTitle:(NSString *)cancelBarTitle { 100 | _cancelBarTitle = cancelBarTitle; 101 | if (self.cancelBar) { 102 | self.cancelBar.text = cancelBarTitle; 103 | } 104 | } 105 | 106 | - (void)setCancelBarTintColor:(UIColor *)cancelBarTintColor { 107 | _cancelBarTintColor = cancelBarTintColor; 108 | if (self.cancelBar) { 109 | self.cancelBar.tintColor = cancelBarTintColor; 110 | } 111 | } 112 | 113 | - (void)setCommitBarTitle:(NSString *)commitBarTitle { 114 | _commitBarTitle = commitBarTitle; 115 | if (self.commitBar) { 116 | self.commitBar.text = commitBarTitle; 117 | } 118 | } 119 | 120 | - (void)setCommitBarTintColor:(UIColor *)commitBarTintColor { 121 | _commitBarTintColor = commitBarTintColor; 122 | if (self.commitBar) { 123 | self.commitBar.tintColor = commitBarTintColor; 124 | } 125 | } 126 | 127 | - (void)setTitleBarTitle:(NSString *)titleBarTitle { 128 | _titleBarTitle = titleBarTitle; 129 | if (self.titleBar) { 130 | self.titleBar.text = titleBarTitle; 131 | } 132 | } 133 | 134 | - (void)setTitleBarTextColor:(UIColor *)titleBarTextColor { 135 | _titleBarTextColor = titleBarTextColor; 136 | if (self.titleBar) { 137 | self.titleBar.textColor = titleBarTextColor;; 138 | } 139 | } 140 | 141 | @end 142 | 143 | 144 | @implementation MOFSPickerDelegateObject 145 | 146 | + (instancetype)initWithCancelBlock:(void (^)(void))cancelBlock commitDateBlock:(void (^)(NSDate *))commitBlock { 147 | MOFSPickerDelegateObject *obj = [MOFSPickerDelegateObject new]; 148 | obj.cancelBlock = cancelBlock; 149 | obj.commitDateBlock = commitBlock; 150 | return obj; 151 | } 152 | 153 | + (instancetype)initWithCancelBlock:(void (^)(void))cancelBlock commitAddressBlock:(void (^)(MOFSAddressSelectedModel *))commitBlock { 154 | MOFSPickerDelegateObject *obj = [MOFSPickerDelegateObject new]; 155 | obj.cancelBlock = cancelBlock; 156 | obj.commitAddressBlock = commitBlock; 157 | return obj; 158 | } 159 | 160 | /** 161 | * 普通选择器 162 | */ 163 | + (instancetype)initWithCancelBlock:(void(^)(void))cancelBlock commitPickerBlock:(void (^)(id obj))commitBlock { 164 | MOFSPickerDelegateObject *obj = [MOFSPickerDelegateObject new]; 165 | obj.cancelBlock = cancelBlock; 166 | obj.commitPickerBlock = commitBlock; 167 | return obj; 168 | } 169 | 170 | + (instancetype)initWithCancelBlock:(void(^)(void))cancelBlock commitLQYDateBlock:(void (^)(NSDateComponents *dateComponents))commitBlock { 171 | MOFSPickerDelegateObject *obj = [MOFSPickerDelegateObject new]; 172 | obj.cancelBlock = cancelBlock; 173 | obj.commitLYQDateBlock = commitBlock; 174 | return obj; 175 | } 176 | 177 | @end 178 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class Model; 12 | 13 | @interface ViewController : UIViewController 14 | 15 | //pod trunk push --use-libraries 16 | 17 | @end 18 | 19 | @interface Model : NSObject 20 | 21 | @property (nonatomic, assign) NSInteger age; 22 | @property (nonatomic, assign) NSInteger userId; 23 | @property (nonatomic, copy) NSString *name; 24 | @property (nonatomic, copy) NSString *nickname; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MOFSPickerManager.h" 11 | #import "LQYPickerView.h" 12 | 13 | @interface ViewController () 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | 23 | 24 | // Do any additional setup after loading the view, typically from a nib. 25 | } 26 | 27 | - (void)didReceiveMemoryWarning { 28 | [super didReceiveMemoryWarning]; 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | - (IBAction)lbClick:(UITapGestureRecognizer *)sender { 33 | UILabel *lb = (UILabel *)(sender.view); 34 | NSDateFormatter *df = [NSDateFormatter new]; 35 | df.dateFormat = @"yyyy-MM-dd"; 36 | [self.view endEditing:true]; 37 | if (lb.tag == 1) { 38 | 39 | //单例方法 40 | // [MOFSPickerManager shareManger].datePicker.toolBar.cancelBar.textColor = [UIColor redColor]; 41 | // NSDateFormatter *df = [NSDateFormatter new]; 42 | // df.dateFormat = @"yyyy-M-d"; 43 | // NSDate *selectedDate = [df dateFromString:@"2015-6-1"]; 44 | // [MOFSPickerManager shareManger].datePicker.toolBar.titleBarTitle = @"选择日期"; 45 | // [MOFSPickerManager shareManger].datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh"]; 46 | // [[MOFSPickerManager shareManger].datePicker showWithTitle:@"选择日期" commitTitle:@"确定" cancelTitle:@"取消" selectedDate:selectedDate minDate:nil maxDate:nil datePickerMode:UIDatePickerModeDate commitBlock:^(NSDate * _Nullable date) { 47 | // NSLog(@"%@", [df stringFromDate:date]); 48 | // } cancelBlock:^{ 49 | // 50 | // }]; 51 | // [[MOFSPickerManager shareManger].datePicker showWithSelectedDate:selectedDate commit:^(NSDate * _Nullable date) { 52 | // NSLog(@"%@", [df stringFromDate:date]); 53 | // } cancel:^{ 54 | // 55 | // }]; 56 | 57 | //自行创建实例方法 58 | MOFSDatePicker *p = [MOFSDatePicker new]; 59 | [p showWithSelectedDate:nil commit:^(NSDate * _Nullable date) { 60 | NSLog(@"%@", [df stringFromDate:date]); 61 | } cancel:^{ 62 | 63 | }]; 64 | 65 | } else if (lb.tag == 2) { 66 | // NSString *str_a = @"疾风剑豪"; 67 | // str_a.mofs_key = @"自定义id"; 68 | // [[MOFSPickerManager shareManger].pickView showWithDataArray:@[@"疾风剑豪",@"刀锋意志",@"诡术妖姬",@"狂战士"] title:nil commitBlock:^(id _Nullable model) { 69 | // 70 | // } cancelBlock:^{ 71 | // 72 | // }]; 73 | 74 | Model *a = [Model new]; 75 | a.age = 17; 76 | a.name = @"疾风剑豪"; 77 | a.nickname = @"托儿所"; 78 | a.userId = 0001; 79 | 80 | Model *b = [Model new]; 81 | b.age = 18; 82 | b.name = @"刀锋意志"; 83 | b.nickname = @"刀妹"; 84 | b.userId = 0002; 85 | 86 | Model *c = [Model new]; 87 | c.age = 22; 88 | c.name = @"诡术妖姬"; 89 | c.nickname = @"乐芙兰"; 90 | c.userId = 0003; 91 | 92 | //单例方法 93 | // [[MOFSPickerManager shareManger].pickView showWithDataArray:@[a, b, c] keyMapper:@"name" title:@"选择英雄" commitBlock:^(id _Nullable model) { 94 | // Model *m = (Model *)model; 95 | // lb.text = m.name; 96 | // NSLog(@"%@-%zd", m.name, m.userId); 97 | // } cancelBlock:^{ 98 | // 99 | // }]; 100 | 101 | //自行创建实例方法 102 | MOFSPickerView *p = [MOFSPickerView new]; 103 | p.attributes = @{NSFontAttributeName : [UIFont systemFontOfSize:17], NSForegroundColorAttributeName : [UIColor redColor]}; 104 | p.toolBar.titleBarTitle = @""; 105 | [p showWithDataArray:@[a, b, c] keyMapper:@"name" title:@"选择" commitBlock:^(id _Nullable model) { 106 | Model *m = (Model *)model; 107 | lb.text = m.name; 108 | NSLog(@"%@-%zd", m.name, m.userId); 109 | } cancelBlock:^{ 110 | 111 | }]; 112 | 113 | // LQYPickerView *p = [LQYPickerView new]; 114 | // p.dataArray = @[@[a, b, c], @[a, b, c]]; 115 | // p.dataArray = @[@{@"name" : @"流浪法师", @"age" : @25},@{@"name" : @"流浪法师1", @"age" : @25}, @{@"name" : @"流浪法师2", @"age" : @25}]; 116 | // p.dataArray = @[@"流浪法师", @"疾风剑豪", @"无双剑姬"]; 117 | // p.dataTextKeys = @{@0 : @"name"}; 118 | 119 | // p.toolBar.titleBar.text = @"自定义选择"; 120 | // p.dataArray = @[@{@"name" : @"广西", @"list" : @[@{@"name" : @"南宁", @"list" : @[@"清秀", @"时区"]}, @{@"name" : @"桂林", @"list" : @[a]}]}]; 121 | //// p.dataTextKeys = @{@0 : @"name"}; 122 | //// p.dataArray = [MOFSPickerManager shareManger].addressPicker.addressDataArray; 123 | // p.numberOfSection = 3; 124 | // p.isDynamic = true; 125 | // p.dataKeys = @{@0 : @"list", @1 : @"list", @2 : @"list"}; 126 | // p.dataTextKeys = @{@0 : @"name"}; 127 | // 128 | // [p show]; 129 | // 130 | // p.commitBlock = ^(NSDictionary * _Nonnull json) { 131 | // NSLog(@"%@", json); 132 | // }; 133 | 134 | // LQYYearAndMonthPickerView *p = [LQYYearAndMonthPickerView new]; 135 | // NSDateFormatter *df = [NSDateFormatter new]; 136 | // df.dateFormat = @"yyyy-M"; 137 | // NSDate *date = [df dateFromString:@"2015-6"]; 138 | // p.minimumDate = date; 139 | // [p show]; 140 | // p.commitBlock = ^(NSDictionary * _Nonnull json) { 141 | // NSLog(@"%@", json); 142 | // }; 143 | 144 | // LQYDatePickerView *p = [LQYDatePickerView new]; 145 | // [p showWithCommitBlock:^(NSDateComponents * _Nonnull components) { 146 | // NSLog(@"%@", components); 147 | // } cancelBlock:^{ 148 | // NSLog(@"取消"); 149 | // }]; 150 | 151 | 152 | } else if (lb.tag == 3) { 153 | // [MOFSPickerManager shareManger].addressPicker.numberOfSection = 2; 154 | // 1. 155 | // [[MOFSPickerManager shareManger].addressPicker showWithTitle:@"选择地址" commitTitle:@"确定" cancelTitle:@"取消" commitBlock:^(MOFSAddressSelectedModel * _Nullable selectedModel) { 156 | // lb.text = [NSString stringWithFormat:@"%@-%@-%@", selectedModel.provinceName, selectedModel.cityName, selectedModel.districtName]; 157 | // } cancelBlock:^{ 158 | // 159 | // }]; 160 | 161 | // 2. 162 | // MOFSAddressSelectedModel *model = [MOFSAddressSelectedModel initWithProvinceName:@"广西壮族自治区" cityName:@"玉林市" districtName:@"容县"]; 163 | // [[MOFSPickerManager shareManger].addressPicker showWithSelectedAddress:model title:@"选择地址" commitTitle:@"确定" cancelTitle:@"取消" commitBlock:^(MOFSAddressSelectedModel * _Nullable selectedModel) { 164 | // lb.text = [NSString stringWithFormat:@"%@-%@-%@", selectedModel.provinceName, selectedModel.cityName, selectedModel.districtName]; 165 | // } cancelBlock:^{ 166 | // 167 | // }]; 168 | 169 | // [[MOFSPickerManager shareManger].addressPicker searchType:MOFSAddressSearchTypeByZipcode keyModel:[MOFSAddressSelectedModel initWithProvinceZipcode:@"450000" cityZipcode:@"450900" districtZipcode:@"450921"] block:^(MOFSSearchAddressModel * _Nullable result) { 170 | // 171 | // }]; 172 | 173 | // [MOFSPickerManager shareManger].addressPicker.attributes = @{NSFontAttributeName : [UIFont systemFontOfSize:15], NSForegroundColorAttributeName : [UIColor redColor]}; 174 | 175 | 176 | // [[MOFSPickerManager shareManger].addressPicker showWithSelectedZipcode:[MOFSAddressSelectedModel initWithProvinceZipcode:@"450000" cityZipcode:@"450900" districtZipcode:@"450921"] title:@"选择地址" commitTitle:@"确定" cancelTitle:@"取消" commitBlock:^(MOFSAddressSelectedModel * _Nullable selectedModel) { 177 | // lb.text = [NSString stringWithFormat:@"%@-%@-%@", selectedModel.provinceName, selectedModel.cityName, selectedModel.districtName]; 178 | // } cancelBlock:^{ 179 | // 180 | // }]; 181 | 182 | // [MOFSPickerManager shareManger].addressPicker.usedXML = true; 183 | // [[MOFSPickerManager shareManger] showMOFSAddressPickerWithTitle:@"选择地址" cancelTitle:@"取消" commitTitle:@"确定" commitBlock:^(NSString * _Nullable address, NSString * _Nullable zipcode) { 184 | // 185 | // } cancelBlock:^{ 186 | // 187 | // }]; 188 | 189 | MOFSAddressPickerView *picker = [MOFSAddressPickerView new]; 190 | [picker showWithTitle:@"请选择地址" commitTitle:@"确定" cancelTitle:@"取消" commitBlock:^(MOFSAddressSelectedModel * _Nullable selectedModel) { 191 | lb.text = [NSString stringWithFormat:@"%@-%@-%@", selectedModel.provinceName, selectedModel.cityName, selectedModel.districtName]; 192 | } cancelBlock:^{ 193 | 194 | }]; 195 | 196 | //修改中间分割线颜色 197 | // MOFSAddressPickerView *picker = [MOFSPickerManager shareManger].addressPicker; 198 | // [picker.subviews objectAtIndex:1].backgroundColor = [UIColor yellowColor]; 199 | // [picker.subviews objectAtIndex:2].backgroundColor = [UIColor yellowColor]; 200 | 201 | } 202 | 203 | } 204 | 205 | 206 | @end 207 | 208 | 209 | @implementation Model 210 | 211 | 212 | @end 213 | 214 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MOFSPickerManager 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemoTests/MOFSPickerManagerDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSPickerManagerTests.m 3 | // MOFSPickerManagerTests 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MOFSPickerManagerDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation MOFSPickerManagerDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MOFSPickerManagerDemoUITests/MOFSPickerManagerDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MOFSPickerManagerUITests.m 3 | // MOFSPickerManagerUITests 4 | // 5 | // Created by luoyuan on 16/9/5. 6 | // Copyright © 2016年 luoyuan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MOFSPickerManagerDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation MOFSPickerManagerDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS PickerView整合,一行代码调用(省市区三级联动+日期选择+普通选择) 2 | 3 | 支持CocoaPods安装, 4 | 5 | pod 'MOFSPickerManager'即可 6 | 7 | ## 预览图 8 | 9 | ![image](https://github.com/memoriesofsnows/MOFSPickerManagerDemo/blob/master/images/tap9.gif) 10 | 11 | ## 用法 12 | 1.日期选择器调用(有多种调用方式,看demo即可) 13 | 14 | ```objective-c 15 | [[MOFSPickerManager shareManger].datePicker showWithTitle:@"选择日期" commitTitle:@"确定" cancelTitle:@"取消" selectedDate:selectedDate minDate:nil maxDate:nil datePickerMode:UIDatePickerModeDate commitBlock:^(NSDate * _Nullable date) { 16 | NSLog(@"%@", [df stringFromDate:date]); 17 | } cancelBlock:^{ 18 | 19 | }]; 20 | ``` 21 | 22 | 参数说明 23 | 24 | * @param title : 中间标题,一般为nil 25 | 26 | * @param cancelTitle : 左边标题 “取消” 27 | 28 | * @param commitTitle : 右边标题 “确定” 29 | 30 | * @param selectedDate : 默认选中日期 31 | 32 | * @param minDate : 可选择的最小日期,不限制则为nil 33 | 34 | * @param maxDate : 可选择的最大日期,不限制则为nil 35 | 36 | * @param model : UIDatePickerMode 日期模式,有四种 UIDatePickerModeTime, UIDatePickerModeDate, UIDatePickerModeDateAndTime, UIDatePickerModeCountDownTimer 37 | 38 | 2.普通选择器调用 39 | 40 | ```objective-c 41 | [[MOFSPickerManager shareManger].pickView showWithDataArray:@[@"疾风剑豪",@"刀锋意志",@"诡术妖姬",@"狂战士"] title:nil commitBlock:^(id _Nullable model) { 42 | 43 | } cancelBlock:^{ 44 | 45 | }]; 46 | ``` 47 | 48 | 3.地址选择器调用 49 | 50 | ```objective-c 51 | [[MOFSPickerManager shareManger].addressPicker showWithTitle:@"选择地址" commitTitle:@"确定" cancelTitle:@"取消" commitBlock:^(MOFSAddressSelectedModel * _Nullable selectedModel) { 52 | lb.text = [NSString stringWithFormat:@"%@-%@-%@", selectedModel.provinceName, selectedModel.cityName, selectedModel.districtName]; 53 | } cancelBlock:^{ 54 | 55 | }]; 56 | ``` 57 | 58 | 地址选择器附带根据地址查询区域码或者根据区域码查询地址功能: 59 | 60 | 用法: 61 | 62 | ①根据区域码查询地址等信息 63 | 64 | ```objective-c 65 | [[MOFSPickerManager shareManger].addressPicker searchType:MOFSAddressSearchTypeByZipcode keyModel:[MOFSAddressSelectedModel initWithProvinceZipcode:@"450000" cityZipcode:@"450900" districtZipcode:@"450921"] block:^(MOFSSearchAddressModel * _Nullable result) { 66 | 67 | }]; 68 | ``` 69 | 70 | ②根据地址查询区域码等信息 71 | 72 | ```objective-c 73 | [[MOFSPickerManager shareManger].addressPicker searchType:MOFSAddressSearchTypeByAddress keyModel:[MOFSAddressSelectedModel initWithProvinceName:@"广西壮族自治区" cityName:@"玉林市" districtName:@"容县"] block:^(MOFSSearchAddressModel * _Nullable result) { 74 | 75 | }]; 76 | ``` 77 | 78 | 79 | [详情请查看](http://www.jianshu.com/p/578065eab5ab) 80 | 81 | 82 | 如果发现有bug,call me! 83 | 84 | luoyuant@163.com 85 | -------------------------------------------------------------------------------- /images/Simulator Screen Shot 2016年9月5日 下午9.17.07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/images/Simulator Screen Shot 2016年9月5日 下午9.17.07.png -------------------------------------------------------------------------------- /images/Simulator Screen Shot 2016年9月5日 下午9.17.31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/images/Simulator Screen Shot 2016年9月5日 下午9.17.31.png -------------------------------------------------------------------------------- /images/Simulator Screen Shot 2016年9月5日 下午9.17.48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/images/Simulator Screen Shot 2016年9月5日 下午9.17.48.png -------------------------------------------------------------------------------- /images/pod_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/images/pod_search.png -------------------------------------------------------------------------------- /images/tap9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyuant/MOFSPickerManagerDemo/5de2cf65030605a42d3dc10d25c24a913a0e6558/images/tap9.gif --------------------------------------------------------------------------------