swift3下通讯录的开发

Posted Shayne_win

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift3下通讯录的开发相关的知识,希望对你有一定的参考价值。

swift3下通讯录的开发

1:封装一个通讯录Manager:

ios9之后,通讯录用CNContactStore实现;iOS9之前使用ABAddressBook。

读取通讯录的流程:

  1. 检测授权;
  2. 没有权限申请权限;
  3. 得到权限读取通讯录消息。

2:开始封装AddressBookManger单例:

  1. 基本信息设置与实现:

    • iOS10之后需要在plist文件中添加访问权限:key:Privacy - Contacts Usage Description value:contactsDesciption。
    • mannager单例实现:

      /// 单例
       class var sharedInstance: YSAddressBookManager
           struct Static 
                          static var instance : YSAddressBookManager = YSAddressBookManager()
                          
                          return Static.instance
                 
    • 分别创建一个CNContactStore和ABAddressBook的属性:

              //注意调用ABAddressBookCreateWithOptions进行ABAddressBookCreateWithOptions的初始化需要设置为一个lazy变量,否则在用户拒绝授权的情况下,程序将会崩溃。因为ABAddressBookCreateWithOptions(nil, nil)得到的值为nil。
          lazy var addressBook:ABAddressBook = 
              var emptyDictionary: CFDictionary?
              var errorRef: Unmanaged<CFError>?
              let ab:ABAddressBook = ABAddressBookCreateWithOptions(emptyDictionary, &errorRef).takeRetainedValue()
              return ab
          ()
      
          @available(iOS 9.0, *)
          lazy var contact:CNContactStore = CNContactStore()
      
          //获取当前系统版本号
          lazy var current_iOS_Version:Float = 
              return UIDevice.current.systemVersion.floatValue
          ()
      
          var originalAddressData:[AddressBookObj] = [] //用于存放通讯录里的原始有效数据
    • 创建一个对外的权限授权状态:
                  //@objc如果是在OC和swift3混编的工程里,OC的类需要使用到AddressBookAuthorizationStatus枚举,则加上@objc,这样就可以在OC类里也使用,否则无需@objc标注
                  @objc enum AddressBookAuthorizationStatus:Int 
                      case deniedOrRestricted = 1
                      case authorized = 2
                      case notDeterMined = 3
                  
  2. 授权:

    • 检测授权情况

              //检测授权情况
              func cheackAddressBookAuthorizationStatus()->AddressBookAuthorizationStatus 
      
                  if #available(iOS 9, *) 
              switch CNContactStore.authorizationStatus(for: .contacts) 
                      case .denied,.restricted:
                          return .deniedOrRestricted
                      case .authorized:
                          return .authorized
                      case .notDetermined:
                          return .notDeterMined
                  
                 else
                  switch ABAddressBookGetAuthorizationStatus() 
                      case .denied,.restricted: //访问限制或者拒绝 弹出设置对话框
                          return .deniedOrRestricted
                      case .authorized://已授权,加载数据
                          return .authorized
                      case .notDetermined://从未进行过授权操作、请求授权
                          return .notDeterMined
              
              
              
    • 请求授权

      //请求授权
          func requestAddressBookAccess(_ success:@escaping ((_ granted:Bool )->Void)) 
          if #available(iOS 9, *)
              self.contact.requestAccess(for: .contacts, completionHandler:  (granted, error) in
                  if !granted 
                          success(false)
                  else
                          success(true)
                  
              )
          else
                  ABAddressBookRequestAccessWithCompletion(self.addressBook) (granted, error) in
                  if !granted 
                      success(false)
                  else
                      success(true)
                  
              
          
          
  3. 读取通讯录信息:

    1//谓词表达式判断手机号码是否有效
        func validateMobile(_ phoneNum:String)-> Bool 
            if phoneNum.characters.count != 11 || phoneNum.characters.count == 0 
                return false
            
            let mobile =  "^1[3|4|5|7|8][0-9]\\\\d8$"
            let regexMobile = NSPredicate(format: "SELF MATCHES %@",mobile)
            let isValid:Bool = regexMobile.evaluate(with: phoneNum)
            if !isValid 
                return false
            
            return true
        
    2//有的手机系统读取到的手机号都有'-',所以去除'-'
        func removeUnuseChar(str:String) -> String 
            var tmpStr = str
            for char in tmpStr.characters 
                if char == "-" 
                    let range = tmpStr.range(of: "-")
                    tmpStr.removeSubrange(range!)
                
                   
            return tmpStr
        
    3:
    
        func readRecords() -> [AddressBookObj] //原始有效数据
        
            self.originalAddressData.removeAll()
            if #available(iOS 9, *)
    
                let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName),CNContactPhoneNumbersKey] as [Any]
    
                try! self.contact.enumerateContacts(with: CNContactFetchRequest(keysToFetch: keysToFetch as! [CNKeyDescriptor]), usingBlock: [weak self] (contact, pointer) in
                var phone = ""
                if contact.phoneNumbers.count > 0 
                    let phoneNum = contact.phoneNumbers.first
    
                    guard let phoneNumber = phoneNum?.value else 
                        return
                    
    
                    let phoneString = phoneNumber.stringValue
    
                    let result = self?.removeUnuseChar(str: phoneString)
    
                    if self!.validateMobile(result!) 
                        phone = result!
                    
    
                    if phone != "" 
                        let obj:AddressBookObj = AddressBookObj()
                        obj.phone = phone
                        let name:String = String(format: "%@%@", contact.givenName,contact.familyName)
                        obj.name = name
                        self?.originalAddressData.append(obj)
                        print("CNContact:\\(name):\\(phone)")
                    
                
            )
            return originalAddressData
        else
    
            let peoples = ABAddressBookCopyArrayOfAllPeople(self.addressBook).takeRetainedValue() as [ABRecord]
    
            for people: ABRecord in peoples 
                var firstName = ""
                var lastName = ""
                var phone = ""
    
                if let firstNameUnmanaged = ABRecordCopyValue(people, kABPersonLastNameProperty) 
                    firstName = firstNameUnmanaged.takeRetainedValue() as? String ?? ""
                
                if let lastNameUnmanaged = ABRecordCopyValue(people, kABPersonFirstNameProperty) 
                    lastName = lastNameUnmanaged.takeRetainedValue() as? String ?? ""
                
    
                let phoneNums: ABMultiValue = ABRecordCopyValue(people, kABPersonPhoneProperty).takeRetainedValue() as ABMultiValue
    
                for index in 0..<ABMultiValueGetCount(phoneNums)
                    let label = ABMultiValueCopyValueAtIndex(phoneNums, index).takeRetainedValue() as! String
    
                    let result = self.removeUnuseChar(str: label)
    
                    if self.validateMobile(result) 
                        phone = result
                        break
                    
    
                
    
    
                if phone != "" 
                    let obj:AddressBookObj = AddressBookObj()
                    obj.phone = phone
                    let name:String = String(format: "%@%@", lastName,firstName)
                    obj.name = name
                    self.originalAddressData.append(obj)
                    print("ABAddressBook:\\(name):\\(phone)")
                
    
            
            return originalAddressData
        
        
  4. 联系人数据的排序与使用:

    //数据处理:排序、传给后端,更新UI
    func updateOroginalData()
        //得出27个索引
        let collation = UILocalizedIndexedCollation.current()
        let sectionTitles = collation.sectionTitles.count
        //self.sectionTitleArr存放section数组
        self.sectionTitleArr = NSMutableArray(array: collation.sectionTitles)
        //初始化27个空数组 self.dataArrays存放numberOfRowsInSection
        var i = 0
        while i<sectionTitles 
            let arr = NSMutableArray()
            self.dataArrays.add(arr)
            i += 1
        
        for obj in self.originalAddressData 
            if obj.name != "" 
                let sectionNum = collation.section(for: obj, collationStringSelector: #selector(obj.nameMethod))
                let array:NSMutableArray = self.dataArrays[sectionNum] as! NSMutableArray 
                array.add(obj)
            
        
    
        //对每个section中的数组按name排序
        for i in 0..<self.dataArrays.count 
            let arr:NSMutableArray = self.dataArrays[i] as! NSMutableArray
            let sortArr = collation.sortedArray(from: arr as [AnyObject], collationStringSelector: #selector(getter: xxClass.name))
            arr.removeAllObjects()
            arr.addObjects(from: sortArr)
        
    
        //去掉无数据的数组
        let tmpArrA = NSMutableArray()
        let tmpArrB = NSMutableArray()
    
        for i in 0..<self.dataArrays.count 
            let arr = self.dataArrays[i]
            if (arr as AnyObject).count == 0 
                tmpArrA.add(self.sectionTitleArr[i])
                tmpArrB.add(self.dataArrays[i])
            
        
    
        for i in 0..<tmpArrA.count 
            self.sectionTitleArr.remove(tmpArrA[i])
            self.dataArrays.remove(tmpArrB[i])
        
    
        tableView.reloadData()
    

以上是关于swift3下通讯录的开发的主要内容,如果未能解决你的问题,请参考以下文章

即时通讯开发之TCP/IP基本概念

即时通讯开发之TCP/IP基本概念

python用单链表写一个通讯录,包括添加,删除(可恢复),查找等基本功能

即时通讯开发

用c语言程序设计一个学生通讯录系统

android开发怎样获取通讯录联系人信息