swift3下通讯录的开发

来源:互联网 发布:学化妆的软件 编辑:程序博客网 时间:2024/06/01 10:39

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. 联系人数据的排序与使用:

    //数据处理:排序、传给后端,更新UIfunc 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
原创粉丝点击