CKAccountStatus在未从ViewController调用时返回不同的值

时间:2015-02-14 20:31:07

标签: ios objective-c cloudkit

我在我的应用程序中使用Cloud Kit,它使用相机,只允许用户在登录iCloud时提交照片。因此,当用户单击相机按钮时,我调用CloudKit方法来获取用户的icloud状态,该状态返回CKAccountStatus值(0-3)。我最初在视图控制器中实现了它,它完美地工作。然后我做了一些重构并创建了一个CKManager类来容纳所有与CK相关的方法。所以现在当单击相机而不是直接在VC中调用容器中的CK方法时,我通过我的CKManager属性(懒惰实例化)中的方法调用它。它应该只返回值0-3,但由于某种原因它会一直返回448。但是,在CKManager日志记录中,我可以看到它正确记录我已登录到iCloud。所以有一个问题就是从那里转换回VC。我觉得这是一个线程/回调问题,我不是那么精通。

有人可以看一下代码,看看有什么明显我做错了吗?提前谢谢!

- (IBAction)cameraBarButtonPressed:(UIBarButtonItem *)sender {
NSLog(@"Entered cameraBarButtonPressed");

//CKContainer *container = [CKContainer defaultContainer];
dispatch_queue_t fetchQ = dispatch_queue_create("check user status", NULL);
__block CKAccountStatus userAccountStatus;

dispatch_async(fetchQ, ^{ // check user's CK status on different thread
    userAccountStatus = [self.ckManager getUsersCKStatus];
    NSLog(@"cameraBarButtonPressed userAccountStatus: %ld", userAccountStatus);

    if (userAccountStatus == CKAccountStatusAvailable) {
        //NSLog(@"User is logged into CK - user can upload pics!");
        UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
        cameraUI.delegate = self; // set the deleage for the ImagePickerController

        // check to see if the camera is available as source type, else check for photo album
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
        } else if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
            cameraUI.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        }

        [cameraUI setAllowsEditing:YES]; // let the user edit the photo
        // set the camera presentation style
        //cameraUI.modalPresentationStyle = UIModalPresentationFullScreen;
        cameraUI.modalPresentationStyle = UIModalPresentationCurrentContext;

        dispatch_async(dispatch_get_main_queue(), ^{ // show the camera on main thread to avoid latency
            [self presentViewController:cameraUI animated:YES completion:nil]; // show the camera with animation
        });
    } else if (userAccountStatus == CKAccountStatusNoAccount) {
        //NSLog(@"User is not logged into CK - Camera not available!");
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"iCloud Not Available" message:@"You must be logged into your iCloud account to submit photos and recipes. Go into iCloud under Settings on your device to login." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        dispatch_async(dispatch_get_main_queue(), ^{
            [alert show];
        });
    } else if (userAccountStatus == CKAccountStatusRestricted) {
        NSLog(@"User CK account is RESTRICTED !");
    } else if (userAccountStatus == CKAccountStatusCouldNotDetermine) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"iCloud Status Undetermined" message:@"We could not determine your iCloud status. You must be logged into your iCloud account to submit photos and recipes. Go into iCloud under Settings on your device to login." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        dispatch_async(dispatch_get_main_queue(), ^{
            [alert show];
        });
    } else { // did not get back one of the above values so show the Could Not Determine message
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"iCloud Status Undetermined" message:@"We could not determine your iCloud status. You must be logged into your iCloud account to submit photos and recipes. Go into iCloud under Settings on your device to login." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        dispatch_async(dispatch_get_main_queue(), ^{
            [alert show];
        });

    }
});
}

上面的代码是不起作用的代码。这是可行的代码。只是复制起始代码,其余部分从那时起就是多余的......

CKContainer *container = [CKContainer defaultContainer];
dispatch_async(fetchQ, ^{ // check user's CK status on different thread
    [container accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError *error) {
        if (error) {...

最后,这里是从CKManager调用的代码,用于不起作用的代码......

- (CKAccountStatus)getUsersCKStatus {

NSLog(@"Entered getUsersCKStatus...");
__block CKAccountStatus userAccountStatus;

[self.container accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError *error) {
    if (error) {
        NSLog(@"Error: Error encountered while getting user CloudKit status: %@", error.localizedDescription);
    } else {
        if (accountStatus == CKAccountStatusAvailable) {
            NSLog(@"Info: User is logged into CK - camera is available!");
            userAccountStatus = CKAccountStatusAvailable;
        } else if (accountStatus == CKAccountStatusNoAccount) {
            NSLog(@"Info: User is not logged into CK - Camera not available!");
            userAccountStatus = CKAccountStatusNoAccount;
        } else if (accountStatus == CKAccountStatusRestricted) {
            NSLog(@"Info: User CK account is RESTRICTED - what does that mean!?");
            userAccountStatus = CKAccountStatusRestricted;
        } else if (accountStatus == CKAccountStatusCouldNotDetermine) {
            NSLog(@"Error: Could not determine user CK Account Status: %@", error.localizedDescription);
            userAccountStatus = CKAccountStatusCouldNotDetermine;
        }
    }
}];

NSLog(@"CKAccountStatus: %ld", userAccountStatus);

return userAccountStatus;

}

1 个答案:

答案 0 :(得分:1)

在getUsersCKStatus中,您正在调用accountStatusWithCompletionHandler。这是一种异步方法。在你的情况下,它将在它的回调方法设置之前返回userAccountStatus。

您可以通过实现信号量使该方法同步来解决此问题。更好的方法是将回调块传递给该方法而不返回值。