3

このコードは以前に投稿されており、私が収集したものからも使用されています。連絡先にアクセスできるかどうかがわかるまで、コードを続行しないようにする必要がある状況にあります。

Xcode 5.0.2 および iOS 6 では、これは問題なく動作します。iOS 7 では、永久にハングアップし、アプリを終了すると、連絡先へのアクセスを許可するよう求めるダイアログ ボックスが表示されます。

ABAddressBookRef addressBook = ABAddressBookCreate();

__block BOOL accessGranted = NO;

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

ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    accessGranted = granted;
    dispatch_semaphore_signal(sema);
});

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

これで遊んでみると、BOOLをNOに設定してから、ブロック内でYESに設定するだけです。ブロックの後、変数がYESであることを確認するwhileループを配置し、1秒間スリープしました。6では完全に正常に動作し、7ではブロック内のNSLogステートメントに到達せず、ログステートメントを出力するwhileループで永遠に立ち往生しています。

私はここで本当に不自由なことをしていますか?それとも、この方法は 7 でうまくいかないのでしょうか?

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    if (granted)
    {
        self.myAddressBook = addressBook;
    }

    done = YES;
    NSLog(@"in block, done is %@", done ? @"YES" : @"NO");
    didGrant = granted;

    //dispatch_semaphore_signal(sema);
});

while (!done)
{
    NSLog(@"done is %@", done ? @"YES" : @"NO");
    sleep(1);
}
4

1 に答える 1

5

私は同じ問題を抱えていましたが、連絡先へのアクセスを要求するダイアログボックスがとにかくアプリをブロックすることに気付いたので、デッドロックが発生している可能性があります. だから私はセマフォを捨てて、次のようなことをしました(iOS 7.1.1でテストされ、動作します):

ABAddressBookRef addressBook = ABAddressBookCreate();

MyController * __weak weakSelf = self;

if (ABAddressBookRequestAccessWithCompletion != NULL)
{ // we're on iOS 6
    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
    {
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf accessGrantedForAddressBook];
            });
        });    
    }
    else
        if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized); //Maybe add something here to handle kABAuthorizationStatusRestricted
            [self accessGrantedForAddressBook];
    }
}
else // we're on iOS 5 or older
     [self accessGrantedForAddressBook];

これは、Apple がドキュメントで行っていることと非常によく似ています(ABAddressBookRequestAccessWithComplete を検索してください)。その上、ABAddressBookRequestAccessWithCompletion が非同期であり、それを待機するポイントは何ですか (こちらを参照)。

于 2014-07-04T09:39:13.410 に答える