【问题标题】:How can I get the address book permission popup to display on top?如何让地址簿权限弹出窗口显示在顶部?
【发布时间】:2013-03-14 15:09:35
【问题描述】:

我正在指导一个由 7 年级和 8 年级学生组成的团队,他们正在开发一个小型应用程序,该应用程序以大格式显示地址簿中的选择。你可以在 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 秒,此时应用程序似乎关闭,显示下方的权限提示。接受将我们发送到桌面。当我们重新打开应用程序时,它就像权限已被清除一样工作。或者,如果我们在屏幕为黑色时点击主页按钮(手机上的方形按钮),它会关闭以显示上述权限提示。权限窗口应在很短的延迟后显示,然后在用户授予权限时将我们留在应用程序中。

我们停留在一些 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;
}

【问题讨论】:

    标签: ios addressbook abaddressbook


    【解决方案1】:

    这里的主要问题是您在 application: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];
             }
        }
    }
    

    【讨论】:

    • 感谢您这么快回答。我尝试将其移至 DataViewController didLoad 方法并遇到了同样的问题。仅供参考,我们的应用程序基于页面视图应用程序模板。
    • 首先 - 在这种情况下,信号量方法不是一个好的方法。最好使用异步方法而不是阻塞主线程。看看这个答案:stackoverflow.com/questions/12648244/…
    • 让它工作。感谢您的帮助。秘诀是把它放在 [super viewDidLoad] 行之后。
    • 您正在测试“错误”以确定用户是否允许访问 - 这个测试肯定应该是“已授予”?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多