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]\\d{8}$"
            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()
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值