iOS开发常用权限汇总

主要总结下以下常用权限的获取及请求授权用法等(均不考虑iOS8以下系统):
网络权限 推送权限 定位权限 通讯录权限 相机权限 相册权限

网络权限

使用系统CoreTelephony库实现网络权限的获取及监听

  • 获取网络权限
 func getTelephonyAuthorization() {
        // 获取网络权限状态
        let cellularData = CTCellularData.init()
        switch cellularData.restrictedState {
            case .restricted:
                print("restricted");
            case .notRestricted:
                print("notRestricted");
            case .restrictedStateUnknown:
                print("restrictedStateUnknown");
        }
    }
  • 请求(申请)网络权限
    系统没有提供接口供开发者手动请求网络权限,iOS10及以上系统,应用首次请求网络时,系统会自动弹出权限选择框;而且一个应用只会弹出一次提示,提示过后就算卸载重装也不再提示;
    ps:首次请求时,如
   Alamofire.request("https://www.baidu.com")

弹出权限提示框

hehe
  • iOS10及以上系统网络权限相关处理
    iOS 10 之后首次安装的应用,请求网络时会弹出上面的提示框;在用户未选择前,所有网络请求都是失败的,这就会造成首页加载不出数据一片空白的情况;而且就算用户点击了允许,但在点击前的网络请求不会自动再次调用;对于这种情况,有几种解决办法:
  1. 封装网络框架,请求失败时,定时重新请求
  2. 提供数据空白页,空白页提供类似“重新加载”的按钮,允许及引导用户手动重新请求;
  3. 监听网络权限的变化,当监听到网络权限更改为允许后,重新请求;
 let cellularData = CTCellularData.init()
 func requestTelephonyAuthorization() {
        // 监听网络权限变化
        cellularData.cellularDataRestrictionDidUpdateNotifier = {state in
            switch state {
                case .restricted:
                    print("restricted");
                case .notRestricted:
                    print("notRestricted");
                case .restrictedStateUnknown:
                    print("restrictedStateUnknown");
            }
        }
    }

详细处理流程,可参考iOS 10 之 网络权限带来的坑

推送权限

推送相关API iOS10更新了,对应的权限API有所不同;

  • 获取推送权限
    系统并没有提供获取推送权限状态的API,但可以通过NotificationSettings判断:
 func getNotificationAuthorization() {
        if #available(iOS 10.0, *) {
            UNUserNotificationCenter.current().getNotificationSettings { (settings) in
                switch settings.authorizationStatus.rawValue {
                case 0:
                    print("not authorized")
                default:
                    print("authorized")
                }
            }
        }else {
            guard let settings = UIApplication.shared.currentUserNotificationSettings else {
                print("not settings");
                return;
            }
            switch settings.types.rawValue {
            case 0:
                print("not authorized")
            default:
                print("authorized")
            }
        }
    }
  • 请求推送权限
    iOS10之前系统,对于请求(申请)推送权限也没有具体的API;只有当应用设置NotificationSettings时,会自动请求推送权限并弹出提示框(提示框应用只会提示一次,不同于网络权限,应用卸载重装后,首次设置NotificationSettings时也会弹出提示框);
    iOS10及之后系统,同上面一样;但系统增加了请求推送权限的接口,可以手动调用接口来请求申请权限,对于手动请求的还可以监听到用户的选项(允许还是拒绝);手动请求权限,应用也只会首次时弹提示框;
func requestNotificationAuthorization() {
        if #available(iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            center.requestAuthorization(options: [.alert,.sound,.badge]) { (granted, error) in
                if granted {
                    print("authorized");
                }else {
                    print("not authorized");
                }
            }
        } else {
            let setting = UIUserNotificationSettings.init(types: [.alert,.sound,.badge], categories: nil)
            UIApplication.shared.registerUserNotificationSettings(setting)
        }
    }

定位权限

定位权限有两种情况,一种是针对手机的(全部应用),一种是针对当前应用;两种情况都有对应接口获取权限状态;

  • 获取定位权限
 func getLocationAuthorization() {
        // 手机的定位权限
        if !CLLocationManager.locationServicesEnabled() {
            print("disenable")
            return;
        }
        // 应用的定位权限
        let status = CLLocationManager.authorizationStatus()
        switch status {
            case .authorizedAlways:
                print("always")
            case .authorizedWhenInUse:
                print("authorizedWhenInUse")
            case .denied:
                print("denied")
            case .notDetermined:
                print("notDetermined")
            case .restricted:
                print("restricted")
        }
    }
  • 请求定位权限
    使用相应接口定位时,会自动请求权限;也可以调用接口手动请求,应用只有首次使用时才会弹出权限提示框;与其他权限不同的是,手动请求定位权限是通过delegate回调的,在回调中可以监听并获取到用户的选项;
   let manager = CLLocationManager.init()
    func requestLocationAuthorization() {
        manager.delegate = self
        manager.requestAlwaysAuthorization()
        manager.requestWhenInUseAuthorization()
    }
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .authorizedAlways:
            print("always")
        case .authorizedWhenInUse:
            print("authorizedWhenInUse")
        case .denied:
            print("denied")
        case .notDetermined:
            print("notDetermined")
        case .restricted:
            print("restricted")
        }
    }
  • 权限描述
    为了让用户清楚了解申请权限的具体用途,iOS已强制开发者为某些权限在info.plist中添加对应的描述;该描述将显示在权限提示框上;这个描述一定要阐明权限的具体用途,比如该权限将用于什么功能之类的,否则app审核会被拒(亲身经历,血的教训);
key

定位权限描述的key有:
NSLocationAlwaysAndWhenInUseUsageDescription,
NSLocationWhenInUseUsageDescription

通讯录权限

通讯录相关API iOS9更新了,对应的权限API有所不同;

  • 获取通讯录权限
func getContactAuthorization() {
        if #available(iOS 9.0, *) {
            let status = CNContactStore.authorizationStatus(for: .contacts)
            // ...
        }else {
            let status = ABAddressBookGetAuthorizationStatus()
            // ...
        }
    }
  • 请求通讯录权限
    和上面权限类似;可以自动,也可以手动请求并监听权限
    func requestContactAuthorization() {
        if #available(iOS 9.0, *) {
            let contact = CNContactStore.init()
            contact.requestAccess(for: .contacts) { (granted, error) in
                // ...
            }
        }else {
            let addressBook = ABAddressBookCreateWithOptions(nil, nil)
            ABAddressBookRequestAccessWithCompletion(addressBook as ABAddressBook) { (granted, error) in
                // ...
            }
        }
    }
  • 权限描述
    key:NSContactsUsageDescription

相机权限

  • 获取相机权限
    func getVideoAuthorization() {
        let videoAuthorStatus = AVCaptureDevice.authorizationStatus(for: .video)
        switch videoAuthorStatus {
            case .authorized:
                print("authorized");
            case .denied:
                print("denied");
            case .notDetermined:
                print("notDetermined");
            case .restricted:
                print("restricted");
        }
    }
  • 请求相机权限
    func requestVideoAuthorization() {
        AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted) in
            if granted {
                print("authorized");
            }else {
                print("not authorized");
            }
        })
    }
  • 权限描述
    key:NSCameraUsageDescription

相册权限

访问系统相册,保存图片至手机相册均需要该权限;

  • 获取相册权限
    func getPhotoAuthorization() {
        let photoAuthorStatus = PHPhotoLibrary.authorizationStatus()
        switch photoAuthorStatus {
            case .authorized:
                print("authorized");
            case .denied:
                print("denied");
            case .notDetermined:
                print("notDetermined");
            case .restricted:
                print("restricted");
            }
    }
  • 请求相册权限
    func requestPhotoAuthorization() {
        PHPhotoLibrary.requestAuthorization { (status) in
            if status == PHAuthorizationStatus.authorized {
                print("authorized");
            }else {
                print("not authorized");
            }
        }
    }
  • 权限描述
    key:NSPhotoLibraryUsageDescription

开发中使用场景

  • 在首次使用具体某些功能时(如拍照,读取照片),系统会自动弹出提示框,向用户申请对应权限;某些权限,开发者也可以手动调用接口来请求、向用户申请相应权限;具体是选择自动请求还是手动请求,可以视需求而定;对于不是频繁使用的功能,可以在使用该功能时再申请权限,也即让系统自动请求;而手动调用接口请求,主要作用是:可以提前申请权限,或者在应用启动后统一申请要用到的权限;
  • 需要用户授权的功能,有可能被用户拒绝授权;所以使用这些功能前要先获取对应的权限状态,如果权限是被拒绝的就需要进一步处理;一般的处理办法是,弹出提示框引导用户开启该权限,最好是提供一个按钮能直接跳转至系统设置界面;跳转至系统设置界面的代码:
// iOS8及以上系统
UIApplication.shared.openURL(NSURL.init(string: UIApplication.openSettingsURLString) as! URL)
  • 引导用户去设置界面开启权限时,我们希望能得到反馈(即用户是否真的去开启了权限),如果用户去设置界面开启了权限后,再重新实现具体功能;比如,使用拍照功能时,首先判断相机权限状态,获取的状态是拒绝的就弹出提示框引导用户去设置界面开启;用户开启权限后,应用再重新调用拍照功能,就不需要用户再多做一步操作了;
    但用户是否在设置界面开启权限,我们是不得而知的;但可以通过其他方式实现:
  1. 开启定时器,每间隔一段时间重新获取权限状态;当权限状态为允许时,再做相关处理;
  2. 当用户切换至系统设置界面再回到当前应用时,当前应用状态肯定会经过BecomeActive这个状态,那么我们可以添加UIApplication.didBecomeActiveNotification通知监听这个状态,做相应处理;
NotificationCenter.default.addObserver(self, selector: #selector(becomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)

以上权限中,通讯录权限、相册权限、相机权限当用户切换至系统设置界面更改后,应用将被kill

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 不容易啊,虽然还是很多不会的........忘记的.......但是起码走了一遍下来,接下来二刷......然后去...
    杰伦哎呦哎呦阅读 382评论 0 0
  • 我是小小高阅读 244评论 0 0
  • 坚持分享第四天 今天突然非常想写写自己的爸爸和妈妈。想起爸爸妈妈,令我感动的事情枚不胜数,但有两件事情...
    一祉微笑阅读 214评论 0 0
  • 推开门 夜雨曾过 空气和风滞留 三棵树安静地沉睡 酣甜的呼吸 让你不敢轻易呼唤 几只欢快的小鸟 歌唱着嬉闹 秋天的...
    龙青阅读 322评论 1 3