2013-03-14 41 views
1

我正在指導一個七年級和八年級的團隊,他們致力於開發一個小應用程序,以大格式顯示地址簿中的選項。你可以在callmeapp.org查看他們的一般項目。我們被困在如何提示用戶獲得許可,以便我們可以訪問通訊錄。基本上用戶提示不能正確顯示。僅供參考,我們已經通過設置>常規>重置>重置位置&隱私清除權限。如何獲取地址簿權限彈出窗口?

我們正在使用xCode 4.6並在運行6.1.2版本的iPhone MC918LL/A上進行測試。

我們從我們的appdelegate.m didfinishlaunchingwithoptions方法中的DavidPhilipOster的回覆代碼開始:How do I correctly use ABAddressBookCreateWithOptions method in iOS 6?。我們進行了一些編輯以清除我們正在收到的錯誤。

現在,應用程序啓動到黑屏並在那裏停留至少24秒,此時應用程序似乎關閉,顯示下面的許可提示。接受將我們發送到桌面。當我們重新打開應用程序時,它的工作就像權限已被清除一樣。或者,如果我們在屏幕上顯示黑色時按下主屏幕按鈕(電話上的一個按鈕),則會關閉以顯示如上所述的權限提示。 Permisison窗口應在非常短暫的延遲後顯示,然後在用戶授予許可時將我們留在應用程序中。

我們卡在一些NSLog的觀點看看發生了什麼。如果有幫助,我已將它們留在代碼中。它會顯示點1,2,5,然後等待。即使手機顯示桌面,清除提示3,7和4後仍然進入。

任何幫助或提示將不勝感激。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    NSLog(@"Point 1"); 
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL,NULL); 

    __block BOOL accessGranted = NO; 

    if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6 
     NSLog(@"Point 2"); 
     dispatch_semaphore_t sema = dispatch_semaphore_create(0); 

     ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 
      NSLog(@"Point 3"); 
      accessGranted = granted; 
      dispatch_semaphore_signal(sema); 
      NSLog(@"Point 4"); 
     }); 
     NSLog(@"Point 5"); 

     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
     dispatch_release(sema); 
    } else { // we're on iOS 5 or older 
     NSLog(@"Point 6"); 

     accessGranted = YES; 

    } 
    NSLog(@"Point 7"); 

    return YES; 
} 

回答

10

這裏的主要問題是,您在應用程序中執行此操作:didFinishLaunchingWithOptions:。總之,這需要轉移到另一個地方。 iOS限制了應用程序啓動過程中發生的情況 - 以及需要多長時間。對於一個簡單的應用程序,您可以將它移到您的主視圖控制器中,並在向最終用戶顯示任何結果之前檢查它。

當前,因爲您在此方法中使用了信號量,所以它阻止函數返回。 iOS對它等待的時間有嚴格的限制 - 然後它會殺死應用程序。總之,彈出窗口保持打開 - 但是當你按下OK時 - 應用程序被終止,因爲application:didFinishLaunchingWithOptions:方法沒有及時完成執行。

另外,我不會在這裏推薦信號量方法。有更好的方法來解決這個問題(見下文)。下面的代碼只是一個例子。

- (void)setupViewWithContactsData 
{ 
    // Do Something 
} 

- (void)setupViewWithoutContactsData 
{ 
    // Do Something because Contacts Access has been Denied or Error Occurred 
} 

- (void)viewDidLoad 
{ 
    [self checkForAddressBookAccess]; 
} 

- (void)checkForAddressBookAccess 
{ 
    if (ABAddressBookRequestAccessWithCompletion == NULL) 
    { 
     // iOS5 or Below 
     [self setupViewWithContactsData]; 
     return; 
    } 
    else 
    { 
     // iOS6 
     if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) 
     { 
      ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { 
      if(error) 
        { 
         [self setupViewWithoutContactsData]; 
        } 
        else 
        { 
         [self setupViewWithContactsData]; 
        } 
      }); 
     } 
     else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) 
     { 
      [self setupViewWithContactsData]; 
     } 
     else 
     { 
      [self setupViewWithoutContactsData]; 
     } 
    } 
} 
+0

謝謝你回答這麼快。我試圖將它移動到DataViewController didLoad方法,並有同樣的麻煩。僅供參考,我們基於我們的應用程序在頁面視圖應用程序模板。 – EricPerson 2013-03-14 19:40:17

+0

首先 - 信號量方法在這種情況下不是一個好的方法。最好使用異步方法而不是阻塞主線程。看看這個答案:http://stackoverflow.com/questions/12648244/programmatically-request-access-to-contacts-in-ios-6 – dtuckernet 2013-03-14 20:17:37

+0

得到它的工作。感謝您的幫助。祕密是把它放在[super viewDidLoad]行之後。 – EricPerson 2013-03-19 05:27:32