ios---聊聊權(quán)限那些事

吶吶,談個(gè)女朋友想解鎖更多姿勢(shì)你也知道必須是要有權(quán)限訪(fǎng)問(wèn)的,強(qiáng)制執(zhí)行?大哥,別鬧,違法的?。?!
今天就來(lái)說(shuō)說(shuō)iOS中關(guān)于權(quán)限的那些事!

  • 相機(jī)權(quán)限: Privacy - Camera Usage Description
  • 相冊(cè)權(quán)限: Privacy - Photo Library Usage Description
  • 定位權(quán)限: Privacy - Location Always and When In Use Usage Description
  • 定位權(quán)限: Privacy - Location When In Use Usage Description
  • 藍(lán)牙權(quán)限: Privacy - Bluetooth Peripheral Usage Description
  • 通訊錄權(quán)限: Privacy - Contacts Usage Description
  • 麥克風(fēng)權(quán)限:Privacy - Microphone Usage Description

一 : 通訊錄權(quán)限

iOS 9 以前的通訊錄框架

  1. AddressBookUI.framework框架
    1. 提供了聯(lián)系人列表界面、聯(lián)系人詳情界面、添加聯(lián)系人界面等
    2. 一般用于選擇聯(lián)系人
  2. AddressBook.framework 框架
    1. 純 C 語(yǔ)言的 API,僅僅是獲得聯(lián)系人數(shù)據(jù)
    2. 沒(méi)有提供 UI 界面展示,需要自己搭建聯(lián)系人展示界面
    3. 里面的數(shù)據(jù)類(lèi)型大部分基于 Core Foundation 框架,使用起來(lái)炒雞復(fù)雜

iOS 9 以后最新通訊錄框架

  1. ContactsUI.framework 框架。

    擁有 AddressBookUI.framework 框架的所有功能,使用起來(lái)更加的面向?qū)ο蟆?/p>

  2. Contacts.framework 框架。

    擁有 AddressBook.framework 框架的所有功能,不再是 C 語(yǔ)言的 API,使用起來(lái)非常簡(jiǎn)單。

值得注意的是如果只是單純的選擇某個(gè)聯(lián)系人的信息時(shí)使用AddressBookUI.framework或者ContactsUI.framework 框架時(shí)是不需要設(shè)置權(quán)限
只有在獲取用戶(hù)通訊錄的時(shí)候系統(tǒng)才會(huì)彈出權(quán)限提示框

WechatIMG1176.png

選擇親近的聯(lián)系人只是獲取單個(gè)聯(lián)系人信息,這里不需要設(shè)置權(quán)限相關(guān)

1. iOS 9 之前使用AddressBookUI.framework框架獲取聯(lián)系人信息

- (void) pushToEarlyIOS9VC
{
    ABPeoplePickerNavigationController *pvc = [[ABPeoplePickerNavigationController alloc] init];
    pvc.peoplePickerDelegate = self;
    [self presentViewController:pvc animated:YES completion:nil];
}


這樣就跳轉(zhuǎn)到了聯(lián)系人界面,但是這里又分為兩種情況,
一種是點(diǎn)擊聯(lián)系人后直接回調(diào):

列表一.png

代碼如下:

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
{
    CFStringRef firstNameRef = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    CFStringRef lastNameRef = ABRecordCopyValue(person, kABPersonLastNameProperty);

    NSString * firstName = CFBridgingRelease(firstNameRef);
    NSString * lastName = CFBridgingRelease(lastNameRef);

    NSString *nameStr;
    if (! firstName && lastName) {
        nameStr = lastName;
    }else if (! lastName && firstName){
        nameStr = firstName;
    }else if (firstName && lastName){
        nameStr = [NSString stringWithFormat:@"%@%@", lastName, firstName];
    }else{
        nameStr = @"";
    }

    ABMultiValueRef phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty);
    CFIndex count = ABMultiValueGetCount(phoneMulti);

    NSString *phoneNum;
    for (int i = 0; i  < count; i++)
    {
        // label:_$!<Mobile>!$_或者_(dá)$!<Home>!$_
        NSString *label = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(multi, i);
        // _$!<Mobile>!$_或者_(dá)$!<Home>!$_對(duì)應(yīng)的手機(jī)號(hào)碼字符串
        NSString *phone =(__bridge_transfer NSString *)  ABMultiValueCopyValueAtIndex(multi, i);//手機(jī)號(hào)
        NSLog(@"%@---%@", label, phone);
        phoneNum = phone;
    }

    

    // 之后對(duì)取到的手機(jī)號(hào)phoneNum進(jìn)行字符串剪切、替換、文本賦值操作

}

另一種是點(diǎn)擊聯(lián)系人后跳轉(zhuǎn)到詳情頁(yè)再進(jìn)行號(hào)碼選擇:

WechatIMG11767的副本.png

代碼如下:

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
    SXLog(@"%d---%d",property,identifier);
    // 獲取該聯(lián)系人多重屬性--電話(huà)號(hào)
    ABMutableMultiValueRef phoneMulti = ABRecordCopyValue(person, kABPersonPhoneProperty);

    // 獲取該聯(lián)系人的名字,簡(jiǎn)單屬性,只需ABRecordCopyValue取一次值
    ABMutableMultiValueRef firstNameRef = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *firstName = (__bridge NSString *)(firstNameRef);
    ABMutableMultiValueRef lastNameRef = ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSString *lastName = (__bridge NSString *)(lastNameRef);

    NSString *nameStr;
    if (!firstName && lastName) {
        nameStr = lastName;
    }else if (!lastName && firstName){
        nameStr = firstName;
    }else if (firstName && lastName){
        nameStr = [NSString stringWithFormat:@"%@%@", lastName, firstName];
    }else{
        nameStr = @"";
    }

    // 點(diǎn)擊某個(gè)聯(lián)系人電話(huà)后dismiss聯(lián)系人控制器,并回調(diào)點(diǎn)擊的數(shù)據(jù)
    [self dismissViewControllerAnimated:YES completion:^{
        // 從聯(lián)系人詳情中取值,參數(shù)identifier是取點(diǎn)擊的索引標(biāo)志(住宅號(hào)碼、手機(jī)號(hào)碼等)
        NSString *phoneNum =  (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phoneMulti, ABMultiValueGetIndexForIdentifier(phoneMulti,identifier)) ;
        // 之后對(duì)取到的手機(jī)號(hào)phoneNum進(jìn)行字符串剪切、替換、文本賦值操作
    }];
}

2. iOS 9 之后使用ContactsUI.framework 框架獲取聯(lián)系人信息

- (void) pushToAfterIOS9VC
{
    if (@available(iOS 9.0, *)) {
        CNContactPickerViewController *contactPickerViewController = [[CNContactPickerViewController alloc] init];
        contactPickerViewController.delegate = self;
        [self presentViewController:contactPickerViewController animated:YES completion:nil];
    } else {
        // Fallback on earlier versions
    }
}


這里也跟使用AddressBookUI.framework一樣,分兩種情況,點(diǎn)擊聯(lián)系人后直接回調(diào)

- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact {

    NSString *givenName = contact.givenName;
    NSString *familyName = contact.familyName;
    NSArray * phoneNumbers = contact.phoneNumbers;
    for (CNLabeledValue<CNPhoneNumber*>*phone in phoneNumbers) {
        //homeOrMobile:遍歷個(gè)人對(duì)應(yīng)所有手機(jī)號(hào)得到的值(_$!<Mobile>!$_或者_(dá)$!<Home>!$_)
        NSString *homeOrMobile = phone.label;
        CNPhoneNumber *phonNumber = (CNPhoneNumber *)phone.value;
        // 手機(jī)號(hào)字符串
        NSString *phoneNumberString = phonNumber.stringValue;

        // 之后做字符串的剪切、替換、文本賦值等操作
    }
}


點(diǎn)擊聯(lián)系人后跳轉(zhuǎn)到進(jìn)入詳情頁(yè)進(jìn)行選擇:

- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty {

    NSString *givenName = contactProperty.contact.givenName;
    NSString *familyName = contactProperty.contact.familyName;
    NSArray * phoneNumbers = contactProperty.contact.phoneNumbers;
    for (CNLabeledValue<CNPhoneNumber*>*phone in phoneNumbers) {
        //homeOrMobile:遍歷詳情屬性得到的值(_$!<Mobile>!$_或者_(dá)$!<Home>!$_)
        NSString *homeOrMobile = phone.label;
        CNPhoneNumber *phonNumber = (CNPhoneNumber *)phone.value;
        // 手機(jī)號(hào)字符串
        NSString *phoneNumberString = phonNumber.stringValue;
        // 如果不做此判斷取到的手機(jī)號(hào)都是最后一個(gè)(一個(gè)人可能對(duì)應(yīng)多個(gè)手機(jī)號(hào))
        if ([homeOrMobile isEqualToString:contactProperty.label]) {
            // contactProperty.label手動(dòng)選擇的結(jié)果(_$!<Mobile>!$_或者_(dá)$!<Home>!$_其中之一)
            // 匹配之后做字符串的剪切、替換、文本賦值等操作
        }
    }
}

到這里選擇聯(lián)系人的幾種情況就講完了,值得注意的是單純的選擇某個(gè)聯(lián)系人的信息跟權(quán)限是無(wú)關(guān)的,是無(wú)關(guān)的,是無(wú)關(guān)的?。?!

只有在你想獲取用戶(hù)通訊錄的時(shí)候才需設(shè)置用戶(hù)權(quán)限

獲取用戶(hù)通訊錄

if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0){
    [self requestContactAuthorAfterSystemVersion9];
}else{
    [self requestContactAuthorEarlySystemVersion9];
}

3. iOS9之前使用AddressBook.framework框架獲取用戶(hù)通訊錄

- (void) requestContactAuthorEarlySystemVersion9{

    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined){
        ABAddressBookRef bookRef = ABAddressBookCreate();
        ABAddressBookRequestAccessWithCompletion(bookRef, ^(bool granted, CFErrorRef error) {
            if (granted){
                bookIsOpen = YES;
                [self getADBookEarlyIOS9];
            }else{
                bookIsOpen = NO;
            }
        });
    }else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized){
        bookIsOpen = YES;
        [self getADBookEarlyIOS9];
    }
}


- (void) getADBookEarlyIOS9{
    // 2. 獲取所有聯(lián)系人
    ABAddressBookRef addressBookRef = ABAddressBookCreate();
    CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
    long count = CFArrayGetCount(arrayRef);
    for (int i = 0; i < count; i++) {
        NSMutableDictionary *dic = [NSMutableDictionary new];
        //獲取聯(lián)系人對(duì)象的引用
        ABRecordRef people = CFArrayGetValueAtIndex(arrayRef, i);
    
        //獲取當(dāng)前聯(lián)系人名字
        NSString *firstName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
        //獲取當(dāng)前聯(lián)系人姓氏
        NSString *lastName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
  
        //拼接姓名
        NSString *nameStr;
        if (!lastName && !firstName) {
            nameStr = @"";
        }else if (!lastName && firstName){
            nameStr = [NSString stringWithFormat:@"%@",firstName];
        }else if (lastName && !firstName){
            nameStr = [NSString stringWithFormat:@"%@",lastName];
        }else if (lastName && firstName){
            nameStr = [NSString stringWithFormat:@"%@%@",lastName,firstName];
        }
        NSString *phoneStr;
        ABMultiValueRef phones = ABRecordCopyValue(people, kABPersonPhoneProperty);
        for (NSInteger j=0; j<ABMultiValueGetCount(phones); j++) {
            NSString *phone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j));
            phoneStr = phone;
        }
    
        if (!phoneStr) {
            phoneStr = @"";
        }
        [dic setObject:phoneStr forKey:@"mobile"];
        [dic setObject:nameStr forKey:@"name"];
        if ([self isBlankString:nameStr] || [self isBlankString:phoneStr]) {
            //名字或者手機(jī)號(hào)為空視為非法
        }else{
            [self.phoneNumArr addObject: dic];
        }
    }
}

4. iOS9之后使用Contacts.framework 框架獲取用戶(hù)通訊錄

- (void)requestContactAuthorAfterSystemVersion9{

    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    if (status == CNAuthorizationStatusNotDetermined) {
        CNContactStore *store = [[CNContactStore alloc] init];
        [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError*  _Nullable error) {
            if (granted) {
                bookIsOpen = YES;
                [self getADBookAfterIOS9];
            }else{
                bookIsOpen = NO;
                [self showAlertVCWithTitle:@"通訊錄訪(fǎng)問(wèn)" message:@"去分期需要訪(fǎng)問(wèn)您的通訊錄"];
            }
        }];
    }else if(status == CNAuthorizationStatusRestricted){
        bookIsOpen = NO;
        [self showAlertVCWithTitle:@"通訊錄訪(fǎng)問(wèn)" message:@"去分期需要訪(fǎng)問(wèn)您的通訊錄"];
    }else if (status == CNAuthorizationStatusDenied){
        bookIsOpen = NO;
        [self showAlertVCWithTitle:@"通訊錄訪(fǎng)問(wèn)" message:@"去分期需要訪(fǎng)問(wèn)您的通訊錄"];
    }else if (status == CNAuthorizationStatusAuthorized){//已經(jīng)授權(quán)
        bookIsOpen = YES;
        //有通訊錄權(quán)限-- 進(jìn)行下一步操作
        [self getADBookAfterIOS9];
    }
}


- (void) showAlertVCWithTitle:(NSString *)title message:(NSString *)message{

    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:(UIAlertControllerStyleAlert)];
    UIAlertAction *cancleAC = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:nil];
    UIAlertAction *openAC = [UIAlertAction actionWithTitle:@"打開(kāi)" style:(UIAlertActionStyleDestructive) handler:^(UIAlertAction * _Nonnull action) {
        NSURL *settingUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        if ([[UIApplication sharedApplication] canOpenURL:settingUrl]) {
            [[UIApplication sharedApplication] openURL:settingUrl];
        }
    }];
    [alertC addAction:cancleAC];
    [alertC addAction:openAC];
    [self presentViewController:alertC animated:YES completion:nil];
}


- (void) getADBookAfterIOS9{
    // 獲取指定的字段,并不是要獲取所有字段,需要指定具體的字段
    NSArray *keysToFetch = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
    CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
    CNContactStore *contactStore = [[CNContactStore alloc] init];

    [contactStore enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
    
        NSMutableDictionary *mDic = [NSMutableDictionary new];
    
        NSString *givenName = contact.givenName;
        NSString *familyName = contact.familyName;//姓
        //拼接姓名
        NSString *nameStr;
        if (!givenName && !familyName) {
            nameStr = @"";
        }else if (!givenName && familyName){
            nameStr = [NSString stringWithFormat:@"%@",familyName];
        }else if (givenName && !familyName){
            nameStr = [NSString stringWithFormat:@"%@",givenName];
        }else if (givenName && familyName){
            nameStr = [NSString stringWithFormat:@"%@%@",familyName,givenName];
        }
    
        NSArray *phoneNumbers = contact.phoneNumbers;
        NSString *phoneStr;
        for (CNLabeledValue *labelValue in phoneNumbers) {
            //遍歷一個(gè)人名下的多個(gè)電話(huà)號(hào)碼
            NSString *label = labelValue.label;
            CNPhoneNumber *phoneNumber = labelValue.value;
            NSString * string = phoneNumber.stringValue ;
        
            //去掉電話(huà)中的特殊字符
            //string = [string stringByReplacingOccurrencesOfString:@"+86" withString:@""];
            //string = [string stringByReplacingOccurrencesOfString:@"-" withString:@""];
            //string = [string stringByReplacingOccurrencesOfString:@"(" withString:@""];
            //string = [string stringByReplacingOccurrencesOfString:@")" withString:@""];
            //string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
            phoneStr = string;
        }
        if (!phoneStr) {
            phoneStr = @"";
        }
        [mDic setObject:phoneStr forKey:@"mobile"];
        [mDic setObject:nameStr forKey:@"name"];
        if ([self isBlankString:nameStr] || [self isBlankString:phoneStr]) {
            //名字或者手機(jī)號(hào)為空視為非法
        }else{
            [self.phoneNumArr addObject:mDic];
        }
    }];
}

\color{red}{-----------------------------}

二:位置權(quán)限

導(dǎo)入類(lèi)庫(kù)#import <CoreLocation/CLLocationManager.h>并遵守CLLocationManagerDelegate協(xié)議

#pragma mark - 啟動(dòng)定位權(quán)限
-(void)getLocation
{
    //判斷定位功能是否打開(kāi)
    if ([CLLocationManager locationServicesEnabled]) {
        locationmanager = [[CLLocationManager alloc]init];
        locationmanager.delegate = self;
        currentCity = [NSString new];

        if (@available(iOS 9.0, *)) {
            locationmanager.allowsBackgroundLocationUpdates = YES;
        } else {
            // Fallback on earlier versions
        }
        [locationmanager requestAlwaysAuthorization];//后臺(tái)始終定位
        [locationmanager requestWhenInUseAuthorization];//使用期間定位
    
        //設(shè)置尋址精度
        locationmanager.desiredAccuracy = kCLLocationAccuracyBest;
        locationmanager.distanceFilter = 5.0;
        [locationmanager startUpdatingLocation];
    }
}

#pragma mark CoreLocation delegate (定位失敗)
//定位失敗后調(diào)用此代理方法
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    //失敗后執(zhí)行你需要的相應(yīng)操作
    strlatitude = @"";
    strlongitude = @"";
}

#pragma mark 定位成功后則執(zhí)行此代理方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    [locationmanager stopUpdatingHeading];
    //舊址
    CLLocation *currentLocation = [locations lastObject];
    CLGeocoder *geoCoder = [[CLGeocoder alloc]init];

    strlatitude = [NSString stringWithFormat:@"%.5f",currentLocation.coordinate.latitude];
    strlongitude = [NSString stringWithFormat:@"%.5f",currentLocation.coordinate.longitude];

    SXLog(@"%@---%@",strlatitude,strlongitude);

    //反地理編碼
    [geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (placemarks.count > 0) {
            CLPlacemark *placeMark = placemarks[0];
            currentCity = placeMark.locality;
            if (!currentCity) {
                currentCity = @"無(wú)法定位當(dāng)前城市";
            }
            //placeMark里面包含了你需要的信息,做相應(yīng)處理就好了
        }
    }];
}


如果有更高需求,可點(diǎn)進(jìn)協(xié)議查看更多方法
至于高德、百度地圖,之前也都用過(guò),官方文檔說(shuō)的也比較清晰,這里就不過(guò)多解讀了

這里還需要注意的是如果同時(shí)設(shè)置了requestWhenInUseAuthorizationrequestAlwaysAuthorization,requestAlwaysAuthorization的權(quán)限是大于(包括)requestWhenInUseAuthorization

如果需要后臺(tái)持續(xù)定位,首先要將下圖的Location updates打鉤

屏幕快照 2018-08.png

//執(zhí)行如下方法
[self.locationManager requestAlwaysAuthorization];


這樣就可以實(shí)現(xiàn)后臺(tái)定位,但是該方法只能實(shí)現(xiàn)后臺(tái)定位20-30分鐘的時(shí)間;
如果想達(dá)到后臺(tái)永久持續(xù)定位的效果,在定位的時(shí)候需要添加如下代碼:

self.locationManager.pausesLocationUpdatesAutomatically = NO;   //系統(tǒng)是否可以自行中斷程序的定位功能


該方法讓系統(tǒng)不能夠自行關(guān)閉程序的定位功能,保證程序一直處于后臺(tái)定位中

三:相冊(cè)權(quán)限

相機(jī)、相冊(cè)、麥克風(fēng)等權(quán)限狀態(tài)都對(duì)應(yīng)下列這種

AuthorizationStatusNotDetermined      // 用戶(hù)從未進(jìn)行過(guò)授權(quán)等處理,首次訪(fǎng)問(wèn)相應(yīng)內(nèi)容會(huì)提示用戶(hù)進(jìn)行授權(quán)
AuthorizationStatusAuthorized = 0,    // 用戶(hù)已授權(quán),允許訪(fǎng)問(wèn)
AuthorizationStatusDenied,            // 用戶(hù)拒絕訪(fǎng)問(wèn)
AuthorizationStatusRestricted,        // 應(yīng)用沒(méi)有相關(guān)權(quán)限,且當(dāng)前用戶(hù)無(wú)法改變這個(gè)權(quán)限,比如:家長(zhǎng)控制

是否支持

[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]


獲取權(quán)限狀態(tài)
ios8之前

ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];


iOS8之后

#import <Photos/PHPhotoLibrary.h>
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];


請(qǐng)求權(quán)限

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 
if (status == PHAuthorizationStatusAuthorized){ 
    //已授權(quán)
  }else{ 
    //未授權(quán)
    }
 }];


這里值得注意的一點(diǎn)是

1、iOS11之前訪(fǎng)問(wèn)相冊(cè)和存儲(chǔ)照片到相冊(cè)(讀寫(xiě)權(quán)限),需要用戶(hù)授權(quán),需要添加NSPhotoLibraryUsageDescription
2、iOS11之后:默認(rèn)開(kāi)啟訪(fǎng)問(wèn)相冊(cè)權(quán)限(讀權(quán)限),無(wú)需用戶(hù)授權(quán),無(wú)需添加NSPhotoLibraryUsageDescription,添加圖片到相冊(cè)(寫(xiě)權(quán)限),才需要用戶(hù)授權(quán),需要添加NSPhotoLibraryAddUsageDescription

PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusRestricted || status == PHAuthorizationStatusDenied){
    // 無(wú)權(quán)限
    UIAlertView * alart = [[UIAlertView alloc]initWithTitle:@"溫馨提示" message:@"請(qǐng)您設(shè)置允許該應(yīng)用訪(fǎng)問(wèn)您的相機(jī)\n設(shè)置>隱私>相機(jī)" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
    [alart show];
    return;
}

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    if (status == PHAuthorizationStatusRestricted || status == PHAuthorizationStatusDenied) {
        SXLog(@"沒(méi)權(quán)限");
    }else if (status == PHAuthorizationStatusNotDetermined){
        SXLog(@"暫未確定");
    }else if (status == PHAuthorizationStatusAuthorized){
        SXLog(@"已授權(quán)");
    }
}];

四:相機(jī)、麥克風(fēng)權(quán)限

是否支持

// 是否有攝像頭
[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]
// 前置攝像頭是否可用
[UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront];
// 后置攝像頭是否可用
[UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear];


獲取權(quán)限狀態(tài)

//獲取相機(jī)權(quán)限狀態(tài)
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
//獲取麥克風(fēng)權(quán)限狀態(tài)
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];


獲取相機(jī)、麥克風(fēng)權(quán)限

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
    if (granted) {
        //相機(jī)授權(quán)成功
    }else{
        //相機(jī)授權(quán)失敗
    }
}];

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
    if (granted) {
        //麥克風(fēng)授權(quán)成功
    }else{
        //麥克風(fēng)授權(quán)失敗
    }
}];

#import <Foundation/Foundation.h>
//獲取相機(jī)或麥克風(fēng)權(quán)限狀態(tài)
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

if (status == AVAuthorizationStatusNotDetermined) {
    //暫未授權(quán)的處理, AVMediaTypeVideo改為AVMediaTypeAudio就是麥克風(fēng)
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
        if (granted) {
            SXLog(@"相機(jī)或麥克風(fēng)授權(quán)成功");
        }else{
            SXLog(@"相機(jī)或麥克風(fēng)授權(quán)失敗");
        }
    }];
}else if (status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied){
    SXLog(@"無(wú)權(quán)限");
}else if (status == AVAuthorizationStatusAuthorized){
    SXLog(@"有權(quán)限");
}

五:推送權(quán)限

這個(gè)最近幾個(gè)項(xiàng)目用的都是極光或者友盟,就不多說(shuō)了,按文檔無(wú)腦集成就好!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 因?yàn)橐Y(jié)局swift3.0中引用snapKit的問(wèn)題,看到一篇介紹Xcode8,swift3變化的文章,覺(jué)得很詳細(xì)...
    uniapp閱讀 4,859評(píng)論 0 12
  • APP開(kāi)發(fā)避免不開(kāi)系統(tǒng)權(quán)限的問(wèn)題,今天做定位時(shí)需要在不允許定位的時(shí)候做一些操作,所以,今天就大概的了解了一些。 權(quán)...
    SunshineBrother閱讀 16,925評(píng)論 4 62
  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱(chēng)項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,186評(píng)論 3 119
  • 有時(shí)候發(fā)現(xiàn)電腦那么不可缺,離開(kāi)電腦像沒(méi)有燈的屋子,沒(méi)有月光的夜晚,一切都是黑暗的恐懼的。有時(shí)候又發(fā)現(xiàn)電腦控制了我的...
    2608閱讀 266評(píng)論 0 0
  • 1.已禁用-[UIDevice uniqueIdentifier] 蘋(píng)果總是把用戶(hù)的隱私看的很重要。-[UIDev...
    李炯7115閱讀 474評(píng)論 0 0

友情鏈接更多精彩內(nèi)容