├── .swift-version ├── LICENSE ├── PPGetAddressBookSwift.podspec ├── PPGetAddressBookSwift.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── AndyPang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── YiAi.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── duoyi.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── AndyPang.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── PPGetAddressBookSwift.xcscheme │ │ └── xcschememanagement.plist │ ├── YiAi.xcuserdatad │ └── xcschemes │ │ ├── PPGetAddressBookSwift.xcscheme │ │ └── xcschememanagement.plist │ └── duoyi.xcuserdatad │ └── xcschemes │ ├── PPGetAddressBookSwift.xcscheme │ └── xcschememanagement.plist ├── PPGetAddressBookSwift ├── AddressBookVC1.swift ├── AddressBookVC2.swift ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── defult.imageset │ │ ├── Contents.json │ │ └── defult.png ├── Base.lproj │ └── LaunchScreen.storyboard ├── Info.plist ├── PPGetAddressBookSwift │ ├── PPAddressBookHandle.swift │ ├── PPGetAddressBook.swift │ └── PPPersonModel.swift └── ViewController.swift ├── PPGetAddressBookSwiftTests ├── Info.plist └── PPGetAddressBookSwiftTests.swift └── README.md /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 jkpang 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 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'PPGetAddressBookSwift' 3 | s.version = "0.2.0" 4 | s.summary = "一行代码极速获取按A~Z分组精准排序的通讯录联系人 Swift版( 已处理姓名所有字符的排序问题)" 5 | 6 | s.homepage = "https://github.com/jkpang/PPGetAddressBookSwift.git" 7 | 8 | s.license = { :type => "MIT", :file => "LICENSE" } 9 | 10 | s.author = { "jkpang" => "jkpang@outlook.com" } 11 | 12 | s.platform = :ios, "8.0" 13 | 14 | s.source = { :git => "https://github.com/jkpang/PPGetAddressBookSwift.git", :tag => s.version.to_s } 15 | 16 | s.source_files = "PPGetAddressBookSwift/PPGetAddressBookSwift/*.{swift}" 17 | 18 | s.requires_arc = true 19 | 20 | end 21 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 22106B221D995F4700D16803 /* .swift-version in Resources */ = {isa = PBXBuildFile; fileRef = 22106B211D995F4700D16803 /* .swift-version */; }; 11 | 228DE38D1D8C46DA00D7353E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE38C1D8C46DA00D7353E /* AppDelegate.swift */; }; 12 | 228DE38F1D8C46DA00D7353E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE38E1D8C46DA00D7353E /* ViewController.swift */; }; 13 | 228DE3941D8C46DA00D7353E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 228DE3931D8C46DA00D7353E /* Assets.xcassets */; }; 14 | 228DE3971D8C46DA00D7353E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 228DE3951D8C46DA00D7353E /* LaunchScreen.storyboard */; }; 15 | 228DE3A21D8C46DB00D7353E /* PPGetAddressBookSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE3A11D8C46DB00D7353E /* PPGetAddressBookSwiftTests.swift */; }; 16 | 228DE3B01D8C46E200D7353E /* PPAddressBookHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE3AD1D8C46E200D7353E /* PPAddressBookHandle.swift */; }; 17 | 228DE3B11D8C46E200D7353E /* PPGetAddressBook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE3AE1D8C46E200D7353E /* PPGetAddressBook.swift */; }; 18 | 228DE3B21D8C46E200D7353E /* PPPersonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE3AF1D8C46E200D7353E /* PPPersonModel.swift */; }; 19 | 228DE3BE1D8CF4A000D7353E /* AddressBookVC1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE3BD1D8CF4A000D7353E /* AddressBookVC1.swift */; }; 20 | 228DE3C01D8D12E700D7353E /* AddressBookVC2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 228DE3BF1D8D12E700D7353E /* AddressBookVC2.swift */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 228DE39E1D8C46DB00D7353E /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 228DE3811D8C46DA00D7353E /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 228DE3881D8C46DA00D7353E; 29 | remoteInfo = PPGetAddressBookSwift; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 22106B211D995F4700D16803 /* .swift-version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = ".swift-version"; path = "../.swift-version"; sourceTree = ""; }; 35 | 228DE3891D8C46DA00D7353E /* PPGetAddressBookSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PPGetAddressBookSwift.app; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 228DE38C1D8C46DA00D7353E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 228DE38E1D8C46DA00D7353E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 38 | 228DE3931D8C46DA00D7353E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../PPGetAddressBookSwift/Assets.xcassets; sourceTree = ""; }; 39 | 228DE3961D8C46DA00D7353E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 40 | 228DE3981D8C46DA00D7353E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../PPGetAddressBookSwift/Info.plist; sourceTree = ""; }; 41 | 228DE39D1D8C46DB00D7353E /* PPGetAddressBookSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PPGetAddressBookSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 228DE3A11D8C46DB00D7353E /* PPGetAddressBookSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPGetAddressBookSwiftTests.swift; sourceTree = ""; }; 43 | 228DE3A31D8C46DB00D7353E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | 228DE3AD1D8C46E200D7353E /* PPAddressBookHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PPAddressBookHandle.swift; sourceTree = ""; }; 45 | 228DE3AE1D8C46E200D7353E /* PPGetAddressBook.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PPGetAddressBook.swift; sourceTree = ""; }; 46 | 228DE3AF1D8C46E200D7353E /* PPPersonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PPPersonModel.swift; sourceTree = ""; }; 47 | 228DE3BD1D8CF4A000D7353E /* AddressBookVC1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressBookVC1.swift; sourceTree = ""; }; 48 | 228DE3BF1D8D12E700D7353E /* AddressBookVC2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressBookVC2.swift; sourceTree = ""; }; 49 | /* End PBXFileReference section */ 50 | 51 | /* Begin PBXFrameworksBuildPhase section */ 52 | 228DE3861D8C46DA00D7353E /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | 228DE39A1D8C46DB00D7353E /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 228DE3801D8C46DA00D7353E = { 70 | isa = PBXGroup; 71 | children = ( 72 | 228DE38B1D8C46DA00D7353E /* PPGetAddressBookSwift */, 73 | 228DE3A01D8C46DB00D7353E /* PPGetAddressBookSwiftTests */, 74 | 228DE38A1D8C46DA00D7353E /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 228DE38A1D8C46DA00D7353E /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 228DE3891D8C46DA00D7353E /* PPGetAddressBookSwift.app */, 82 | 228DE39D1D8C46DB00D7353E /* PPGetAddressBookSwiftTests.xctest */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 228DE38B1D8C46DA00D7353E /* PPGetAddressBookSwift */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 22106B211D995F4700D16803 /* .swift-version */, 91 | 228DE3AC1D8C46E200D7353E /* PPGetAddressBookSwift */, 92 | 228DE38C1D8C46DA00D7353E /* AppDelegate.swift */, 93 | 228DE38E1D8C46DA00D7353E /* ViewController.swift */, 94 | 228DE3BD1D8CF4A000D7353E /* AddressBookVC1.swift */, 95 | 228DE3BF1D8D12E700D7353E /* AddressBookVC2.swift */, 96 | ); 97 | path = PPGetAddressBookSwift; 98 | sourceTree = ""; 99 | }; 100 | 228DE3A01D8C46DB00D7353E /* PPGetAddressBookSwiftTests */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 228DE3931D8C46DA00D7353E /* Assets.xcassets */, 104 | 228DE3951D8C46DA00D7353E /* LaunchScreen.storyboard */, 105 | 228DE3981D8C46DA00D7353E /* Info.plist */, 106 | 228DE3A11D8C46DB00D7353E /* PPGetAddressBookSwiftTests.swift */, 107 | 228DE3A31D8C46DB00D7353E /* Info.plist */, 108 | ); 109 | path = PPGetAddressBookSwiftTests; 110 | sourceTree = ""; 111 | }; 112 | 228DE3AC1D8C46E200D7353E /* PPGetAddressBookSwift */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 228DE3AE1D8C46E200D7353E /* PPGetAddressBook.swift */, 116 | 228DE3AD1D8C46E200D7353E /* PPAddressBookHandle.swift */, 117 | 228DE3AF1D8C46E200D7353E /* PPPersonModel.swift */, 118 | ); 119 | path = PPGetAddressBookSwift; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 228DE3881D8C46DA00D7353E /* PPGetAddressBookSwift */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 228DE3A61D8C46DB00D7353E /* Build configuration list for PBXNativeTarget "PPGetAddressBookSwift" */; 128 | buildPhases = ( 129 | 228DE3851D8C46DA00D7353E /* Sources */, 130 | 228DE3861D8C46DA00D7353E /* Frameworks */, 131 | 228DE3871D8C46DA00D7353E /* Resources */, 132 | ); 133 | buildRules = ( 134 | ); 135 | dependencies = ( 136 | ); 137 | name = PPGetAddressBookSwift; 138 | productName = PPGetAddressBookSwift; 139 | productReference = 228DE3891D8C46DA00D7353E /* PPGetAddressBookSwift.app */; 140 | productType = "com.apple.product-type.application"; 141 | }; 142 | 228DE39C1D8C46DB00D7353E /* PPGetAddressBookSwiftTests */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 228DE3A91D8C46DB00D7353E /* Build configuration list for PBXNativeTarget "PPGetAddressBookSwiftTests" */; 145 | buildPhases = ( 146 | 228DE3991D8C46DB00D7353E /* Sources */, 147 | 228DE39A1D8C46DB00D7353E /* Frameworks */, 148 | 228DE39B1D8C46DB00D7353E /* Resources */, 149 | ); 150 | buildRules = ( 151 | ); 152 | dependencies = ( 153 | 228DE39F1D8C46DB00D7353E /* PBXTargetDependency */, 154 | ); 155 | name = PPGetAddressBookSwiftTests; 156 | productName = PPGetAddressBookSwiftTests; 157 | productReference = 228DE39D1D8C46DB00D7353E /* PPGetAddressBookSwiftTests.xctest */; 158 | productType = "com.apple.product-type.bundle.unit-test"; 159 | }; 160 | /* End PBXNativeTarget section */ 161 | 162 | /* Begin PBXProject section */ 163 | 228DE3811D8C46DA00D7353E /* Project object */ = { 164 | isa = PBXProject; 165 | attributes = { 166 | LastSwiftUpdateCheck = 0730; 167 | LastUpgradeCheck = 0800; 168 | ORGANIZATIONNAME = AndyPang; 169 | TargetAttributes = { 170 | 228DE3881D8C46DA00D7353E = { 171 | CreatedOnToolsVersion = 7.3.1; 172 | DevelopmentTeam = YY4NTQ7LN8; 173 | LastSwiftMigration = 0800; 174 | }; 175 | 228DE39C1D8C46DB00D7353E = { 176 | CreatedOnToolsVersion = 7.3.1; 177 | LastSwiftMigration = 0800; 178 | TestTargetID = 228DE3881D8C46DA00D7353E; 179 | }; 180 | }; 181 | }; 182 | buildConfigurationList = 228DE3841D8C46DA00D7353E /* Build configuration list for PBXProject "PPGetAddressBookSwift" */; 183 | compatibilityVersion = "Xcode 3.2"; 184 | developmentRegion = English; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | Base, 189 | ); 190 | mainGroup = 228DE3801D8C46DA00D7353E; 191 | productRefGroup = 228DE38A1D8C46DA00D7353E /* Products */; 192 | projectDirPath = ""; 193 | projectRoot = ""; 194 | targets = ( 195 | 228DE3881D8C46DA00D7353E /* PPGetAddressBookSwift */, 196 | 228DE39C1D8C46DB00D7353E /* PPGetAddressBookSwiftTests */, 197 | ); 198 | }; 199 | /* End PBXProject section */ 200 | 201 | /* Begin PBXResourcesBuildPhase section */ 202 | 228DE3871D8C46DA00D7353E /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | 228DE3971D8C46DA00D7353E /* LaunchScreen.storyboard in Resources */, 207 | 22106B221D995F4700D16803 /* .swift-version in Resources */, 208 | 228DE3941D8C46DA00D7353E /* Assets.xcassets in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | 228DE39B1D8C46DB00D7353E /* Resources */ = { 213 | isa = PBXResourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXResourcesBuildPhase section */ 220 | 221 | /* Begin PBXSourcesBuildPhase section */ 222 | 228DE3851D8C46DA00D7353E /* Sources */ = { 223 | isa = PBXSourcesBuildPhase; 224 | buildActionMask = 2147483647; 225 | files = ( 226 | 228DE3BE1D8CF4A000D7353E /* AddressBookVC1.swift in Sources */, 227 | 228DE38F1D8C46DA00D7353E /* ViewController.swift in Sources */, 228 | 228DE3C01D8D12E700D7353E /* AddressBookVC2.swift in Sources */, 229 | 228DE38D1D8C46DA00D7353E /* AppDelegate.swift in Sources */, 230 | 228DE3B21D8C46E200D7353E /* PPPersonModel.swift in Sources */, 231 | 228DE3B11D8C46E200D7353E /* PPGetAddressBook.swift in Sources */, 232 | 228DE3B01D8C46E200D7353E /* PPAddressBookHandle.swift in Sources */, 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | 228DE3991D8C46DB00D7353E /* Sources */ = { 237 | isa = PBXSourcesBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | 228DE3A21D8C46DB00D7353E /* PPGetAddressBookSwiftTests.swift in Sources */, 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | /* End PBXSourcesBuildPhase section */ 245 | 246 | /* Begin PBXTargetDependency section */ 247 | 228DE39F1D8C46DB00D7353E /* PBXTargetDependency */ = { 248 | isa = PBXTargetDependency; 249 | target = 228DE3881D8C46DA00D7353E /* PPGetAddressBookSwift */; 250 | targetProxy = 228DE39E1D8C46DB00D7353E /* PBXContainerItemProxy */; 251 | }; 252 | /* End PBXTargetDependency section */ 253 | 254 | /* Begin PBXVariantGroup section */ 255 | 228DE3951D8C46DA00D7353E /* LaunchScreen.storyboard */ = { 256 | isa = PBXVariantGroup; 257 | children = ( 258 | 228DE3961D8C46DA00D7353E /* Base */, 259 | ); 260 | name = LaunchScreen.storyboard; 261 | path = ../PPGetAddressBookSwift; 262 | sourceTree = ""; 263 | }; 264 | /* End PBXVariantGroup section */ 265 | 266 | /* Begin XCBuildConfiguration section */ 267 | 228DE3A41D8C46DB00D7353E /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ANALYZER_NONNULL = YES; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 279 | CLANG_WARN_EMPTY_BODY = YES; 280 | CLANG_WARN_ENUM_CONVERSION = YES; 281 | CLANG_WARN_INFINITE_RECURSION = YES; 282 | CLANG_WARN_INT_CONVERSION = YES; 283 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 284 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 285 | CLANG_WARN_UNREACHABLE_CODE = YES; 286 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 287 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 288 | COPY_PHASE_STRIP = NO; 289 | DEBUG_INFORMATION_FORMAT = dwarf; 290 | ENABLE_STRICT_OBJC_MSGSEND = YES; 291 | ENABLE_TESTABILITY = YES; 292 | GCC_C_LANGUAGE_STANDARD = gnu99; 293 | GCC_DYNAMIC_NO_PIC = NO; 294 | GCC_NO_COMMON_BLOCKS = YES; 295 | GCC_OPTIMIZATION_LEVEL = 0; 296 | GCC_PREPROCESSOR_DEFINITIONS = ( 297 | "DEBUG=1", 298 | "$(inherited)", 299 | ); 300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 301 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 302 | GCC_WARN_UNDECLARED_SELECTOR = YES; 303 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 304 | GCC_WARN_UNUSED_FUNCTION = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 307 | MTL_ENABLE_DEBUG_INFO = YES; 308 | ONLY_ACTIVE_ARCH = YES; 309 | SDKROOT = iphoneos; 310 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 311 | TARGETED_DEVICE_FAMILY = "1,2"; 312 | }; 313 | name = Debug; 314 | }; 315 | 228DE3A51D8C46DB00D7353E /* Release */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | ALWAYS_SEARCH_USER_PATHS = NO; 319 | CLANG_ANALYZER_NONNULL = YES; 320 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 321 | CLANG_CXX_LIBRARY = "libc++"; 322 | CLANG_ENABLE_MODULES = YES; 323 | CLANG_ENABLE_OBJC_ARC = YES; 324 | CLANG_WARN_BOOL_CONVERSION = YES; 325 | CLANG_WARN_CONSTANT_CONVERSION = YES; 326 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 327 | CLANG_WARN_EMPTY_BODY = YES; 328 | CLANG_WARN_ENUM_CONVERSION = YES; 329 | CLANG_WARN_INFINITE_RECURSION = YES; 330 | CLANG_WARN_INT_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 349 | MTL_ENABLE_DEBUG_INFO = NO; 350 | SDKROOT = iphoneos; 351 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 352 | TARGETED_DEVICE_FAMILY = "1,2"; 353 | VALIDATE_PRODUCT = YES; 354 | }; 355 | name = Release; 356 | }; 357 | 228DE3A71D8C46DB00D7353E /* Debug */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 361 | DEVELOPMENT_TEAM = YY4NTQ7LN8; 362 | INFOPLIST_FILE = PPGetAddressBookSwift/Info.plist; 363 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 364 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 365 | PRODUCT_BUNDLE_IDENTIFIER = com.jkpang.PPGetAddressBookSwift; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | SDKROOT = iphoneos; 368 | SWIFT_VERSION = 3.0; 369 | }; 370 | name = Debug; 371 | }; 372 | 228DE3A81D8C46DB00D7353E /* Release */ = { 373 | isa = XCBuildConfiguration; 374 | buildSettings = { 375 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 376 | DEVELOPMENT_TEAM = YY4NTQ7LN8; 377 | INFOPLIST_FILE = PPGetAddressBookSwift/Info.plist; 378 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 379 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 380 | PRODUCT_BUNDLE_IDENTIFIER = com.jkpang.PPGetAddressBookSwift; 381 | PRODUCT_NAME = "$(TARGET_NAME)"; 382 | SDKROOT = iphoneos; 383 | SWIFT_VERSION = 3.0; 384 | }; 385 | name = Release; 386 | }; 387 | 228DE3AA1D8C46DB00D7353E /* Debug */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | BUNDLE_LOADER = "$(TEST_HOST)"; 391 | INFOPLIST_FILE = PPGetAddressBookSwiftTests/Info.plist; 392 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 393 | PRODUCT_BUNDLE_IDENTIFIER = com.jkpang.PPGetAddressBookSwiftTests; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | SWIFT_VERSION = 3.0; 396 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PPGetAddressBookSwift.app/PPGetAddressBookSwift"; 397 | }; 398 | name = Debug; 399 | }; 400 | 228DE3AB1D8C46DB00D7353E /* Release */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | BUNDLE_LOADER = "$(TEST_HOST)"; 404 | INFOPLIST_FILE = PPGetAddressBookSwiftTests/Info.plist; 405 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 406 | PRODUCT_BUNDLE_IDENTIFIER = com.jkpang.PPGetAddressBookSwiftTests; 407 | PRODUCT_NAME = "$(TARGET_NAME)"; 408 | SWIFT_VERSION = 3.0; 409 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PPGetAddressBookSwift.app/PPGetAddressBookSwift"; 410 | }; 411 | name = Release; 412 | }; 413 | /* End XCBuildConfiguration section */ 414 | 415 | /* Begin XCConfigurationList section */ 416 | 228DE3841D8C46DA00D7353E /* Build configuration list for PBXProject "PPGetAddressBookSwift" */ = { 417 | isa = XCConfigurationList; 418 | buildConfigurations = ( 419 | 228DE3A41D8C46DB00D7353E /* Debug */, 420 | 228DE3A51D8C46DB00D7353E /* Release */, 421 | ); 422 | defaultConfigurationIsVisible = 0; 423 | defaultConfigurationName = Release; 424 | }; 425 | 228DE3A61D8C46DB00D7353E /* Build configuration list for PBXNativeTarget "PPGetAddressBookSwift" */ = { 426 | isa = XCConfigurationList; 427 | buildConfigurations = ( 428 | 228DE3A71D8C46DB00D7353E /* Debug */, 429 | 228DE3A81D8C46DB00D7353E /* Release */, 430 | ); 431 | defaultConfigurationIsVisible = 0; 432 | defaultConfigurationName = Release; 433 | }; 434 | 228DE3A91D8C46DB00D7353E /* Build configuration list for PBXNativeTarget "PPGetAddressBookSwiftTests" */ = { 435 | isa = XCConfigurationList; 436 | buildConfigurations = ( 437 | 228DE3AA1D8C46DB00D7353E /* Debug */, 438 | 228DE3AB1D8C46DB00D7353E /* Release */, 439 | ); 440 | defaultConfigurationIsVisible = 0; 441 | defaultConfigurationName = Release; 442 | }; 443 | /* End XCConfigurationList section */ 444 | }; 445 | rootObject = 228DE3811D8C46DA00D7353E /* Project object */; 446 | } 447 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/project.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPGetAddressBookSwift/eaa8de8cbdccc0a33216d3bb16c6eebd8bcbc048/PPGetAddressBookSwift.xcodeproj/project.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/project.xcworkspace/xcuserdata/YiAi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPGetAddressBookSwift/eaa8de8cbdccc0a33216d3bb16c6eebd8bcbc048/PPGetAddressBookSwift.xcodeproj/project.xcworkspace/xcuserdata/YiAi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/project.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPGetAddressBookSwift/eaa8de8cbdccc0a33216d3bb16c6eebd8bcbc048/PPGetAddressBookSwift.xcodeproj/project.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcschemes/PPGetAddressBookSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPGetAddressBookSwift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 228DE3881D8C46DA00D7353E 16 | 17 | primary 18 | 19 | 20 | 228DE39C1D8C46DB00D7353E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/YiAi.xcuserdatad/xcschemes/PPGetAddressBookSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/YiAi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPGetAddressBookSwift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 228DE3881D8C46DA00D7353E 16 | 17 | primary 18 | 19 | 20 | 228DE39C1D8C46DB00D7353E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/duoyi.xcuserdatad/xcschemes/PPGetAddressBookSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift.xcodeproj/xcuserdata/duoyi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPGetAddressBookSwift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 228DE3881D8C46DA00D7353E 16 | 17 | primary 18 | 19 | 20 | 228DE39C1D8C46DB00D7353E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/AddressBookVC1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressBookVC2.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/17. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AddressBookVC1: UIViewController { 12 | 13 | var tableView: UITableView! 14 | /// 所有联系人信息的字典 15 | var addressBookSouce = [String:[PPPersonModel]]() 16 | /// 所有分组的key值 17 | var keysArray = [String]() 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | 22 | navigationItem.title = "A~Z联系人分组排序" 23 | 24 | tableView = UITableView.init(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height), style: UITableViewStyle.plain) 25 | tableView.dataSource = self 26 | tableView.delegate = self 27 | tableView.rowHeight = 60.0 28 | view.addSubview(tableView) 29 | 30 | 31 | // MARK: - 获取A~Z分组顺序的通讯录 32 | PPGetAddressBook.getOrderAddressBook(addressBookInfo: { (addressBookDict, nameKeys) in 33 | 34 | self.addressBookSouce = addressBookDict // 所有联系人信息的字典 35 | self.keysArray = nameKeys // 所有分组的key值 36 | 37 | // 刷新tableView 38 | self.tableView.reloadData() 39 | 40 | }, authorizationFailure: { 41 | 42 | let alertView = UIAlertController.init(title: "提示", message: "请在iPhone的“设置-隐私-通讯录”选项中,允许PPAddressBookSwift访问您的通讯录", preferredStyle: UIAlertControllerStyle.alert) 43 | let confirm = UIAlertAction.init(title: "知道啦", style: UIAlertActionStyle.cancel, handler:nil) 44 | alertView.addAction(confirm) 45 | self.present(alertView, animated: true, completion: nil) 46 | }) 47 | 48 | } 49 | 50 | deinit{ 51 | print("挂了") 52 | } 53 | 54 | } 55 | 56 | extension AddressBookVC1: UITableViewDelegate, UITableViewDataSource { 57 | 58 | func numberOfSections(in tableView: UITableView) -> Int { 59 | return keysArray.count 60 | } 61 | 62 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 63 | 64 | let key = keysArray[section] 65 | let array = addressBookSouce[key] 66 | 67 | return (array?.count)! 68 | } 69 | 70 | func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 71 | return keysArray[section] 72 | } 73 | 74 | // 右侧索引 75 | func sectionIndexTitles(for tableView: UITableView) -> [String]? { 76 | return keysArray 77 | } 78 | 79 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 80 | var cell = tableView.dequeueReusableCell(withIdentifier: "cell") 81 | if cell == nil { 82 | 83 | cell = UITableViewCell.init(style: UITableViewCellStyle.default, reuseIdentifier: "cell") 84 | } 85 | 86 | let modelArray = addressBookSouce[keysArray[indexPath.section]] 87 | let model = modelArray![indexPath.row] 88 | 89 | 90 | cell?.textLabel?.text = model.name 91 | cell?.imageView?.image = model.headerImage ?? UIImage.init(named: "defult") 92 | cell?.imageView?.layer.cornerRadius = 30 93 | cell?.imageView?.clipsToBounds = true 94 | 95 | return cell! 96 | } 97 | 98 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 99 | 100 | let modelArray = addressBookSouce[keysArray[indexPath.section]] 101 | let model = modelArray![indexPath.row] 102 | 103 | let alertViewVC = UIAlertController.init(title: model.name, message:"\(model.mobileArray)", preferredStyle: UIAlertControllerStyle.alert) 104 | let confirm = UIAlertAction.init(title: "确定", style: UIAlertActionStyle.cancel, handler:nil) 105 | alertViewVC.addAction(confirm) 106 | self.present(alertViewVC, animated: true, completion: nil) 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/AddressBookVC2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressBookVC2.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/17. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AddressBookVC2: UIViewController { 12 | 13 | var tableView: UITableView! 14 | 15 | /// 联系人模型数组 16 | var dataSourceArray = [PPPersonModel]() 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | 21 | navigationItem.title = "原始顺序" 22 | 23 | tableView = UITableView.init(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)) 24 | 25 | tableView.dataSource = self 26 | tableView.delegate = self 27 | tableView.rowHeight = 60.0 28 | view.addSubview(tableView) 29 | 30 | // MARK: - 获取原始顺序联系人的模型数组 31 | PPGetAddressBook.getOriginalAddressBook(addressBookArray: { (addressBookArray) in 32 | 33 | self.dataSourceArray = addressBookArray 34 | 35 | self.tableView.reloadData() 36 | 37 | }, authorizationFailure: { 38 | 39 | let alertViewVC = UIAlertController.init(title: "提示", message: "请在iPhone的“设置-隐私-通讯录”选项中,允许PPAddressBookSwift访问您的通讯录", preferredStyle: UIAlertControllerStyle.alert) 40 | let confirm = UIAlertAction.init(title: "知道啦", style: UIAlertActionStyle.cancel, handler:nil) 41 | alertViewVC.addAction(confirm) 42 | self.present(alertViewVC, animated: true, completion: nil) 43 | }) 44 | 45 | } 46 | 47 | deinit{ 48 | print("挂了") 49 | } 50 | } 51 | 52 | extension AddressBookVC2: UITableViewDelegate, UITableViewDataSource { 53 | 54 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 55 | 56 | return dataSourceArray.count 57 | } 58 | 59 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 60 | 61 | var cell = tableView.dequeueReusableCell(withIdentifier: "cell") 62 | if cell == nil { 63 | 64 | cell = UITableViewCell.init(style: UITableViewCellStyle.default, reuseIdentifier: "cell") 65 | } 66 | 67 | let model = dataSourceArray[indexPath.row] 68 | 69 | cell?.textLabel?.text = model.name 70 | cell?.imageView?.image = model.headerImage ?? UIImage.init(named: "defult") 71 | cell?.imageView?.layer.cornerRadius = 30 72 | cell?.imageView?.clipsToBounds = true 73 | return cell! 74 | } 75 | 76 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 77 | 78 | let model = dataSourceArray[indexPath.row] 79 | 80 | let alertViewVC = UIAlertController.init(title: model.name, message:"\(model.mobileArray)", preferredStyle: UIAlertControllerStyle.alert) 81 | let confirm = UIAlertAction.init(title: "确定", style: UIAlertActionStyle.cancel, handler:nil) 82 | alertViewVC.addAction(confirm) 83 | self.present(alertViewVC, animated: true, completion: nil) 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/16. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | 20 | window = UIWindow(frame: UIScreen.main.bounds) 21 | 22 | PPGetAddressBook.requestAddressBookAuthorization(); 23 | 24 | let rootVC = ViewController() 25 | let naviVC = UINavigationController.init(rootViewController: rootVC) 26 | 27 | window?.rootViewController = naviVC 28 | window?.makeKeyAndVisible() 29 | 30 | return true 31 | } 32 | 33 | func applicationWillResignActive(_ application: UIApplication) { 34 | // 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. 35 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 36 | } 37 | 38 | func applicationDidEnterBackground(_ application: UIApplication) { 39 | // 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. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | func applicationWillEnterForeground(_ application: UIApplication) { 44 | // 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. 45 | } 46 | 47 | func applicationDidBecomeActive(_ application: UIApplication) { 48 | // 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. 49 | } 50 | 51 | func applicationWillTerminate(_ application: UIApplication) { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/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 | } -------------------------------------------------------------------------------- /PPGetAddressBookSwift/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PPGetAddressBookSwift/Assets.xcassets/defult.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "defult.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PPGetAddressBookSwift/Assets.xcassets/defult.imageset/defult.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPGetAddressBookSwift/eaa8de8cbdccc0a33216d3bb16c6eebd8bcbc048/PPGetAddressBookSwift/Assets.xcassets/defult.imageset/defult.png -------------------------------------------------------------------------------- /PPGetAddressBookSwift/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 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSContactsUsageDescription 6 | 允许程序访问您的通讯录 7 | CFBundleDevelopmentRegion 8 | en 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 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/PPGetAddressBookSwift/PPAddressBookHandle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PPAddressBookHandle.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/16. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPGetAddressBookSwift 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * PS:PPGetAddressBookSwift的Objective-C版本: 23 | * https://github.com/jkpang/PPGetAddressBook 24 | * 25 | * 如果 PPGetAddressBookSwift 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 26 | ********************************************************************************* 27 | */ 28 | 29 | import UIKit 30 | import AddressBook 31 | import Contacts 32 | 33 | /// 一个联系人信息模型的闭包 34 | public typealias PPPersonModelClosure = (_ model: PPPersonModel)->() 35 | /// 授权失败的闭包 36 | public typealias AuthorizationFailure = ()->() 37 | 38 | 39 | class PPAddressBookHandle { 40 | 41 | func requestAuthorizationWithSuccessClosure(success: @escaping ()->()) { 42 | 43 | if #available(iOS 9.0, *) { 44 | 45 | if CNContactStore.authorizationStatus(for: CNEntityType.contacts) == CNAuthorizationStatus.authorized { 46 | return 47 | } 48 | contactStore.requestAccess(for: .contacts, completionHandler: { (granted, error) in 49 | 50 | if granted { 51 | success() ; print("授权成功") 52 | } else { 53 | print("授权失败") 54 | } 55 | }) 56 | 57 | 58 | } else { 59 | 60 | // 1.获取授权的状态 61 | let status = ABAddressBookGetAuthorizationStatus() 62 | // 2.判断授权状态,如果是未决定状态,才需要请求 63 | if status == ABAuthorizationStatus.notDetermined { 64 | // 3.创建通讯录进行授权 65 | ABAddressBookRequestAccessWithCompletion(addressBook, { (granted, error) in 66 | if granted { 67 | success() ; print("授权成功") 68 | }else { 69 | print("授权失败") 70 | } 71 | }) 72 | 73 | } 74 | 75 | } 76 | 77 | } 78 | 79 | func getAddressBookDataSource(personModel success: PPPersonModelClosure, authorizationFailure failure: AuthorizationFailure) { 80 | 81 | if #available(iOS 9.0, *) { 82 | // iOS9 之后 83 | getDataSourceFrom_IOS9_Later(personModel: success, authorizationFailure: failure) 84 | } else { 85 | // iOS9 之前 86 | getDataSourceFrom_IOS9_Ago(personModel: success, authorizationFailure: failure) 87 | } 88 | 89 | } 90 | 91 | 92 | // MARK: - IOS9之前获取通讯录的函数 93 | @available(iOS, introduced: 8.0, deprecated: 9.0) 94 | private func getDataSourceFrom_IOS9_Ago(personModel success: PPPersonModelClosure, authorizationFailure failure: AuthorizationFailure) { 95 | 96 | // 1.获取授状态 97 | let status = ABAddressBookGetAuthorizationStatus() 98 | 99 | // 2.如果没有授权,先执行授权失败的闭包后return 100 | if status != ABAuthorizationStatus.authorized { 101 | failure() 102 | return 103 | } 104 | 105 | // 3.创建通信录对象 106 | //let addressBook = ABAddressBookCreateWithOptions(nil, nil).takeRetainedValue() 107 | 108 | // 4.按照按姓名属性的排序规则从通信录对象中请求所有的联系人 109 | let recordRef = ABAddressBookCopyDefaultSource(addressBook).takeRetainedValue() 110 | let allPeopleArray = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, recordRef,ABPersonGetSortOrdering()).takeRetainedValue() as Array 111 | 112 | // 5.遍历所有联系人 113 | for personInfo in allPeopleArray { 114 | 115 | let model = PPPersonModel() 116 | 117 | // 5.1 获取到联系人 118 | let person = personInfo as ABRecord 119 | 120 | // 5.2 获取联系人全名 121 | let name = ABRecordCopyCompositeName(person)?.takeRetainedValue() as String? ?? "无名氏" 122 | model.name = name 123 | 124 | // 5.3 获取头像数据 125 | let imageData = ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail)?.takeRetainedValue() as NSData? ?? NSData.init() 126 | model.headerImage = UIImage.init(data: imageData as Data) 127 | 128 | // 5.4 遍历每个人的电话号码 129 | let phones = ABRecordCopyValue(person, kABPersonPhoneProperty).takeRetainedValue(); 130 | let phoneCount = ABMultiValueGetCount(phones) 131 | for i in 0.. Void in 171 | contacts.append(contact) 172 | }) 173 | 174 | } 175 | catch let error as NSError { 176 | print(error.localizedDescription) 177 | } 178 | // 3.1遍历联系人 179 | for contact in contacts { 180 | 181 | // 创建联系人模型 182 | let model = PPPersonModel() 183 | 184 | // 获取联系人全名 185 | model.name = CNContactFormatter.string(from: contact, style: CNContactFormatterStyle.fullName) ?? "无名氏" 186 | 187 | // 获取头像 188 | let imageData = contact.thumbnailImageData ?? NSData.init() as Data 189 | model.headerImage = UIImage.init(data: imageData) 190 | 191 | // 遍历一个人的所有电话号码 192 | for labelValue in contact.phoneNumbers { 193 | let phoneNumber = labelValue.value 194 | model.mobileArray.append(phoneNumber.stringValue) 195 | } 196 | 197 | // 将联系人模型回调出去 198 | success(model) 199 | } 200 | 201 | } 202 | 203 | 204 | /** 205 | 过滤指定字符串(可自定义添加自己过滤的字符串) 206 | */ 207 | func removeSpecialSubString(string: String) -> String { 208 | 209 | let resultString = string.replacingOccurrences(of: "+86", with: "") 210 | .replacingOccurrences(of: "-", with: "") 211 | .replacingOccurrences(of: "(", with: "") 212 | .replacingOccurrences(of: ")", with: "") 213 | .replacingOccurrences(of: " ", with: "") 214 | .replacingOccurrences(of: " ", with: "") 215 | 216 | return resultString; 217 | } 218 | 219 | 220 | // MARK: - lazy 221 | @available(iOS 9.0, *) 222 | lazy var contactStore: CNContactStore = { 223 | let contactStore = CNContactStore.init() 224 | return contactStore 225 | }() 226 | 227 | @available(iOS, introduced: 8.0, deprecated: 9.0) 228 | lazy var addressBook: ABAddressBook = { 229 | let addressBook = ABAddressBookCreateWithOptions(nil, nil).takeRetainedValue() 230 | return addressBook 231 | }() 232 | 233 | } 234 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/PPGetAddressBookSwift/PPGetAddressBook.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PPGetAddressBookSwift.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/16. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | /* 9 | ********************************************************************************* 10 | * 11 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 12 | * 13 | * 如果您在使用 PPGetAddressBookSwift 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 14 | * 时修复bug,解决问题. 15 | * 16 | * Weibo : jkpang-庞 17 | * Email : jkpang@outlook.com 18 | * QQ 群 : 323408051 19 | * GitHub: https://github.com/jkpang 20 | * 21 | * PS:PPGetAddressBookSwift的Objective-C版本: 22 | * https://github.com/jkpang/PPGetAddressBook 23 | * 24 | * 如果 PPGetAddressBookSwift 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 25 | ********************************************************************************* 26 | */ 27 | 28 | 29 | import Foundation 30 | import AddressBook 31 | import Contacts 32 | 33 | /// 获取原始顺序的所有联系人的闭包 34 | public typealias AddressBookArrayClosure = (_ addressBookArray: [PPPersonModel])->() 35 | /// 获取按A~Z顺序排列的所有联系人的闭包 36 | public typealias AddressBookDictClosure = (_ addressBookDict: [String:[PPPersonModel]], _ nameKeys: [String])->() 37 | 38 | 39 | public class PPGetAddressBook : NSObject { 40 | 41 | /** 42 | 请求用户是否授权APP访问通讯录的权限,建议在APPDeletegate.m中的didFinishLaunchingWithOptions方法中调用 43 | */ 44 | public class func requestAddressBookAuthorization() { 45 | 46 | PPAddressBookHandle().requestAuthorizationWithSuccessClosure { 47 | PPGetAddressBook.getOrderAddressBook(addressBookInfo: { (addressBookDict, nameKeys) in 48 | 49 | }, authorizationFailure: { 50 | 51 | }) 52 | } 53 | } 54 | override public class func initialize () { 55 | PPGetAddressBook.getOrderAddressBook(addressBookInfo: { (addressBookDict, nameKeys) in 56 | 57 | }, authorizationFailure: { 58 | 59 | }) 60 | } 61 | 62 | 63 | // MARK: - 获取原始顺序所有联系人 64 | public class func getOriginalAddressBook(addressBookArray success: @escaping AddressBookArrayClosure, authorizationFailure failure: @escaping AuthorizationFailure) { 65 | 66 | //开启一个子线程,将耗时操作放到异步串行队列 67 | let queue = DispatchQueue(label: "addressBook.array") 68 | queue.async { 69 | 70 | var modelArray = [PPPersonModel]() 71 | PPAddressBookHandle().getAddressBookDataSource(personModel: { (model) in 72 | 73 | //将单个联系人模型装进数组 74 | modelArray.append(model) 75 | 76 | }, authorizationFailure: { 77 | 78 | //将授权失败的信息回调到主线程 79 | DispatchQueue.main.async { 80 | failure() 81 | } 82 | }) 83 | 84 | // 将联系人数组回调到主线程 85 | DispatchQueue.main.async { 86 | success(modelArray) 87 | } 88 | 89 | } 90 | 91 | } 92 | 93 | // MARK: - 获取按A~Z顺序排列的所有联系人 94 | public class func getOrderAddressBook(addressBookInfo success: @escaping AddressBookDictClosure, authorizationFailure failure: @escaping AuthorizationFailure) { 95 | 96 | let queue = DispatchQueue(label:"addressBook.infoDict") 97 | queue.async { 98 | 99 | var addressBookDict = [String:[PPPersonModel]]() 100 | PPAddressBookHandle().getAddressBookDataSource(personModel: { (model) in 101 | 102 | // 获取到姓名的大写首字母 103 | let firstLetterString = getFirstLetterFromString(aString: model.name) 104 | 105 | if addressBookDict[firstLetterString] != nil { 106 | // swift的字典,如果对应的key在字典中没有,则会新增 107 | addressBookDict[firstLetterString]?.append(model) 108 | 109 | } else { 110 | var arrGroupNames = [model] 111 | arrGroupNames.append(model) 112 | addressBookDict[firstLetterString] = arrGroupNames 113 | } 114 | 115 | }, authorizationFailure: { 116 | 117 | //将授权失败的信息回调到主线程 118 | DispatchQueue.main.async { 119 | failure() 120 | } 121 | }) 122 | 123 | // 将addressBookDict字典中的所有Key值进行排序: A~Z 124 | var nameKeys = Array(addressBookDict.keys).sorted() 125 | 126 | // 将 "#" 排列在 A~Z 的后面 127 | if nameKeys.first == "#" { 128 | nameKeys.insert(nameKeys.first!, at: nameKeys.count) 129 | nameKeys.remove(at: 0); 130 | } 131 | 132 | // 将排序好的通讯录数据回调到主线程 133 | DispatchQueue.main.async { 134 | success(addressBookDict, nameKeys) 135 | } 136 | 137 | } 138 | } 139 | 140 | // MARK: - 获取联系人姓名首字母(传入汉字字符串, 返回大写拼音首字母) 141 | private class func getFirstLetterFromString(aString: String) -> (String) { 142 | 143 | // 注意,这里一定要转换成可变字符串 144 | let mutableString = NSMutableString.init(string: aString) 145 | // 将中文转换成带声调的拼音 146 | CFStringTransform(mutableString as CFMutableString, nil, kCFStringTransformToLatin, false) 147 | // 去掉声调(用此方法大大提高遍历的速度) 148 | let pinyinString = mutableString.folding(options: String.CompareOptions.diacriticInsensitive, locale: NSLocale.current) 149 | // 将拼音首字母装换成大写 150 | let strPinYin = polyphoneStringHandle(nameString: aString, pinyinString: pinyinString).uppercased() 151 | // 截取大写首字母 152 | let firstString = strPinYin.substring(to: strPinYin.index(strPinYin.startIndex, offsetBy:1)) 153 | // 判断姓名首位是否为大写字母 154 | let regexA = "^[A-Z]$" 155 | let predA = NSPredicate.init(format: "SELF MATCHES %@", regexA) 156 | return predA.evaluate(with: firstString) ? firstString : "#" 157 | } 158 | 159 | 160 | /// 多音字处理 161 | private class func polyphoneStringHandle(nameString:String, pinyinString:String) -> String { 162 | if nameString.hasPrefix("长") {return "chang"} 163 | if nameString.hasPrefix("沈") {return "shen"} 164 | if nameString.hasPrefix("厦") {return "xia"} 165 | if nameString.hasPrefix("地") {return "di"} 166 | if nameString.hasPrefix("重") {return "chong"} 167 | 168 | return pinyinString; 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/PPGetAddressBookSwift/PPPersonModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PPPersonModel.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/16. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPGetAddressBookSwift 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * PS:PPGetAddressBookSwift的Objective-C版本: 23 | * https://github.com/jkpang/PPGetAddressBook 24 | * 25 | * 如果 PPGetAddressBookSwift 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 26 | ********************************************************************************* 27 | */ 28 | 29 | import UIKit 30 | 31 | public class PPPersonModel { 32 | 33 | /// 联系人姓名 34 | public var name: String = "" 35 | 36 | /// 联系人电话数组,一个联系人可能存储多个号码 37 | public var mobileArray: [String] = [] 38 | 39 | /// 联系人头像 40 | public var headerImage: UIImage? 41 | 42 | } 43 | -------------------------------------------------------------------------------- /PPGetAddressBookSwift/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PPGetAddressBookSwift 4 | // 5 | // Created by AndyPang on 16/9/16. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPGetAddressBookSwift 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * PS:PPGetAddressBookSwift的Objective-C版本: 23 | * https://github.com/jkpang/PPGetAddressBook 24 | * 25 | * 如果 PPGetAddressBookSwift 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 26 | ********************************************************************************* 27 | */ 28 | 29 | import UIKit 30 | 31 | class ViewController: UIViewController { 32 | 33 | var tableView: UITableView! 34 | 35 | let dateSource = ["A~Z顺序排序","原始顺序"] 36 | 37 | override func viewDidLoad() { 38 | super.viewDidLoad() 39 | 40 | navigationItem.title = "PPGetAddressBook Swift版" 41 | 42 | tableView = UITableView.init(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height), style: UITableViewStyle.grouped) 43 | tableView.delegate = self 44 | tableView.dataSource = self 45 | view.addSubview(tableView) 46 | } 47 | 48 | } 49 | 50 | extension ViewController: UITableViewDelegate, UITableViewDataSource { 51 | 52 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 53 | 54 | return dateSource.count 55 | } 56 | 57 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 58 | 59 | var cell = tableView.dequeueReusableCell(withIdentifier: "cell") 60 | if cell == nil { 61 | 62 | cell = UITableViewCell.init(style: UITableViewCellStyle.default, reuseIdentifier: "cell") 63 | } 64 | 65 | cell?.textLabel?.text = dateSource[indexPath.row] 66 | cell?.accessoryType = UITableViewCellAccessoryType.disclosureIndicator 67 | return cell! 68 | 69 | } 70 | 71 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 72 | if indexPath.row == 0 { 73 | // A~Z分组排序 74 | navigationController?.pushViewController(AddressBookVC1(), animated: true) 75 | 76 | } else if indexPath.row == 1{ 77 | //原始顺序 78 | navigationController?.pushViewController(AddressBookVC2(), animated: true) 79 | } 80 | } 81 | 82 | } 83 | 84 | -------------------------------------------------------------------------------- /PPGetAddressBookSwiftTests/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 | -------------------------------------------------------------------------------- /PPGetAddressBookSwiftTests/PPGetAddressBookSwiftTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PPGetAddressBookSwiftTests.swift 3 | // PPGetAddressBookSwiftTests 4 | // 5 | // Created by AndyPang on 16/9/16. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import PPGetAddressBookSwift 11 | 12 | class PPGetAddressBookSwiftTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PPGetAddressBookSwift 2 | ![](https://img.shields.io/badge/platform-iOS-red.svg) ![](https://img.shields.io/badge/language-Swift-orange.svg) ![](https://img.shields.io/cocoapods/v/PPGetAddressBookSwift.svg?style=flat) ![](https://img.shields.io/cocoapods/dt/PPGetAddressBookSwift.svg) ![](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) [![](https://img.shields.io/badge/weibo-jkpang--%E5%BA%9E-red.svg)](http://weibo.com/5743737098/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) 3 | 4 | PPGetAddressBookSwift与Objective-C版本功能与特性相同(基于swift语言的特性,此版本会比OC版性能要好一些).在这里就不多做介绍. 5 | 6 | #### Objective-C版本,请戳: https://github.com/jkpang/PPGetAddressBook 7 | 8 | ### 新建 PP-iOS学习交流群 : 323408051 有关于PP系列封装的问题和iOS技术可以在此群讨论 9 | 10 | [简书地址](http://www.jianshu.com/p/b51a6125bcff) ; 11 | 12 | ![image](https://github.com/jkpang/PPGetAddressBook/blob/master/AddressBook.mov.gif) 13 | 14 | ## Requirements 要求 15 | * iOS 8+ 16 | * Xcode 8+ 17 | 18 | ## Installation 安装 19 | ### 1.手动安装: 20 | `下载DEMO后,将子文件夹PPGetAddressBookSwift拖入到项目中,无须import,直接使用` 21 | ### 2.CocoaPods安装: 22 | first 23 | `pod 'PPGetAddressBookSwift',:git => 'https://github.com/jkpang/PPGetAddressBookSwift.git'` 24 | 25 | then 26 | `pod install或pod install --no-repo-update` 27 | 28 | 在你需要使用的地方 import PPGetAddressBook 29 | 30 | 如果发现pod search PPGetAddressBookSwift 不是最新版本,在终端执行pod setup命令更新本地spec镜像缓存(时间可能有点长),重新搜索就OK了 31 | ## Usage 使用方法 32 | ****注意, 在iOS 10系统下必须在info.plist文件中配置获取隐私数据权限声明 : [兼容iOS 10:配置获取隐私数据权限声明 33 | ](http://www.jianshu.com/p/616240463a7a)*** 34 | ### 一、首先必须要请求用户是否授权APP访问通讯录的权限(建议在APPDeletegate.m中的didFinishLaunchingWithOptions方法中调用) 35 | 36 | ```swift 37 | // MARK: - 请求用户获取通讯录权限, 必须调用 38 | PPGetAddressBook.requestAddressBookAuthorization() 39 | ``` 40 | ### 二、获取通讯录 41 | ### 1.获取按联系人姓名首字拼音A~Z排序(已处理姓名所有字符的排序问题),一句话搞定! 42 | 43 | ```swift 44 | // MARK: - 获取A~Z分组顺序的通讯录 45 | PPGetAddressBook.getOrderAddressBook(addressBookInfo: { (addressBookDict, nameKeys) in 46 | 47 | self.addressBookSouce = addressBookDict // 所有联系人信息的字典 48 | self.keysArray = nameKeys // 所有分组的key值数组 49 | // 刷新tableView 50 | self.tableView.reloadData() 51 | 52 | }, authorizationFailure: { 53 | print("请在iPhone的“设置-隐私-通讯录”选项中,允许PPAddressBookSwift访问您的通讯录") 54 | }) 55 | 56 | 57 | 58 | ``` 59 | ### 2.获取原始顺序的联系人模型,未分组,一句话搞定! 60 | 61 | ```swift 62 | // MARK: - 获取原始顺序联系人的模型数组 63 | PPGetAddressBook.getOriginalAddressBook(addressBookArray: { (addressBookArray) in 64 | 65 | self.dataSourceArray = addressBookArray 66 | self.tableView.reloadData() 67 | 68 | }, authorizationFailure: { 69 | print("请在iPhone的“设置-隐私-通讯录”选项中,允许PPAddressBookSwift访问您的通讯录") 70 | }) 71 | 72 | ``` 73 | 74 | 如果你有更好的实现方法,希望不吝赐教! 75 | #### 你的star是我持续更新的动力! 76 | === 77 | ## CocoaPods更新日志 78 | * 2016.10.30(tag:0.2.0)--1.对姓"长","沈","厦","地","冲"多音字进行优化处理; 2.将'#'key值排列在A~Z的末尾! 3. 修复优化其他BUG 79 | * 2016.09.24(tag:0.1.5)--适配Swift3 80 | * 2016.09.18(tag:0.1.1)--修复可能造成崩溃的Bug 81 | * 2016.09.17(tag:0.1.0)--Pods初始化 82 | 83 | ## 联系方式: 84 | * Weibo : [@jkpang-庞](http://weibo.com/5743737098/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) 85 | * Email : jkpang@outlook.com 86 | * QQ群 : 323408051 87 | 88 | ![PP-iOS学习交流群群二维码](https://github.com/jkpang/PPCounter/blob/master/PP-iOS%E5%AD%A6%E4%B9%A0%E4%BA%A4%E6%B5%81%E7%BE%A4%E7%BE%A4%E4%BA%8C%E7%BB%B4%E7%A0%81.png) 89 | 90 | ## 许可证 91 | PPGetAddressBookSwift 使用 MIT 许可证,详情见 LICENSE 文件。 92 | 93 | 94 | 95 | 96 | --------------------------------------------------------------------------------