Запрашивать у пользователя доступ к его контактам в адресной книге

У меня есть контроллер представления, где я пытаюсь получить доступ к адресной книге пользователя на viewDidLoad. Когда пользователь попадает на контроллер представления, я хочу, чтобы всплывающее окно с предупреждением спрашивало его, может ли приложение получить доступ к контактам в их адресной книге, а затем они могли выбрать «ОК» или «Не разрешать».

Что странно, у меня создалось впечатление, что мой код был настроен правильно для этого. Однако всякий раз, когда я запускаю приложение на своем iPhone и посещаю этот контроллер представления, он даже не спрашивает у меня разрешения, а просто автоматически получает доступ к моим контактам. Я даже попытался удалить приложение и все его данные со своего iPhone, а затем повторно запустить его в xcode и на моем iPhone.

Я не уверен, что это сбой, потому что я разработчик, или что-то не так с моим кодом.

Вот код, который я использую для доступа к адресной книге в viewDidLoad:

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view.

//Asks for access to Address Book.

ABAddressBookRef m_addressbook =  ABAddressBookCreateWithOptions(NULL, NULL);


ABAddressBookCopyArrayOfAllPeople(m_addressbook);


__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @autoreleasepool {

            // Write your code here...
            // Fetch data from SQLite DB
        }
    });

    ABAddressBookRequestAccessWithCompletion(m_addressbook, ^(bool granted, CFErrorRef error)

    {
        accessGranted = granted;

        NSLog(@"Has access been granted?: %hhd", accessGranted);
        NSLog(@"Has there been an error? %@", error);


        dispatch_semaphore_signal(sema);
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
    accessGranted = YES;

    NSLog(@"Address book access has been granted.");
}

if (accessGranted) {


    NSArray *allContacts = (__bridge_transfer NSArray
                            *)ABAddressBookCopyArrayOfAllPeople(m_addressbook);

И затем в основном, если доступ предоставлен, я начинаю загружать все имена и номера телефонов в UITableView контроллера представления.

Мне действительно нужно выяснить, почему это так, и я также хотел бы добавить представление предупреждений, которое спрашивает пользователя, хотят ли они разрешить доступ к контактам адресной книги.

На самом деле он не запрашивает доступ, потому что мой код неправильный? Потому что он знает, что я разработчик? Как я уже сказал, я запускаю это после удаления приложения и всех его данных с моего iPhone.

ОБНОВЛЕНИЕ: я использую iOS 7.0.4, если это имеет значение.


person user3344977    schedule 09.03.2014    source источник


Ответы (3)


Одна ошибка, которую я вижу в вашем коде, заключается в том, что у вас есть это:

if (ABAddressBookRequestAccessWithCompletion != NULL) {

Это должно быть:

if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {

Проблема с вашим исходным кодом в том, что ABAddressBookRequestAccessWithCompletion - это не что-то другое: для него требуются параметры, как вы используете позже в том же операторе if. Я удивлен, что вы не получаете сообщение об ошибке от Xcode. ABAddressBookGetAuthorizationStatus был новым в iOS 6.

Кроме того, вы должны создать ссылку адресной книги после получения разрешения, а не до этого.

Также возможно, что поскольку приложение было на вашем iPhone в какой-то момент, оно запоминает, что вы разрешили приложению использовать ваши контакты. В симуляторе iOS есть параметр «Сбросить содержимое и настройки». Это заставляет симулятор забыть о любых настройках разрешений, которые вы дали своему приложению. Я считаю маловероятным, что вы захотите перезагрузить свой iPhone, верно?

person erdekhayser    schedule 10.03.2014
comment
Когда я заменяю свой оператор if на ваш, я получаю красное предупреждение в xcode: Использование необъявленного идентификатора 'ABAuthorizationStatusNotDetermined' - person user3344977; 11.03.2014
comment
Отредактировал свой ответ. Должен быть k перед (kABAuthrorizationStatusNotDetermined) - person erdekhayser; 11.03.2014
comment
Вы сказали, что он помнит, что вы разрешили приложению использовать ваши контакты. Разве это не будет удалено / забыто, если удалить приложение и все его данные с iPhone? - person user3344977; 11.03.2014
comment
Казалось бы, должно. Однако, если вы попытаетесь запустить приложение на своем телефоне и дать ему разрешение на адресную книгу, удалив приложение, а затем запустив его снова, приложение больше не будет запрашивать у вас разрешение. Когда впервые вышла iOS 7, я помню, что видел место, где можно увидеть данные, оставшиеся от удаленных приложений, но не могу вспомнить, где именно я это видел. - person erdekhayser; 11.03.2014
comment
Да, я думаю, что вчера видел учебник по этому поводу, но на самом деле он требовал от вас полного сброса настроек iPhone. В любом случае, спасибо за помощь. - person user3344977; 11.03.2014
comment
Извините, но я забрал ответ. Изменив свой код, он все испортил. Ваш код предотвращает появление UIAlertView, который просит пользователя разрешить доступ к контактам. - person user3344977; 11.03.2014
comment
Это бессмысленно. Код внутри этого оператора if должен быть ABAddressBookRequestAccessWithCompletion(). Единственное, что следовало изменить, - это условие, которое должно произойти только при первом запросе разрешения. После того, как пользователя спросят один раз, вы не сможете спрашивать снова позже. Если вы сбросите симулятор, попробуйте еще раз, чтобы увидеть, появляется ли предупреждение. - person erdekhayser; 12.03.2014
comment
Я не использую симулятор, я использую физический iPhone. Дело в том, что, основываясь на предоставленном мной коде, когда я заменил ABAddressBookRequestAccessWithCompletion! = NULL вашей заменой ABAddressBookGetAuthorizationStatus == ABAuthorizationStatusNotDetermined, это каким-то образом препятствует появлению UIAlertView и запросу доступа. - person user3344977; 12.03.2014
comment
Кроме того, мой код основан на чрезвычайно популярном ответе на другой вопрос о доступе к адресной книге, который был задан, когда впервые вышла iOS 6, и он набрал 150+ голосов, так что я действительно не знаю, что еще вам сказать. - person user3344977; 12.03.2014
comment
В настоящее время у меня есть 3 приложения, использующих этот фреймворк, и я использую свой подход в каждом из них. Я могу показать вам свой код доступа в чате, если хотите. Если у вас есть ссылка на найденное вами решение, можете ли вы опубликовать ссылку? Я заинтригован. - person erdekhayser; 12.03.2014
comment
Извините, но мне нужно перейти к другим проблемам. Дело не в том, что я тебе не верю, это просто не работает на меня. Я просто пошел искать нить, и оказалось, что ты прав. Ответ с 102 положительными голосами совпадает с вашим, тот, который я использую, находится прямо под ним, всего с 38 положительными голосами. Вот вопрос: stackoverflow.com/questions/12648244/ < / а> - person user3344977; 12.03.2014
comment
ОЙ. Я понимаю, о чем вы говорили. Это должно было поддерживать iOS 5 и iOS 6 одновременно. На данный момент немногие разработчики все еще пытаются поддерживать iOS 5, так что этот ответ наполовину устарел. - person erdekhayser; 12.03.2014
comment
Попался. Могу поклясться, что использовал другой. В любом случае, похоже, пора перейти на ваше решение. Спасибо за помощь. - person user3344977; 12.03.2014
comment
@erdekhayser К вашему сведению, причина, по которой он не работал, заключается в том, что вам не хватало () в конце ABAddressBookGetAuthorizationStatus. Отредактировано для добавления пустых параметров (), потому что в противном случае XCode 5.1 оптимизирует строку, рассматривая вместо этого вызов функции как указатель на функцию и, таким образом, сравнение двух констант, которые никогда не равны. В результате код в блоке if никогда не выполняется. - person jzn; 10.04.2014

Я наконец понял это. Удаление приложения и «всех его данных» - это вводящий в заблуждение диалог, предоставляемый вашим iPhone. Что касается тестирования с настройками конфиденциальности, вам нужно перейти в Настройки> Общие> Сброс> Сбросить местоположение и конфиденциальность. Сделав это, вы получите действительно «свежую» среду, которая позволит вам протестировать свой код «доступа к конфиденциальности». Имейте в виду, что это приведет к удалению настроек вашего местоположения и конфиденциальности, которые вы установили для всех других приложений, которые вы используете.

person user3344977    schedule 11.03.2014

Используйте этот код .....

if (ABAddressBookGetAuthorizationStatus == ABAuthorizationStatusNotDetermined){

вместо того.....

 if (ABAddressBookRequestAccessWithCompletion != NULL) {
person Community    schedule 10.03.2014
comment
Когда я заменяю свой оператор if на ваш, я получаю красное предупреждение в xcode: Использование необъявленного идентификатора 'ABAuthorizationStatusNotDetermined' - person user3344977; 11.03.2014