如何获取地址簿权限弹出窗口?
我正在指导一个七年级和八年级的团队,他们致力于开发一个小应用程序,以大格式显示地址簿中的选项。你可以在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;
}
这里的主要问题是,您在应用程序中执行此操作: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方法,并有同样的麻烦。仅供参考,我们基于我们的应用程序在页面视图应用程序模板。 – EricPerson 2013-03-14 19:40:17
首先 - 信号量方法在这种情况下不是一个好的方法。最好使用异步方法而不是阻塞主线程。看看这个答案:http://stackoverflow.com/questions/12648244/programmatically-request-access-to-contacts-in-ios-6 – dtuckernet 2013-03-14 20:17:37
得到它的工作。感谢您的帮助。秘密是把它放在[super viewDidLoad]行之后。 – EricPerson 2013-03-19 05:27:32