├── README.md ├── textField.gif └── textField ├── textField.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── JiWuChao.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ ├── UserInterfaceState_BACKUP_2141.xcuserstate │ │ ├── UserInterfaceState_BASE_2141.xcuserstate │ │ ├── UserInterfaceState_LOCAL_2141.xcuserstate │ │ └── UserInterfaceState_REMOTE_2141.xcuserstate └── xcuserdata │ └── JiWuChao.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist └── textField ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── UITextField+NumberFormat.h ├── UITextField+NumberFormat.m ├── ViewController.h ├── ViewController.m └── main.m /README.md: -------------------------------------------------------------------------------- 1 | # TextField + NumberFormat 2 | 3 | >TextField中输入身份证号,手机号,银行卡号时每隔几位需要添加空格。当输入错误时需要从末尾或者中间删除,删除之后还要保持当前textfield的中内容保持每隔几位就有一个空格的格式。这个分类主要是为了解决这个问题 4 | 5 | ### (补2018年09月11日)使用条件 6 | 7 | - 目前还不支持动态的改变格式。即在输入之前是@[@2,@5],输入几个数字之后改变为@[@3,@6] 8 | - 不支持粘贴。当初在设计这个分类的时候,考虑到这种格式化的场景不太适合粘贴。因为粘贴的话不能保证用户粘贴过来的就是数字,可能是其他乱码,需要对粘贴过来的内容做过滤。当时嫌太麻烦也没太大必要就没做。不知道使用的小伙伴这种需求大不大,如果这种场景的使用比较多的话,最近比较忙,后期补上这种场景的处理 9 | 10 | ### API介绍 11 | 12 | 13 | ``` 14 | textField中输入的空格格式化 15 | @param textField 16 | @param range 17 | @param string 18 | @param blankLocation 要加的空格的位置 比如手机号11 位 如果需要 344的显示格式 空格位置就是 @[@4,@9] 19 | 身份证号最大 18位 684格式 空格位置 位@[@6,@15] 20 | 银行卡号最大 24 空格位置 @[@4,@9,@14,@19,@24] 不同的账号显示格式可以自定义 21 | @param limitCount 限制的长度 超过此限制长度 则不能输入 如果输入的为0 则不限制输入的长度 22 | @return textField中输入的身份证号 ,手机号,银行卡号 有需要在中间加入空格的需求 此扩展就是为了解决这类问题的 23 | 24 | */ 25 | + (BOOL)inputTextField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range 26 | replacementString:(NSString *)string 27 | blankLocations:(NSArray *)blankLocation 28 | limitCount:(NSInteger )limitCount; 29 | 30 | ``` 31 | 32 | 33 | ### 使用方法 34 | - [x] 只需一行代码 35 | 36 | ``` 37 | 38 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 39 | // 在textField的代理方法中调用这一句方法 40 | // 设置好要展示的格式 即 空格的位置blankLocations 41 | // 如果limitCount 为0 表示不显示输入的长度大小 42 | return [UITextField inputTextField:textField 43 | shouldChangeCharactersInRange:range 44 | replacementString:string 45 | blankLocations:@[@4,@9,@14,@19,@24] 46 | limitCount:24]; 47 | 48 | } 49 | 50 | 51 | ``` 52 | ### 原理讲解 53 | 54 | 具体实现原理在这 55 | [我是 blog 点我](http://www.wuchao.net.cn/2018/01/10/TextField%E8%BE%93%E5%85%A5%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%B7%E6%89%8B%E6%9C%BA%E5%8F%B7%E9%93%B6%E8%A1%8C%E5%8D%A1%E5%8F%B7%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%20/) 56 | 57 | ### 效果图 58 | 59 | 60 | ![image](https://github.com/JiWuChao/TextField/blob/master/textField.gif) -------------------------------------------------------------------------------- /textField.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nobodyJee/TextField/64ee434581045ad67a7a83b3bfe57fe83f85b5a0/textField.gif -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 047206711FC0A34F00FE9C72 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 047206701FC0A34F00FE9C72 /* AppDelegate.m */; }; 11 | 047206741FC0A34F00FE9C72 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 047206731FC0A34F00FE9C72 /* ViewController.m */; }; 12 | 047206771FC0A34F00FE9C72 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 047206751FC0A34F00FE9C72 /* Main.storyboard */; }; 13 | 047206791FC0A34F00FE9C72 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 047206781FC0A34F00FE9C72 /* Assets.xcassets */; }; 14 | 0472067C1FC0A34F00FE9C72 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0472067A1FC0A34F00FE9C72 /* LaunchScreen.storyboard */; }; 15 | 0472067F1FC0A34F00FE9C72 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0472067E1FC0A34F00FE9C72 /* main.m */; }; 16 | 049130171FC3F22E001308CE /* UITextField+NumberFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 049130161FC3F22E001308CE /* UITextField+NumberFormat.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 0472066C1FC0A34F00FE9C72 /* textField.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = textField.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 0472066F1FC0A34F00FE9C72 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 22 | 047206701FC0A34F00FE9C72 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 23 | 047206721FC0A34F00FE9C72 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 24 | 047206731FC0A34F00FE9C72 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 25 | 047206761FC0A34F00FE9C72 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | 047206781FC0A34F00FE9C72 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | 0472067B1FC0A34F00FE9C72 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | 0472067D1FC0A34F00FE9C72 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 0472067E1FC0A34F00FE9C72 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | 049130151FC3F22E001308CE /* UITextField+NumberFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITextField+NumberFormat.h"; sourceTree = ""; }; 31 | 049130161FC3F22E001308CE /* UITextField+NumberFormat.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITextField+NumberFormat.m"; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 047206691FC0A34F00FE9C72 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 047206631FC0A34F00FE9C72 = { 46 | isa = PBXGroup; 47 | children = ( 48 | 0472066E1FC0A34F00FE9C72 /* textField */, 49 | 0472066D1FC0A34F00FE9C72 /* Products */, 50 | ); 51 | sourceTree = ""; 52 | }; 53 | 0472066D1FC0A34F00FE9C72 /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 0472066C1FC0A34F00FE9C72 /* textField.app */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | 0472066E1FC0A34F00FE9C72 /* textField */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 0472066F1FC0A34F00FE9C72 /* AppDelegate.h */, 65 | 047206701FC0A34F00FE9C72 /* AppDelegate.m */, 66 | 047206721FC0A34F00FE9C72 /* ViewController.h */, 67 | 047206731FC0A34F00FE9C72 /* ViewController.m */, 68 | 049130151FC3F22E001308CE /* UITextField+NumberFormat.h */, 69 | 049130161FC3F22E001308CE /* UITextField+NumberFormat.m */, 70 | 047206751FC0A34F00FE9C72 /* Main.storyboard */, 71 | 047206781FC0A34F00FE9C72 /* Assets.xcassets */, 72 | 0472067A1FC0A34F00FE9C72 /* LaunchScreen.storyboard */, 73 | 0472067D1FC0A34F00FE9C72 /* Info.plist */, 74 | 0472067E1FC0A34F00FE9C72 /* main.m */, 75 | ); 76 | path = textField; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 0472066B1FC0A34F00FE9C72 /* textField */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 047206821FC0A34F00FE9C72 /* Build configuration list for PBXNativeTarget "textField" */; 85 | buildPhases = ( 86 | 047206681FC0A34F00FE9C72 /* Sources */, 87 | 047206691FC0A34F00FE9C72 /* Frameworks */, 88 | 0472066A1FC0A34F00FE9C72 /* Resources */, 89 | ); 90 | buildRules = ( 91 | ); 92 | dependencies = ( 93 | ); 94 | name = textField; 95 | productName = textField; 96 | productReference = 0472066C1FC0A34F00FE9C72 /* textField.app */; 97 | productType = "com.apple.product-type.application"; 98 | }; 99 | /* End PBXNativeTarget section */ 100 | 101 | /* Begin PBXProject section */ 102 | 047206641FC0A34F00FE9C72 /* Project object */ = { 103 | isa = PBXProject; 104 | attributes = { 105 | LastUpgradeCheck = 0910; 106 | ORGANIZATIONNAME = JiWuChao; 107 | TargetAttributes = { 108 | 0472066B1FC0A34F00FE9C72 = { 109 | CreatedOnToolsVersion = 9.1; 110 | ProvisioningStyle = Automatic; 111 | }; 112 | }; 113 | }; 114 | buildConfigurationList = 047206671FC0A34F00FE9C72 /* Build configuration list for PBXProject "textField" */; 115 | compatibilityVersion = "Xcode 8.0"; 116 | developmentRegion = en; 117 | hasScannedForEncodings = 0; 118 | knownRegions = ( 119 | en, 120 | Base, 121 | ); 122 | mainGroup = 047206631FC0A34F00FE9C72; 123 | productRefGroup = 0472066D1FC0A34F00FE9C72 /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | 0472066B1FC0A34F00FE9C72 /* textField */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXResourcesBuildPhase section */ 133 | 0472066A1FC0A34F00FE9C72 /* Resources */ = { 134 | isa = PBXResourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 0472067C1FC0A34F00FE9C72 /* LaunchScreen.storyboard in Resources */, 138 | 047206791FC0A34F00FE9C72 /* Assets.xcassets in Resources */, 139 | 047206771FC0A34F00FE9C72 /* Main.storyboard in Resources */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXResourcesBuildPhase section */ 144 | 145 | /* Begin PBXSourcesBuildPhase section */ 146 | 047206681FC0A34F00FE9C72 /* Sources */ = { 147 | isa = PBXSourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | 047206741FC0A34F00FE9C72 /* ViewController.m in Sources */, 151 | 0472067F1FC0A34F00FE9C72 /* main.m in Sources */, 152 | 049130171FC3F22E001308CE /* UITextField+NumberFormat.m in Sources */, 153 | 047206711FC0A34F00FE9C72 /* AppDelegate.m in Sources */, 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | /* End PBXSourcesBuildPhase section */ 158 | 159 | /* Begin PBXVariantGroup section */ 160 | 047206751FC0A34F00FE9C72 /* Main.storyboard */ = { 161 | isa = PBXVariantGroup; 162 | children = ( 163 | 047206761FC0A34F00FE9C72 /* Base */, 164 | ); 165 | name = Main.storyboard; 166 | sourceTree = ""; 167 | }; 168 | 0472067A1FC0A34F00FE9C72 /* LaunchScreen.storyboard */ = { 169 | isa = PBXVariantGroup; 170 | children = ( 171 | 0472067B1FC0A34F00FE9C72 /* Base */, 172 | ); 173 | name = LaunchScreen.storyboard; 174 | sourceTree = ""; 175 | }; 176 | /* End PBXVariantGroup section */ 177 | 178 | /* Begin XCBuildConfiguration section */ 179 | 047206801FC0A34F00FE9C72 /* Debug */ = { 180 | isa = XCBuildConfiguration; 181 | buildSettings = { 182 | ALWAYS_SEARCH_USER_PATHS = NO; 183 | CLANG_ANALYZER_NONNULL = YES; 184 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 185 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 186 | CLANG_CXX_LIBRARY = "libc++"; 187 | CLANG_ENABLE_MODULES = YES; 188 | CLANG_ENABLE_OBJC_ARC = YES; 189 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 190 | CLANG_WARN_BOOL_CONVERSION = YES; 191 | CLANG_WARN_COMMA = YES; 192 | CLANG_WARN_CONSTANT_CONVERSION = YES; 193 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 194 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 195 | CLANG_WARN_EMPTY_BODY = YES; 196 | CLANG_WARN_ENUM_CONVERSION = YES; 197 | CLANG_WARN_INFINITE_RECURSION = YES; 198 | CLANG_WARN_INT_CONVERSION = YES; 199 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 200 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 201 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 202 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 203 | CLANG_WARN_STRICT_PROTOTYPES = YES; 204 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 205 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 206 | CLANG_WARN_UNREACHABLE_CODE = YES; 207 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 208 | CODE_SIGN_IDENTITY = "iPhone Developer"; 209 | COPY_PHASE_STRIP = NO; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu11; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | IPHONEOS_DEPLOYMENT_TARGET = 11.1; 228 | MTL_ENABLE_DEBUG_INFO = YES; 229 | ONLY_ACTIVE_ARCH = YES; 230 | SDKROOT = iphoneos; 231 | }; 232 | name = Debug; 233 | }; 234 | 047206811FC0A34F00FE9C72 /* Release */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 240 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 241 | CLANG_CXX_LIBRARY = "libc++"; 242 | CLANG_ENABLE_MODULES = YES; 243 | CLANG_ENABLE_OBJC_ARC = YES; 244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 245 | CLANG_WARN_BOOL_CONVERSION = YES; 246 | CLANG_WARN_COMMA = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN_ENUM_CONVERSION = YES; 252 | CLANG_WARN_INFINITE_RECURSION = YES; 253 | CLANG_WARN_INT_CONVERSION = YES; 254 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 261 | CLANG_WARN_UNREACHABLE_CODE = YES; 262 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 263 | CODE_SIGN_IDENTITY = "iPhone Developer"; 264 | COPY_PHASE_STRIP = NO; 265 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 266 | ENABLE_NS_ASSERTIONS = NO; 267 | ENABLE_STRICT_OBJC_MSGSEND = YES; 268 | GCC_C_LANGUAGE_STANDARD = gnu11; 269 | GCC_NO_COMMON_BLOCKS = YES; 270 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 271 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 272 | GCC_WARN_UNDECLARED_SELECTOR = YES; 273 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 274 | GCC_WARN_UNUSED_FUNCTION = YES; 275 | GCC_WARN_UNUSED_VARIABLE = YES; 276 | IPHONEOS_DEPLOYMENT_TARGET = 11.1; 277 | MTL_ENABLE_DEBUG_INFO = NO; 278 | SDKROOT = iphoneos; 279 | VALIDATE_PRODUCT = YES; 280 | }; 281 | name = Release; 282 | }; 283 | 047206831FC0A34F00FE9C72 /* Debug */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 287 | CODE_SIGN_STYLE = Automatic; 288 | DEVELOPMENT_TEAM = 2D6N55N4D2; 289 | INFOPLIST_FILE = textField/Info.plist; 290 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 291 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 292 | PRODUCT_BUNDLE_IDENTIFIER = JiWuChao.textField; 293 | PRODUCT_NAME = "$(TARGET_NAME)"; 294 | TARGETED_DEVICE_FAMILY = "1,2"; 295 | }; 296 | name = Debug; 297 | }; 298 | 047206841FC0A34F00FE9C72 /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | CODE_SIGN_STYLE = Automatic; 303 | DEVELOPMENT_TEAM = 2D6N55N4D2; 304 | INFOPLIST_FILE = textField/Info.plist; 305 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 307 | PRODUCT_BUNDLE_IDENTIFIER = JiWuChao.textField; 308 | PRODUCT_NAME = "$(TARGET_NAME)"; 309 | TARGETED_DEVICE_FAMILY = "1,2"; 310 | }; 311 | name = Release; 312 | }; 313 | /* End XCBuildConfiguration section */ 314 | 315 | /* Begin XCConfigurationList section */ 316 | 047206671FC0A34F00FE9C72 /* Build configuration list for PBXProject "textField" */ = { 317 | isa = XCConfigurationList; 318 | buildConfigurations = ( 319 | 047206801FC0A34F00FE9C72 /* Debug */, 320 | 047206811FC0A34F00FE9C72 /* Release */, 321 | ); 322 | defaultConfigurationIsVisible = 0; 323 | defaultConfigurationName = Release; 324 | }; 325 | 047206821FC0A34F00FE9C72 /* Build configuration list for PBXNativeTarget "textField" */ = { 326 | isa = XCConfigurationList; 327 | buildConfigurations = ( 328 | 047206831FC0A34F00FE9C72 /* Debug */, 329 | 047206841FC0A34F00FE9C72 /* Release */, 330 | ); 331 | defaultConfigurationIsVisible = 0; 332 | defaultConfigurationName = Release; 333 | }; 334 | /* End XCConfigurationList section */ 335 | }; 336 | rootObject = 047206641FC0A34F00FE9C72 /* Project object */; 337 | } 338 | -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nobodyJee/TextField/64ee434581045ad67a7a83b3bfe57fe83f85b5a0/textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_BACKUP_2141.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nobodyJee/TextField/64ee434581045ad67a7a83b3bfe57fe83f85b5a0/textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_BACKUP_2141.xcuserstate -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_BASE_2141.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nobodyJee/TextField/64ee434581045ad67a7a83b3bfe57fe83f85b5a0/textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_BASE_2141.xcuserstate -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_LOCAL_2141.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nobodyJee/TextField/64ee434581045ad67a7a83b3bfe57fe83f85b5a0/textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_LOCAL_2141.xcuserstate -------------------------------------------------------------------------------- /textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_REMOTE_2141.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nobodyJee/TextField/64ee434581045ad67a7a83b3bfe57fe83f85b5a0/textField/textField.xcodeproj/project.xcworkspace/xcuserdata/JiWuChao.xcuserdatad/UserInterfaceState_REMOTE_2141.xcuserstate -------------------------------------------------------------------------------- /textField/textField.xcodeproj/xcuserdata/JiWuChao.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 56 | 68 | 69 | 70 | 72 | 82 | 83 | 84 | 86 | 96 | 97 | 98 | 100 | 110 | 111 | 112 | 114 | 124 | 125 | 126 | 128 | 138 | 139 | 140 | 142 | 152 | 153 | 154 | 156 | 166 | 167 | 168 | 170 | 180 | 181 | 182 | 184 | 194 | 195 | 196 | 198 | 208 | 209 | 210 | 212 | 222 | 223 | 224 | 226 | 236 | 237 | 238 | 240 | 250 | 251 | 252 | 254 | 264 | 265 | 266 | 268 | 278 | 279 | 280 | 282 | 292 | 293 | 294 | 296 | 308 | 309 | 310 | 312 | 324 | 325 | 326 | 328 | 340 | 341 | 342 | 343 | 344 | -------------------------------------------------------------------------------- /textField/textField.xcodeproj/xcuserdata/JiWuChao.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | textField.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /textField/textField/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/19. 6 | // Copyright © 2017年 JiWuChao. 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 | -------------------------------------------------------------------------------- /textField/textField/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/19. 6 | // Copyright © 2017年 JiWuChao. 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 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /textField/textField/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 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /textField/textField/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 | -------------------------------------------------------------------------------- /textField/textField/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 | -------------------------------------------------------------------------------- /textField/textField/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /textField/textField/UITextField+NumberFormat.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+NumberFormat.h 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/21. 6 | // Copyright © 2017年 JiWuChao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UITextField (NumberFormat) 12 | /** 13 | textField中输入的空格格式化 14 | 15 | @param textField <#textField description#> 16 | @param range <#range description#> 17 | @param string <#string description#> 18 | @param blankLocation 要加的空格的位置 比如手机号11 位 如果需要 344的显示格式 空格位置就是 @[@4,@9] 19 | 身份证号最大 18位 684格式 空格位置 位@[@6,@15] 20 | 银行卡号最大 24 空格位置 @[@4,@9,@14,@19,@24] 不同的账号显示格式可以自定义 21 | @param limitCount 限制的长度 超过此限制长度 则不能输入 如果输入的为0 则不显示输入的长度 22 | @return textField中输入的身份证号 ,手机号,银行卡号 有需要在中间加入空格的需求 此扩展就是为了解决这类问题的 23 | 24 | */ 25 | + (BOOL)inputTextField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range 26 | replacementString:(NSString *)string 27 | blankLocations:(NSArray *)blankLocation 28 | limitCount:(NSInteger )limitCount; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /textField/textField/UITextField+NumberFormat.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+NumberFormat.m 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/21. 6 | // Copyright © 2017年 JiWuChao. All rights reserved. 7 | // 8 | 9 | #import "UITextField+NumberFormat.h" 10 | 11 | @implementation UITextField (NumberFormat) 12 | 13 | + (BOOL)inputTextField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range 14 | replacementString:(NSString *)string 15 | blankLocations:(NSArray *)blankLocation 16 | limitCount:(NSInteger)limitCount { 17 | 18 | BOOL limit = YES; 19 | if (limitCount == 0) { 20 | limit = NO; 21 | } 22 | if (textField) { 23 | NSString *text = textField.text; 24 | if ([string isEqualToString:@""]) { // 删除 25 | if (range.length == 1) {// 删除一位 26 | if (range.location == text.length - 1) { // location是下标 此句表示删除的最后一位 27 | return YES; 28 | } else { // 不是最后一位 29 | NSInteger offset = range.location; 30 | if (range.location < text.length && [text characterAtIndex:range.location] == ' ' && [textField.selectedTextRange isEmpty]) { 31 | [textField deleteBackward]; 32 | offset --; 33 | } 34 | [textField deleteBackward]; 35 | textField.text = [self insertString:textField.text withBlankLocations:blankLocation]; 36 | //设置光标的位置 37 | [self setCursorLocation:textField withOffset:offset]; 38 | return NO; 39 | } 40 | } else if (range.length > 1) { 41 | BOOL lastOne = NO; 42 | if (range.location + range.length == text.length) {//是否是最后一位 43 | lastOne = YES; 44 | } 45 | [textField deleteBackward]; 46 | textField.text = [self insertString:textField.text withBlankLocations:blankLocation]; 47 | NSInteger offset = range.location; 48 | if (lastOne) { 49 | // 最后一个不需要设置光标 50 | } else { 51 | [self setCursorLocation:textField withOffset:offset]; 52 | } 53 | return NO; 54 | } else { 55 | return YES; 56 | } 57 | } else if (string.length > 0) { 58 | if (limit) { 59 | if ([self removeBlankString:textField.text].length + string.length - range.length > limitCount ) {// [self whiteSpaseString:textField.text].length 目前textfield中有的 内容的长度 string.length 即将加入的内容的长度 range.length 60 | return NO; 61 | } 62 | } 63 | } 64 | [textField insertText:string]; 65 | textField.text = [self insertString:textField.text withBlankLocations:blankLocation]; 66 | NSInteger offset = range.location + string.length; 67 | 68 | for (NSNumber *location in blankLocation) { 69 | if (range.location == location.integerValue) { 70 | offset ++; 71 | } 72 | } 73 | [self setCursorLocation:textField withOffset:offset]; 74 | return NO; 75 | 76 | } else { 77 | return YES; 78 | } 79 | return YES; 80 | } 81 | 82 | // 在指定的位置添加空格 83 | +(NSString*)insertString:(NSString*)string withBlankLocations:(NSArray*)locations { 84 | if (!string) { 85 | return nil; 86 | } 87 | NSMutableString* mutableString = [NSMutableString stringWithString:[string stringByReplacingOccurrencesOfString:@" " withString:@""]]; 88 | for (NSNumber *location in locations) { 89 | if (mutableString.length > location.integerValue) { 90 | [mutableString insertString:@" " atIndex:location.integerValue]; 91 | } 92 | } 93 | return mutableString; 94 | } 95 | 96 | // 去除空格 97 | +(NSString*)removeBlankString:(NSString*)string { 98 | return [string stringByReplacingOccurrencesOfString:@" " withString:@""]; 99 | } 100 | 101 | // 设置光标 102 | + (void)setCursorLocation:(UITextField *)textField withOffset:(NSInteger) offset{ 103 | UITextPosition *newPostion = [textField positionFromPosition:textField.beginningOfDocument offset:offset] ; 104 | textField.selectedTextRange = [textField textRangeFromPosition:newPostion toPosition:newPostion]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /textField/textField/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/19. 6 | // Copyright © 2017年 JiWuChao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /textField/textField/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/19. 6 | // Copyright © 2017年 JiWuChao. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "UITextField+NumberFormat.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (nonatomic, strong) UITextField *textBankNumber; 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | [self textBankNumber]; 24 | } 25 | 26 | #pragma mark - UITextFieldDelegate 27 | - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { 28 | return YES; 29 | } 30 | 31 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 32 | 33 | return [UITextField inputTextField:textField 34 | shouldChangeCharactersInRange:range 35 | replacementString:string 36 | blankLocations:@[@4,@9,@14,@19,@24] 37 | limitCount:24]; 38 | 39 | }// @[@6,@15] @[@4,@9,@14,@19,@24] @[@4,@9] 40 | 41 | 42 | #pragma mark - setupUI 43 | 44 | - (UITextField *)textBankNumber { 45 | if (!_textBankNumber) { 46 | _textBankNumber = [[UITextField alloc] initWithFrame:CGRectMake(50, 100, 250, 30)]; 47 | _textBankNumber.delegate = self; 48 | _textBankNumber.backgroundColor = [UIColor whiteColor]; 49 | _textBankNumber.borderStyle = UITextBorderStyleRoundedRect; 50 | _textBankNumber.keyboardType = UIKeyboardTypeNumberPad; 51 | _textBankNumber.placeholder = @"请输入~~"; 52 | [self.view addSubview:_textBankNumber]; 53 | } 54 | return _textBankNumber; 55 | } 56 | 57 | 58 | 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /textField/textField/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // textField 4 | // 5 | // Created by JiWuChao on 2017/11/19. 6 | // Copyright © 2017年 JiWuChao. 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 | --------------------------------------------------------------------------------