├── Extension └── String+Validators.swift ├── IDCardNumber-Validation-Demo ├── IDCardNumber-Validation-Demo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ ├── Mac.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── vincent.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── Mac.xcuserdatad │ │ └── xcschemes │ │ │ ├── IDCardNumber-Validation-Demo.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── vincent.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── IDCardNumber-Validation-Demo │ ├── NSString+IDCardNumberValidator.h │ ├── NSString+IDCardNumberValidator.m │ └── main.m ├── IDCardNumber-Validator.podspec ├── LICENSE ├── README.md └── Swift-Demo ├── Swift-Demo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── vincent.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── vincent.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── Swift-Demo ├── String+Validators.swift └── main.swift /Extension/String+Validators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Validators.swift 3 | // Swift-Demo 4 | // 5 | // Created by Zhishen Wen on 2018/4/10. 6 | // Copyright © 2018 0xa6a. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | extension String { 13 | /// 验证身份证号码 14 | func validateIDCardNumber() -> Bool { 15 | struct Static { 16 | fileprivate static let predicate: NSPredicate = { 17 | let regex = "(^\\d{15}$)|(^\\d{17}([0-9]|X)$)" 18 | let predicate = NSPredicate(format: "SELF MATCHES %@", argumentArray: [regex]) 19 | return predicate 20 | }() 21 | fileprivate static let provinceCodes = [ 22 | "11", "12", "13", "14", "15", 23 | "21", "22", "23", 24 | "31", "32", "33", "34", "35", "36", "37", 25 | "41", "42", "43", "44", "45", "46", 26 | "50", "51", "52", "53", "54", 27 | "61", "62", "63", "64", "65", 28 | "71", "81", "82", "91"] 29 | } 30 | // 初步验证 31 | guard Static.predicate.evaluate(with: self) else { 32 | return false 33 | } 34 | // 验证省份代码。如果需要更精确的话,可以把前六位行政区划代码都列举出来比较。 35 | let provinceCode = String(self.prefix(2)) 36 | guard Static.provinceCodes.contains(provinceCode) else { 37 | return false 38 | } 39 | if self.count == 15 { 40 | return self.validate15DigitsIDCardNumber() 41 | } else { 42 | return self.validate18DigitsIDCardNumber() 43 | } 44 | } 45 | 46 | /// 15位身份证号码验证。 47 | // 6位行政区划代码 + 6位出生日期码(yyMMdd) + 3位顺序码 48 | private func validate15DigitsIDCardNumber() -> Bool { 49 | let birthdate = "19\(self.substring(from: 6, to: 11)!)" 50 | return birthdate.validateBirthDate() 51 | } 52 | 53 | /// 18位身份证号码验证。 54 | // 6位行政区划代码 + 8位出生日期码(yyyyMMdd) + 3位顺序码 + 1位校验码 55 | private func validate18DigitsIDCardNumber() -> Bool { 56 | let birthdate = self.substring(from: 6, to: 13)! 57 | guard birthdate.validateBirthDate() else { 58 | return false 59 | } 60 | struct Static { 61 | static let weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2] 62 | static let validationCodes = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"] 63 | } 64 | // 验证校验位 65 | let digits = self.substring(from: 0, to: 16)!.map { Int("\($0)")! } 66 | var sum = 0 67 | for i in 0.. Bool { 76 | struct Static { 77 | static let dateFormatter: DateFormatter = { 78 | let dateFormatter = DateFormatter() 79 | dateFormatter.dateFormat = "yyyyMMdd" 80 | return dateFormatter 81 | }() 82 | } 83 | if let _ = Static.dateFormatter.date(from: self) { 84 | return true 85 | } else { 86 | return false 87 | } 88 | } 89 | 90 | private func substring(from: Int, to: Int) -> String? { 91 | guard to >= from && from >= 0 && to < count else { 92 | return nil 93 | } 94 | let startIdx = self.index(startIndex, offsetBy: from) 95 | let endIdx = self.index(startIndex, offsetBy: to) 96 | return String(self[startIdx...endIdx]) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 040AA2CF1C814F8700D4B221 /* NSString+IDCardNumberValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 040AA2CE1C814F8700D4B221 /* NSString+IDCardNumberValidator.m */; }; 11 | 04A7BFC21C8060B800A24D71 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A7BFC11C8060B800A24D71 /* main.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 04A7BFBC1C8060B800A24D71 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 040AA2CD1C814F8700D4B221 /* NSString+IDCardNumberValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+IDCardNumberValidator.h"; sourceTree = ""; }; 28 | 040AA2CE1C814F8700D4B221 /* NSString+IDCardNumberValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+IDCardNumberValidator.m"; sourceTree = ""; }; 29 | 04A7BFBE1C8060B800A24D71 /* IDCardNumber-Validation-Demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "IDCardNumber-Validation-Demo"; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 04A7BFC11C8060B800A24D71 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 04A7BFBB1C8060B800A24D71 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 04A7BFB51C8060B800A24D71 = { 45 | isa = PBXGroup; 46 | children = ( 47 | 04A7BFC01C8060B800A24D71 /* IDCardNumber-Validation-Demo */, 48 | 04A7BFBF1C8060B800A24D71 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 04A7BFBF1C8060B800A24D71 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 04A7BFBE1C8060B800A24D71 /* IDCardNumber-Validation-Demo */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 04A7BFC01C8060B800A24D71 /* IDCardNumber-Validation-Demo */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 04A7BFC11C8060B800A24D71 /* main.m */, 64 | 040AA2CD1C814F8700D4B221 /* NSString+IDCardNumberValidator.h */, 65 | 040AA2CE1C814F8700D4B221 /* NSString+IDCardNumberValidator.m */, 66 | ); 67 | path = "IDCardNumber-Validation-Demo"; 68 | sourceTree = ""; 69 | }; 70 | /* End PBXGroup section */ 71 | 72 | /* Begin PBXNativeTarget section */ 73 | 04A7BFBD1C8060B800A24D71 /* IDCardNumber-Validation-Demo */ = { 74 | isa = PBXNativeTarget; 75 | buildConfigurationList = 04A7BFC51C8060B800A24D71 /* Build configuration list for PBXNativeTarget "IDCardNumber-Validation-Demo" */; 76 | buildPhases = ( 77 | 04A7BFBA1C8060B800A24D71 /* Sources */, 78 | 04A7BFBB1C8060B800A24D71 /* Frameworks */, 79 | 04A7BFBC1C8060B800A24D71 /* CopyFiles */, 80 | ); 81 | buildRules = ( 82 | ); 83 | dependencies = ( 84 | ); 85 | name = "IDCardNumber-Validation-Demo"; 86 | productName = "IDCardNumber-Validation-Demo"; 87 | productReference = 04A7BFBE1C8060B800A24D71 /* IDCardNumber-Validation-Demo */; 88 | productType = "com.apple.product-type.tool"; 89 | }; 90 | /* End PBXNativeTarget section */ 91 | 92 | /* Begin PBXProject section */ 93 | 04A7BFB61C8060B800A24D71 /* Project object */ = { 94 | isa = PBXProject; 95 | attributes = { 96 | LastUpgradeCheck = 0720; 97 | ORGANIZATIONNAME = Vincent; 98 | TargetAttributes = { 99 | 04A7BFBD1C8060B800A24D71 = { 100 | CreatedOnToolsVersion = 7.2.1; 101 | }; 102 | }; 103 | }; 104 | buildConfigurationList = 04A7BFB91C8060B800A24D71 /* Build configuration list for PBXProject "IDCardNumber-Validation-Demo" */; 105 | compatibilityVersion = "Xcode 3.2"; 106 | developmentRegion = English; 107 | hasScannedForEncodings = 0; 108 | knownRegions = ( 109 | English, 110 | en, 111 | ); 112 | mainGroup = 04A7BFB51C8060B800A24D71; 113 | productRefGroup = 04A7BFBF1C8060B800A24D71 /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | 04A7BFBD1C8060B800A24D71 /* IDCardNumber-Validation-Demo */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXSourcesBuildPhase section */ 123 | 04A7BFBA1C8060B800A24D71 /* Sources */ = { 124 | isa = PBXSourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | 040AA2CF1C814F8700D4B221 /* NSString+IDCardNumberValidator.m in Sources */, 128 | 04A7BFC21C8060B800A24D71 /* main.m in Sources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXSourcesBuildPhase section */ 133 | 134 | /* Begin XCBuildConfiguration section */ 135 | 04A7BFC31C8060B800A24D71 /* Debug */ = { 136 | isa = XCBuildConfiguration; 137 | buildSettings = { 138 | ALWAYS_SEARCH_USER_PATHS = NO; 139 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 140 | CLANG_CXX_LIBRARY = "libc++"; 141 | CLANG_ENABLE_MODULES = YES; 142 | CLANG_ENABLE_OBJC_ARC = YES; 143 | CLANG_WARN_BOOL_CONVERSION = YES; 144 | CLANG_WARN_CONSTANT_CONVERSION = YES; 145 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 150 | CLANG_WARN_UNREACHABLE_CODE = YES; 151 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 152 | CODE_SIGN_IDENTITY = "-"; 153 | COPY_PHASE_STRIP = NO; 154 | DEBUG_INFORMATION_FORMAT = dwarf; 155 | ENABLE_STRICT_OBJC_MSGSEND = YES; 156 | ENABLE_TESTABILITY = YES; 157 | GCC_C_LANGUAGE_STANDARD = gnu99; 158 | GCC_DYNAMIC_NO_PIC = NO; 159 | GCC_NO_COMMON_BLOCKS = YES; 160 | GCC_OPTIMIZATION_LEVEL = 0; 161 | GCC_PREPROCESSOR_DEFINITIONS = ( 162 | "DEBUG=1", 163 | "$(inherited)", 164 | ); 165 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 166 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 167 | GCC_WARN_UNDECLARED_SELECTOR = YES; 168 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 169 | GCC_WARN_UNUSED_FUNCTION = YES; 170 | GCC_WARN_UNUSED_VARIABLE = YES; 171 | MACOSX_DEPLOYMENT_TARGET = 10.11; 172 | MTL_ENABLE_DEBUG_INFO = YES; 173 | ONLY_ACTIVE_ARCH = YES; 174 | SDKROOT = macosx; 175 | }; 176 | name = Debug; 177 | }; 178 | 04A7BFC41C8060B800A24D71 /* Release */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_WARN_BOOL_CONVERSION = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 189 | CLANG_WARN_EMPTY_BODY = YES; 190 | CLANG_WARN_ENUM_CONVERSION = YES; 191 | CLANG_WARN_INT_CONVERSION = YES; 192 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 193 | CLANG_WARN_UNREACHABLE_CODE = YES; 194 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 195 | CODE_SIGN_IDENTITY = "-"; 196 | COPY_PHASE_STRIP = NO; 197 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 198 | ENABLE_NS_ASSERTIONS = NO; 199 | ENABLE_STRICT_OBJC_MSGSEND = YES; 200 | GCC_C_LANGUAGE_STANDARD = gnu99; 201 | GCC_NO_COMMON_BLOCKS = YES; 202 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 203 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 204 | GCC_WARN_UNDECLARED_SELECTOR = YES; 205 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 206 | GCC_WARN_UNUSED_FUNCTION = YES; 207 | GCC_WARN_UNUSED_VARIABLE = YES; 208 | MACOSX_DEPLOYMENT_TARGET = 10.11; 209 | MTL_ENABLE_DEBUG_INFO = NO; 210 | SDKROOT = macosx; 211 | }; 212 | name = Release; 213 | }; 214 | 04A7BFC61C8060B800A24D71 /* Debug */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | PRODUCT_NAME = "$(TARGET_NAME)"; 218 | }; 219 | name = Debug; 220 | }; 221 | 04A7BFC71C8060B800A24D71 /* Release */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | PRODUCT_NAME = "$(TARGET_NAME)"; 225 | }; 226 | name = Release; 227 | }; 228 | /* End XCBuildConfiguration section */ 229 | 230 | /* Begin XCConfigurationList section */ 231 | 04A7BFB91C8060B800A24D71 /* Build configuration list for PBXProject "IDCardNumber-Validation-Demo" */ = { 232 | isa = XCConfigurationList; 233 | buildConfigurations = ( 234 | 04A7BFC31C8060B800A24D71 /* Debug */, 235 | 04A7BFC41C8060B800A24D71 /* Release */, 236 | ); 237 | defaultConfigurationIsVisible = 0; 238 | defaultConfigurationName = Release; 239 | }; 240 | 04A7BFC51C8060B800A24D71 /* Build configuration list for PBXNativeTarget "IDCardNumber-Validation-Demo" */ = { 241 | isa = XCConfigurationList; 242 | buildConfigurations = ( 243 | 04A7BFC61C8060B800A24D71 /* Debug */, 244 | 04A7BFC71C8060B800A24D71 /* Release */, 245 | ); 246 | defaultConfigurationIsVisible = 0; 247 | defaultConfigurationName = Release; 248 | }; 249 | /* End XCConfigurationList section */ 250 | }; 251 | rootObject = 04A7BFB61C8060B800A24D71 /* Project object */; 252 | } 253 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.xcworkspace/xcuserdata/Mac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzso/IDCardNumber-Validator/ef67f69f8da64129036f37c8adf67c481c8f3be5/IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.xcworkspace/xcuserdata/Mac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.xcworkspace/xcuserdata/vincent.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzso/IDCardNumber-Validator/ef67f69f8da64129036f37c8adf67c481c8f3be5/IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/project.xcworkspace/xcuserdata/vincent.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/xcuserdata/Mac.xcuserdatad/xcschemes/IDCardNumber-Validation-Demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/xcuserdata/Mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IDCardNumber-Validation-Demo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 04A7BFBD1C8060B800A24D71 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo.xcodeproj/xcuserdata/vincent.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IDCardNumber-Validation-Demo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | IDCardNumber-Validation-Demo.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo/NSString+IDCardNumberValidator.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IDCardNumberValidator.h 3 | // IDCardNumber-Validation-Demo 4 | // 5 | // Created by Vincent on 2/26/16. 6 | // Copyright © 2016 Vincent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (IDCardNumberValidator) 12 | - (BOOL)validIDCardNumber; 13 | @end 14 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo/NSString+IDCardNumberValidator.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IDCardNumberValidator.m 3 | // IDCardNumber-Validation-Demo 4 | // 5 | // Created by Vincent on 2/26/16. 6 | // Copyright © 2016 Vincent. All rights reserved. 7 | // 8 | 9 | #import "NSString+IDCardNumberValidator.h" 10 | 11 | @implementation NSString (IDCardNumberValidator) 12 | 13 | /// 验证身份证号码 14 | - (BOOL)validIDCardNumber { 15 | NSString *regex = @"(^\\d{15}$)|(^\\d{17}([0-9]|X)$)"; 16 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; 17 | if (![predicate evaluateWithObject:self]) return NO; 18 | // 省份代码。如果需要更精确的话,可以把六位行政区划代码都列举出来比较。 19 | NSString *provinceCode = [self substringToIndex:2]; 20 | NSArray *proviceCodes = @[@"11", @"12", @"13", @"14", @"15", 21 | @"21", @"22", @"23", 22 | @"31", @"32", @"33", @"34", @"35", @"36", @"37", 23 | @"41", @"42", @"43", @"44", @"45", @"46", 24 | @"50", @"51", @"52", @"53", @"54", 25 | @"61", @"62", @"63", @"64", @"65", 26 | @"71", @"81", @"82", @"91"]; 27 | if (![proviceCodes containsObject:provinceCode]) return NO; 28 | 29 | if (self.length == 15) { 30 | return [self validate15DigitsIDCardNumber]; 31 | } else { 32 | return [self validate18DigitsIDCardNumber]; 33 | } 34 | } 35 | 36 | #pragma mark Helpers 37 | /// 15位身份证号码验证。6位行政区划代码 + 6位出生日期码(yyMMdd) + 3位顺序码 38 | - (BOOL)validate15DigitsIDCardNumber { 39 | NSString *birthday = [NSString stringWithFormat:@"19%@", [self substringWithRange:NSMakeRange(6, 6)]]; // 00后都是18位的身份证号 40 | 41 | return [birthday validateBirthDate]; 42 | } 43 | 44 | /// 18位身份证号码验证。6位行政区划代码 + 8位出生日期码(yyyyMMdd) + 3位顺序码 + 1位校验码 45 | - (BOOL)validate18DigitsIDCardNumber { 46 | NSString *birthday = [self substringWithRange:NSMakeRange(6, 8)]; 47 | if (![birthday validateBirthDate]) return NO; 48 | 49 | // 验证校验码 50 | int weight[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; 51 | 52 | int sum = 0; 53 | for (int i = 0; i < 17; i ++) { 54 | sum += [self substringWithRange:NSMakeRange(i, 1)].intValue * weight[i]; 55 | } 56 | int mod11 = sum % 11; 57 | NSArray *validationCodes = [@"1 0 X 9 8 7 6 5 4 3 2" componentsSeparatedByString:@" "]; 58 | NSString *validationCode = validationCodes[mod11]; 59 | 60 | return [self hasSuffix:validationCode]; 61 | } 62 | 63 | /// 验证出生年月日(yyyyMMdd) 64 | - (BOOL)validateBirthDate { 65 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 66 | dateFormatter.dateFormat = @"yyyyMMdd"; 67 | NSDate *date = [dateFormatter dateFromString:self]; 68 | return date != nil; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /IDCardNumber-Validation-Demo/IDCardNumber-Validation-Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // IDCardNumber-Validation-Demo 4 | // 5 | // Created by Vincent on 2/26/16. 6 | // Copyright © 2016 Vincent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSString+IDCardNumberValidator.h" 11 | 12 | int main(int argc, const char * argv[]) { 13 | @autoreleasepool { 14 | // insert code here... 15 | NSArray *IDs = @[@"500234200105183376", @"431027200010280016", @"441322199002093019", @"61232619800820051X", @"522731198402148335", @"441322199211282721", @"522129198306064014", @"420983199207026013", @"452630197408051724", @"512223196101233677", @"522524197103085814", @"43052219730821437X", @"362123197605253015", @"450821199604182192", @"441624199910023816", @"441624198002295248", @"510821197204033718", @"420921199005174422", @"500236198609253983", @"45272819871014361X", @"441481199612124885", @"432826197812220377", @"422424196807122261", @"450722198507101537", @"450722199607131551", @"450603197901110029", @"370919196910141540", @"440523198008030213", @"511121197502030411", @"441421198711106411", @"452402198705210611", @"441522197205155111", @"44152319900520704X", @"440882199404255722", @"513029198701303074", @"44082519731224195X", @"51112119631209329X", @"422324198512152985", @"42100219951020455X"]; 16 | for (NSString *ID in IDs) { 17 | NSLog(@"%@-%@", ID, [ID validIDCardNumber] ? @"True" : @"False"); 18 | } 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /IDCardNumber-Validator.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint IDCardNumber-Validator.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 https://guides.cocoapods.org/syntax/podspec.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |spec| 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 | spec.name = "IDCardNumber-Validator" 19 | spec.version = "1.0.0" 20 | spec.summary = "OC & Swift身份证号码验证" 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 | spec.description = "An Objective-C & Swift implementation to validate Chinese ID Card No. 身份证号码验证。" 28 | 29 | spec.homepage = "https://github.com/benjamin-wen/IDCardNumber-Validator" 30 | # spec.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 31 | 32 | 33 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 34 | # 35 | # Licensing your code is important. See https://choosealicense.com for more info. 36 | # CocoaPods will detect a license file if there is a named LICENSE* 37 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 38 | # 39 | 40 | spec.license = { :type => "MIT", :file => "LICENSE" } 41 | 42 | 43 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 44 | # 45 | # Specify the authors of the library, with email addresses. Email addresses 46 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 47 | # accepts just a name if you'd rather not provide an email address. 48 | # 49 | # Specify a social_media_url where others can refer to, for example a twitter 50 | # profile URL. 51 | # 52 | 53 | spec.author = "Benjamin Wen" 54 | # Or just: spec.author = "Mint" 55 | # spec.authors = { "Mint" => "email@address.com" } 56 | # spec.social_media_url = "https://twitter.com/Mint" 57 | 58 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 59 | # 60 | # If this Pod runs only on iOS or OS X, then specify the platform and 61 | # the deployment target. You can optionally include the target after the platform. 62 | # 63 | 64 | spec.platform = :ios 65 | spec.platform = :ios, "8.0" 66 | spec.swift_versions = "5.0" 67 | 68 | # When using multiple platforms 69 | # spec.ios.deployment_target = "5.0" 70 | # spec.osx.deployment_target = "10.7" 71 | # spec.watchos.deployment_target = "2.0" 72 | # spec.tvos.deployment_target = "9.0" 73 | 74 | 75 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 76 | # 77 | # Specify the location from where the source should be retrieved. 78 | # Supports git, hg, bzr, svn and HTTP. 79 | # 80 | 81 | spec.source = { :git => "https://github.com/benjamin-wen/IDCardNumber-Validator.git", :tag => "1.0.0" } 82 | 83 | 84 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 85 | # 86 | # CocoaPods is smart about how it includes source code. For source files 87 | # giving a folder will include any swift, h, m, mm, c & cpp files. 88 | # For header files it will include any header in the folder. 89 | # Not including the public_header_files will make all headers public. 90 | # 91 | 92 | spec.source_files = "Extension/**/*.swift" 93 | # spec.exclude_files = "Classes/Exclude" 94 | 95 | # spec.public_header_files = "Classes/**/*.h" 96 | 97 | 98 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 99 | # 100 | # A list of resources included with the Pod. These are copied into the 101 | # target bundle with a build phase script. Anything else will be cleaned. 102 | # You can preserve files from being cleaned, please don't preserve 103 | # non-essential files like tests, examples and documentation. 104 | # 105 | 106 | # spec.resource = "icon.png" 107 | # spec.resources = "Resources/*.png" 108 | 109 | # spec.preserve_paths = "FilesToSave", "MoreFilesToSave" 110 | 111 | 112 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 113 | # 114 | # Link your library with frameworks, or libraries. Libraries do not include 115 | # the lib prefix of their name. 116 | # 117 | 118 | # spec.framework = "SomeFramework" 119 | # spec.frameworks = "SomeFramework", "AnotherFramework" 120 | 121 | # spec.library = "iconv" 122 | # spec.libraries = "iconv", "xml2" 123 | 124 | 125 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 126 | # 127 | # If your library depends on compiler flags you can set them in the xcconfig hash 128 | # where they will only apply to your library. If you depend on other Podspecs 129 | # you can include multiple dependencies to ensure it works. 130 | 131 | # spec.requires_arc = true 132 | 133 | # spec.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 134 | # spec.dependency "JSONKit", "~> 1.4" 135 | 136 | end 137 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Vincent 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IDCardNumber-Validation 2 | 3 | 4 | 5 | [![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) 6 | [![pod](https://img.shields.io/cocoapods/v/IDCardNumber-Validator.svg?style=flat)](https://cocoapods.org/pods/IDCardNumber-Validator) 7 | 8 | 9 | An Objective-C & Swift implementation to (check) validate Chinese ID Card No. 身份证号码验证。 10 | 11 | ### Reference: 12 | * [国家统计局-行政区划代码](http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/); 13 | * [身份证号码验证算法](http://www.cnblogs.com/xudong-bupt/p/3293838.html); 14 | 15 | 16 | # Install 17 | 18 | pod 'IDCardNumber-Validator' 19 | -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BF9B2BE5207C5514006F945A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9B2BE4207C5514006F945A /* main.swift */; }; 11 | BF9B2BEC207C5536006F945A /* String+Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9B2BEB207C5536006F945A /* String+Validators.swift */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | BF9B2BDF207C5514006F945A /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | BF9B2BE1207C5514006F945A /* Swift-Demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Swift-Demo"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | BF9B2BE4207C5514006F945A /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 29 | BF9B2BEB207C5536006F945A /* String+Validators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Validators.swift"; sourceTree = ""; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | BF9B2BDE207C5514006F945A /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | ); 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXFrameworksBuildPhase section */ 41 | 42 | /* Begin PBXGroup section */ 43 | BF9B2BD8207C5514006F945A = { 44 | isa = PBXGroup; 45 | children = ( 46 | BF9B2BE3207C5514006F945A /* Swift-Demo */, 47 | BF9B2BE2207C5514006F945A /* Products */, 48 | ); 49 | sourceTree = ""; 50 | }; 51 | BF9B2BE2207C5514006F945A /* Products */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | BF9B2BE1207C5514006F945A /* Swift-Demo */, 55 | ); 56 | name = Products; 57 | sourceTree = ""; 58 | }; 59 | BF9B2BE3207C5514006F945A /* Swift-Demo */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | BF9B2BE4207C5514006F945A /* main.swift */, 63 | BF9B2BEB207C5536006F945A /* String+Validators.swift */, 64 | ); 65 | path = "Swift-Demo"; 66 | sourceTree = ""; 67 | }; 68 | /* End PBXGroup section */ 69 | 70 | /* Begin PBXNativeTarget section */ 71 | BF9B2BE0207C5514006F945A /* Swift-Demo */ = { 72 | isa = PBXNativeTarget; 73 | buildConfigurationList = BF9B2BE8207C5514006F945A /* Build configuration list for PBXNativeTarget "Swift-Demo" */; 74 | buildPhases = ( 75 | BF9B2BDD207C5514006F945A /* Sources */, 76 | BF9B2BDE207C5514006F945A /* Frameworks */, 77 | BF9B2BDF207C5514006F945A /* CopyFiles */, 78 | ); 79 | buildRules = ( 80 | ); 81 | dependencies = ( 82 | ); 83 | name = "Swift-Demo"; 84 | productName = "Swift-Demo"; 85 | productReference = BF9B2BE1207C5514006F945A /* Swift-Demo */; 86 | productType = "com.apple.product-type.tool"; 87 | }; 88 | /* End PBXNativeTarget section */ 89 | 90 | /* Begin PBXProject section */ 91 | BF9B2BD9207C5514006F945A /* Project object */ = { 92 | isa = PBXProject; 93 | attributes = { 94 | LastSwiftUpdateCheck = 0930; 95 | LastUpgradeCheck = 0930; 96 | ORGANIZATIONNAME = 0xa6a; 97 | TargetAttributes = { 98 | BF9B2BE0207C5514006F945A = { 99 | CreatedOnToolsVersion = 9.3; 100 | }; 101 | }; 102 | }; 103 | buildConfigurationList = BF9B2BDC207C5514006F945A /* Build configuration list for PBXProject "Swift-Demo" */; 104 | compatibilityVersion = "Xcode 9.3"; 105 | developmentRegion = en; 106 | hasScannedForEncodings = 0; 107 | knownRegions = ( 108 | en, 109 | ); 110 | mainGroup = BF9B2BD8207C5514006F945A; 111 | productRefGroup = BF9B2BE2207C5514006F945A /* Products */; 112 | projectDirPath = ""; 113 | projectRoot = ""; 114 | targets = ( 115 | BF9B2BE0207C5514006F945A /* Swift-Demo */, 116 | ); 117 | }; 118 | /* End PBXProject section */ 119 | 120 | /* Begin PBXSourcesBuildPhase section */ 121 | BF9B2BDD207C5514006F945A /* Sources */ = { 122 | isa = PBXSourcesBuildPhase; 123 | buildActionMask = 2147483647; 124 | files = ( 125 | BF9B2BE5207C5514006F945A /* main.swift in Sources */, 126 | BF9B2BEC207C5536006F945A /* String+Validators.swift in Sources */, 127 | ); 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXSourcesBuildPhase section */ 131 | 132 | /* Begin XCBuildConfiguration section */ 133 | BF9B2BE6207C5514006F945A /* Debug */ = { 134 | isa = XCBuildConfiguration; 135 | buildSettings = { 136 | ALWAYS_SEARCH_USER_PATHS = NO; 137 | CLANG_ANALYZER_NONNULL = YES; 138 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 139 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 140 | CLANG_CXX_LIBRARY = "libc++"; 141 | CLANG_ENABLE_MODULES = YES; 142 | CLANG_ENABLE_OBJC_ARC = YES; 143 | CLANG_ENABLE_OBJC_WEAK = YES; 144 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 145 | CLANG_WARN_BOOL_CONVERSION = YES; 146 | CLANG_WARN_COMMA = YES; 147 | CLANG_WARN_CONSTANT_CONVERSION = YES; 148 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 149 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 150 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 151 | CLANG_WARN_EMPTY_BODY = YES; 152 | CLANG_WARN_ENUM_CONVERSION = YES; 153 | CLANG_WARN_INFINITE_RECURSION = YES; 154 | CLANG_WARN_INT_CONVERSION = YES; 155 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 156 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 157 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 158 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 159 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 160 | CLANG_WARN_STRICT_PROTOTYPES = YES; 161 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 162 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 163 | CLANG_WARN_UNREACHABLE_CODE = YES; 164 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 165 | CODE_SIGN_IDENTITY = "-"; 166 | COPY_PHASE_STRIP = NO; 167 | DEBUG_INFORMATION_FORMAT = dwarf; 168 | ENABLE_STRICT_OBJC_MSGSEND = YES; 169 | ENABLE_TESTABILITY = YES; 170 | GCC_C_LANGUAGE_STANDARD = gnu11; 171 | GCC_DYNAMIC_NO_PIC = NO; 172 | GCC_NO_COMMON_BLOCKS = YES; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | GCC_PREPROCESSOR_DEFINITIONS = ( 175 | "DEBUG=1", 176 | "$(inherited)", 177 | ); 178 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 179 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 180 | GCC_WARN_UNDECLARED_SELECTOR = YES; 181 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 182 | GCC_WARN_UNUSED_FUNCTION = YES; 183 | GCC_WARN_UNUSED_VARIABLE = YES; 184 | MACOSX_DEPLOYMENT_TARGET = 10.13; 185 | MTL_ENABLE_DEBUG_INFO = YES; 186 | ONLY_ACTIVE_ARCH = YES; 187 | SDKROOT = macosx; 188 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 189 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 190 | }; 191 | name = Debug; 192 | }; 193 | BF9B2BE7207C5514006F945A /* Release */ = { 194 | isa = XCBuildConfiguration; 195 | buildSettings = { 196 | ALWAYS_SEARCH_USER_PATHS = NO; 197 | CLANG_ANALYZER_NONNULL = YES; 198 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_ENABLE_MODULES = YES; 202 | CLANG_ENABLE_OBJC_ARC = YES; 203 | CLANG_ENABLE_OBJC_WEAK = YES; 204 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 205 | CLANG_WARN_BOOL_CONVERSION = YES; 206 | CLANG_WARN_COMMA = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 209 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 210 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 211 | CLANG_WARN_EMPTY_BODY = YES; 212 | CLANG_WARN_ENUM_CONVERSION = YES; 213 | CLANG_WARN_INFINITE_RECURSION = YES; 214 | CLANG_WARN_INT_CONVERSION = YES; 215 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 216 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 217 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 218 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 219 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 220 | CLANG_WARN_STRICT_PROTOTYPES = YES; 221 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 222 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 223 | CLANG_WARN_UNREACHABLE_CODE = YES; 224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 225 | CODE_SIGN_IDENTITY = "-"; 226 | COPY_PHASE_STRIP = NO; 227 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 228 | ENABLE_NS_ASSERTIONS = NO; 229 | ENABLE_STRICT_OBJC_MSGSEND = YES; 230 | GCC_C_LANGUAGE_STANDARD = gnu11; 231 | GCC_NO_COMMON_BLOCKS = YES; 232 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 233 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 234 | GCC_WARN_UNDECLARED_SELECTOR = YES; 235 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 236 | GCC_WARN_UNUSED_FUNCTION = YES; 237 | GCC_WARN_UNUSED_VARIABLE = YES; 238 | MACOSX_DEPLOYMENT_TARGET = 10.13; 239 | MTL_ENABLE_DEBUG_INFO = NO; 240 | SDKROOT = macosx; 241 | SWIFT_COMPILATION_MODE = wholemodule; 242 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 243 | }; 244 | name = Release; 245 | }; 246 | BF9B2BE9207C5514006F945A /* Debug */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | CODE_SIGN_STYLE = Automatic; 250 | PRODUCT_NAME = "$(TARGET_NAME)"; 251 | SWIFT_VERSION = 4.0; 252 | }; 253 | name = Debug; 254 | }; 255 | BF9B2BEA207C5514006F945A /* Release */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | CODE_SIGN_STYLE = Automatic; 259 | PRODUCT_NAME = "$(TARGET_NAME)"; 260 | SWIFT_VERSION = 4.0; 261 | }; 262 | name = Release; 263 | }; 264 | /* End XCBuildConfiguration section */ 265 | 266 | /* Begin XCConfigurationList section */ 267 | BF9B2BDC207C5514006F945A /* Build configuration list for PBXProject "Swift-Demo" */ = { 268 | isa = XCConfigurationList; 269 | buildConfigurations = ( 270 | BF9B2BE6207C5514006F945A /* Debug */, 271 | BF9B2BE7207C5514006F945A /* Release */, 272 | ); 273 | defaultConfigurationIsVisible = 0; 274 | defaultConfigurationName = Release; 275 | }; 276 | BF9B2BE8207C5514006F945A /* Build configuration list for PBXNativeTarget "Swift-Demo" */ = { 277 | isa = XCConfigurationList; 278 | buildConfigurations = ( 279 | BF9B2BE9207C5514006F945A /* Debug */, 280 | BF9B2BEA207C5514006F945A /* Release */, 281 | ); 282 | defaultConfigurationIsVisible = 0; 283 | defaultConfigurationName = Release; 284 | }; 285 | /* End XCConfigurationList section */ 286 | }; 287 | rootObject = BF9B2BD9207C5514006F945A /* Project object */; 288 | } 289 | -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo.xcodeproj/project.xcworkspace/xcuserdata/vincent.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzso/IDCardNumber-Validator/ef67f69f8da64129036f37c8adf67c481c8f3be5/Swift-Demo/Swift-Demo.xcodeproj/project.xcworkspace/xcuserdata/vincent.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo.xcodeproj/xcuserdata/vincent.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Swift-Demo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | Swift-Demo.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo/String+Validators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Validators.swift 3 | // Swift-Demo 4 | // 5 | // Created by Zhishen Wen on 2018/4/10. 6 | // Copyright © 2018 0xa6a. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | extension String { 13 | /// 验证身份证号码 14 | func validateIDCardNumber() -> Bool { 15 | struct Static { 16 | fileprivate static let predicate: NSPredicate = { 17 | let regex = "(^\\d{15}$)|(^\\d{17}([0-9]|X)$)" 18 | let predicate = NSPredicate(format: "SELF MATCHES %@", argumentArray: [regex]) 19 | return predicate 20 | }() 21 | fileprivate static let provinceCodes = [ 22 | "11", "12", "13", "14", "15", 23 | "21", "22", "23", 24 | "31", "32", "33", "34", "35", "36", "37", 25 | "41", "42", "43", "44", "45", "46", 26 | "50", "51", "52", "53", "54", 27 | "61", "62", "63", "64", "65", 28 | "71", "81", "82", "91"] 29 | } 30 | // 初步验证 31 | guard Static.predicate.evaluate(with: self) else { 32 | return false 33 | } 34 | // 验证省份代码。如果需要更精确的话,可以把前六位行政区划代码都列举出来比较。 35 | let provinceCode = String(self.prefix(2)) 36 | guard Static.provinceCodes.contains(provinceCode) else { 37 | return false 38 | } 39 | if self.count == 15 { 40 | return self.validate15DigitsIDCardNumber() 41 | } else { 42 | return self.validate18DigitsIDCardNumber() 43 | } 44 | } 45 | 46 | /// 15位身份证号码验证。 47 | // 6位行政区划代码 + 6位出生日期码(yyMMdd) + 3位顺序码 48 | private func validate15DigitsIDCardNumber() -> Bool { 49 | let birthdate = "19\(self.substring(from: 6, to: 11)!)" 50 | return birthdate.validateBirthDate() 51 | } 52 | 53 | /// 18位身份证号码验证。 54 | // 6位行政区划代码 + 8位出生日期码(yyyyMMdd) + 3位顺序码 + 1位校验码 55 | private func validate18DigitsIDCardNumber() -> Bool { 56 | let birthdate = self.substring(from: 6, to: 13)! 57 | guard birthdate.validateBirthDate() else { 58 | return false 59 | } 60 | struct Static { 61 | static let weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2] 62 | static let validationCodes = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"] 63 | } 64 | // 验证校验位 65 | let digits = self.substring(from: 0, to: 16)!.map { Int("\($0)")! } 66 | var sum = 0 67 | for i in 0.. Bool { 76 | struct Static { 77 | static let dateFormatter: DateFormatter = { 78 | let dateFormatter = DateFormatter() 79 | dateFormatter.dateFormat = "yyyyMMdd" 80 | return dateFormatter 81 | }() 82 | } 83 | if let _ = Static.dateFormatter.date(from: self) { 84 | return true 85 | } else { 86 | return false 87 | } 88 | } 89 | 90 | private func substring(from: Int, to: Int) -> String? { 91 | guard to >= from && from >= 0 && to < count else { 92 | return nil 93 | } 94 | let startIdx = self.index(startIndex, offsetBy: from) 95 | let endIdx = self.index(startIndex, offsetBy: to) 96 | return String(self[startIdx...endIdx]) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Swift-Demo/Swift-Demo/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // Swift-Demo 4 | // 5 | // Created by Zhishen Wen on 2018/4/10. 6 | // Copyright © 2018 0xa6a. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | print("130984198104262278".validateIDCardNumber()) 12 | print("13098419810426227X".validateIDCardNumber()) 13 | print("230984198104262278".validateIDCardNumber()) 14 | print("123456080808657".validateIDCardNumber()) 15 | --------------------------------------------------------------------------------