封装调用手机通讯录工具(swift)

在开发的时候我们经常会用到调用系统的通讯录, 直接写代理很容易实现, 网上也很多例子, 例如:

iOS调用系统通讯录(适配iOS9、iOS10)(转载)

如果只是一个地方用到还好, 直接在controller里面签代理.

        但是遇到很多地方调用, 每次都签代理是不是感觉很麻烦, 这时候没有有想过封装出来一个工具类, 然后在用的时候直接调用就可以了, 比如一个block回调 (swift叫闭包). 


图片来自网络

本次封装的主要目的是把每个用到的地方都变成一个block, 直接回调, 方便以后别的地方用.

现在问题来了:

问题1: 通讯录的vc需要当前的vc 给present出来, 需要把当前的vc(context)传到工具类里

问题2: 代理签到传进来的vc里还是工具类里, 签到传进来的vc没法代理了, 就想办法签到工具类里

 所以大体思路是 写一个类 初始化的时候把vc和另一个参数回调的block都传进来,  然后写一个方法调用通讯录, 把代理签到工具类上,在代理执行的时候返回block

那么开始写代码, 我的工具类是ContactTool  直接考虑iOS9.0以上的 导入头文件 

import ContactsUI

回调的block

typealias ContactPickBlock = ( _ info: ContactInfo?) -> Void

定一个属性保留传进来的vc

private var context:UIViewController

private var callBack:ContactPickBlock?


初始化的时候传递或者属性传也可以

init(context:UIViewController) {        self.context = context    }

///调用联系人

    publicfuncjudgeAddressBookPower(didPcik:@escaping ContactPickBlock) {

        //检查权限

       checkAddressBookAuthorization{ [weakself] (isAuthorized)in

            guardlet`self` =selfelse{return}

            ifisAuthorized ==true{

                self.callAddressBook()

            }else{

                self.showMsg(msg:"请到设置>隐私>通讯录打开本应用的权限设置")

            }

        }

       self.callBack= didPcik

   }



检查权限

///获取通讯录权限

    privatefunccheckAddressBookAuthorization(handler:@escaping((_:Bool) ->Void)) {

        let contactStore =CNContactStore()

        if CNContactStore.authorizationStatus(for: .contacts) == .notDetermined {

            contactStore.requestAccess(for: .contacts, completionHandler: { (granted, error)in

                iferror !=nil{

                    print(errorasAny)

                    self.showMsg(msg: error.debugDescription)

                }elseifgranted ==false{

                    handler(false)

                }else{

                    handler(true)

                }

            })

        }else if CNContactStore.authorizationStatus(for: .contacts) == .authorized {

            handler(true)

        }else{

            handler(false)

        }

    }


调用通讯录

///调用通讯录

    privatefunccallAddressBook() {

        let contactPicker = CNContactPickerViewController()

        contactPicker.delegate=self

        contactPicker.displayedPropertyKeys = [CNContactPhoneNumbersKey]

        context.present(contactPicker, animated:true, completion:nil)

    }


提示信息的Alert

///显示信息

    privatefuncshowMsg(msg:String) {

        letalert =UIAlertController(title:"没有权限", message: msg, preferredStyle: .alert)

        alert.addAction(UIAlertAction(title:"知道了", style: .cancel, handler:nil))

        context.present(alert, animated:true)

    }


接下来实现代理 

///代理

extension ContactTool : CNContactPickerDelegate {

    //取消了

    funccontactPickerDidCancel(_picker:CNContactPickerViewController) {

        self.filtration(nil)

    }

    //选择完联系人

    funccontactPicker(_picker:CNContactPickerViewController, didSelect contactProperty:CNContactProperty) {

        letphoneNumber = contactProperty.valueas!CNPhoneNumber

        context.dismiss(animated:true) {

            // 联系人

            letname = contactProperty.contact.familyName+ contactProperty.contact.givenName

            // 电话

            letphone = phoneNumber.stringValue

            self.filtration(ContactInfo(name: name, phone: phone))

        }

    }

}

filtration 这个方法里就是回调的

        self.callBack?(info);

本以为这样就结束了, 新的问题出现, 当你调用通讯录的时候, 会发现代理根本没有走, 是因为在CNContactPickerViewController出现的时候, ContactTool 就被释放了, 这个怎么办...


图片来自网络

那怎么才能让ContactTool 不被释放呢, 必须得有个地方引用他, 用传过来的vc引用他还得写个属性, 思来想去想出一个比较奇葩的放法, 我们经常会提到避免循环引用, 循环引用会造成对象无法释放, 影响内存释放, 那正是我们想到的结果, 不让ContactTool释放, 我们为何不制造一个循环引用呢, 然后在使用之后打开循环释放.

创建一个类让他持有工具类的对象ContactTool

class Abbot: NSObject {

  let monk:ContactTool  

     init(monk:ContactTool) {       

     self.monk = monk     

     }   

  }


在judgeAddressBookPower方法中添加如下代码:

///调用联系人

    publicfuncjudgeAddressBookPower(didPcik:@escapingContactPickBlock) {

        //检查权限

        checkAddressBookAuthorization{ [weakself] (isAuthorized)in

            guardlet`self` =selfelse{return}

            ifisAuthorized ==true{

                self.callAddressBook()

            }else{

                self.showMsg(msg:"请到设置>隐私>通讯录打开本应用的权限设置")

            }

        }

        self.callBack= didPcik

        //制造循环引用

        letabbot_p =Abbot(monk:self)

        self.abbot= abbot_p

    } 


然后在filtration里打开循环引用

///过滤处理

    private func filtration(_info:ContactInfo?) {

        self.callBack?(info);

        //释放

        DispatchQueue.main.asyncAfter(deadline:DispatchTime.now()+0.1) {

            self.abbot=nil

        }

    }


这些就是所有逻辑, 虽然只是一个简单的封装, 但通过制造循环, 然后再释放, 貌似让我看到所有的代理都能通过这种方式封装成block, 也是一个通用的思想. 请各位大神指点

代码:ContactTest

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355