NSSharingService performWithItems挂起

时间:2018-05-06 23:40:41

标签: macos cloudkit appkit ensembles nssharingservice

我有一个工作分享例程,现在已经坏了。有一段时间没有检查或修改它,现在发现它无法操作。当我打电话

[sharingService performWithItems:[NSArray arrayWithObject:itemProvider]];

我显示了一张分享表。它显示了当前成员的份额。表单无法使用,不接受任何输入或点击。我不能完全添加,删除或停止共享。当我关闭表单时,我的应用程序挂起,无法响应或关注。我必须杀死该应用程序并重新打开以使其再次运行。

这在过去几个月内一直很好。我没有改变任何东西,所以我对新问题感到非常惊讶。

我在这里添加了用于创建共享的代码:

NSString *shareOption = [[NSUserDefaults standardUserDefaults] objectForKey:kSet_CLOUD_SERVICE_USER_DEFAULT];
if ([shareOption isEqualToString:TTICloudKitShareOwnerService]) {
    CDEZipCloudFileSystem *zipFile = (CDEZipCloudFileSystem *)_cloudFileSystem;
    CDECloudKitFileSystem *fileSystem = (CDECloudKitFileSystem *)zipFile.cloudFileSystem;

    NSItemProvider *itemProvider = [[NSItemProvider alloc] init];
    [itemProvider registerCloudKitShare:fileSystem.share container:fileSystem.container];

    NSSharingService *sharingService = [NSSharingService sharingServiceNamed:NSSharingServiceNameCloudSharing];
    sharingService.subject = @"Share Workforce Data";
    sharingService.delegate = self;
    if ([sharingService canPerformWithItems:[NSArray arrayWithObject:itemProvider]]) {
        [sharingService performWithItems:[NSArray arrayWithObject:itemProvider]];

    // This is the point at which the Apple UI is presented but inoperable.
    // No changes can be made to the share.
    // The only way to dismiss the dialog is to quit or press escape.
    // Upon dismissal the app is either crashed or hung up.
    // Quitting the app and restart is only option to use the app again.
    // If not run from Xcode, requires force quit.

    }
} else {
    NSLog(@"Is Shared Ensemble");
    NSAlert *alert = [[NSAlert alloc] init];
    [alert addButtonWithTitle:@"Stop Share"];
    [alert addButtonWithTitle:@"Cancel"];
    [alert setMessageText:@"Shared Data Options"];
    [alert setInformativeText:@"You are participating in a shared file. Stop sharing will remove your participation and reset your data. You will no longer participate or have access to the shared information."];
    [alert setAlertStyle:NSAlertStyleWarning];

    if ([alert runModal] == NSAlertFirstButtonReturn) {
        [alert setInformativeText:@"Are you sure? You will no longer have access to shared data. You will need the owner of the share to resend an invitation to join the share."];
        if ([alert runModal] == NSAlertFirstButtonReturn) {
            // This actually does not remove user from sharing as intended.
            // I am sure that is my own implementation incomplete though.
            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            [defaults setNilValueForKey:kSet_CLOUDKIT_SHARE_OWNER_DEFAULT];
            [defaults setObject:TTICloudKitShareOwnerService forKey:kSet_CLOUD_SERVICE_USER_DEFAULT];
            [defaults synchronize];
            [self disconnectFromSyncServiceWithCompletion:^{
                // TODO: Need to wipe the existing Core Data info here. Leave them with no access to shared data.
                //      Also need to remove self from the share?
                [self reset];
                [self setupEnsemble];
            }];
        }
    }
}

创建共享和发送工作完美无缺,我一直在开发app和测试。目前我的测试与其他两个用户共享,仍然有效。事实上,我似乎无法找到一种方法来停止与这些用户共享或以任何方式改变当前的共享。

这是NSCloudSharingServiceDelegate代码:

-(NSCloudKitSharingServiceOptions)optionsForSharingService:(NSSharingService *)cloudKitSharingService shareProvider:(NSItemProvider *)provider
{
  return NSCloudKitSharingServiceAllowPrivate | NSCloudKitSharingServiceAllowReadWrite;
}

-(void)sharingService:(NSSharingService *)sharingService willShareItems:(NSArray *)items
{
  DLog(@"Will Share Called with items:%@",items);
}

-(void)sharingService:(NSSharingService *)sharingService didShareItems:(NSArray *)items
{
  DLog(@"Did share called");
}

-(void)sharingService:(NSSharingService *)sharingService didFailToShareItems:(NSArray *)items error:(NSError *)error
{
  DLog(@"Sharing service failed to share items, %@-", error);
  if (error.code == NSUserCancelledError) return;
  DLog(@"Failed to share, error- %@", error.userInfo);
  [self disconnectFromSyncServiceWithCompletion:^{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:kSet_CLOUDKIT_SHARE_OWNER_DEFAULT forKey:kSet_CLOUD_SERVICE_USER_DEFAULT];
    [defaults setNilValueForKey:kSet_CLOUDKIT_SHARE_OWNER_DEFAULT];
    [defaults synchronize];
  }];
}

很明显,我是少数几个发现这一点很重要的人之一,因为我已经仔细检查了网,发现几乎没有人讨论它。 Apple文档只是零。

这是Apple UI的屏幕截图,它不起作用:

Inoperable Dialog for CKShare Process

1 个答案:

答案 0 :(得分:0)

我将其发布为答案,更像是我设法开始工作的一项解决方法。关于Apple UI无法响应的原因,仍然没有答案。

请参见在没有Apple UI的情况下邀请参与者的代码。

-(void)addParticipantWithEmail:(NSString *)email toShare:(CKShare *)share inContainer:(CKContainer *)container
{
    [container discoverUserIdentityWithEmailAddress:(email) completionHandler:^(CKUserIdentity * _Nullable userInfo, NSError * _Nullable error) {
        if (!userInfo || error) {
            NSLog(@"Participant was not found for email %@", email);
            if (error) {
                NSLog(@"Error: %@", error.userInfo);
            } else {
                NSLog(@"No error was provided");
            }

            // abort
            return;
        }
        CKFetchShareMetadataOperation *fetchMetaDataOperation = [[CKFetchShareMetadataOperation alloc] initWithShareURLs:[NSArray arrayWithObject:share.URL]];
        fetchMetaDataOperation.shouldFetchRootRecord = YES;
        [fetchMetaDataOperation setPerShareMetadataBlock:^(NSURL * _Nonnull shareURL, CKShareMetadata * _Nullable shareMetadata, NSError * _Nullable error) {
            CKRecord *root = shareMetadata.rootRecord;

            if (!root) {
                NSLog(@"There was an error retrieving the root record- %@", error);
            } else {
                NSLog(@"Root is %@", root);
                NSLog(@"/n");
            }

            CKUserIdentityLookupInfo *info = userInfo.lookupInfo;
            CKFetchShareParticipantsOperation *fetchOperation = [[CKFetchShareParticipantsOperation alloc] initWithUserIdentityLookupInfos:[NSArray arrayWithObject:info]];
            [fetchOperation setShareParticipantFetchedBlock:^(CKShareParticipant * _Nonnull participant) {
                participant.permission = CKShareParticipantPermissionReadWrite;
                [share addParticipant:participant];
                CKModifyRecordsOperation *modifyOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:[NSArray arrayWithObjects:root, share, nil] recordIDsToDelete:nil];
                modifyOperation.savePolicy = CKRecordSaveIfServerRecordUnchanged;
                [modifyOperation setPerRecordCompletionBlock:^(CKRecord * _Nonnull record, NSError * _Nullable error) {
                    if (error) {
                        DLog(@"Error modifying record %@. UserInfo: %@", record, error.userInfo);
                    } else {
                        DLog(@"No Error Reported in Modify Operation");
                    }
                }];
                [container.privateCloudDatabase addOperation:modifyOperation];
            }];
            [fetchOperation setFetchShareParticipantsCompletionBlock:^(NSError * _Nullable operationError) {
                if (operationError) {
                    NSLog(@"There was en error in the fetch operation- %@", operationError.userInfo);
                    // Error may be a network issue, should implement a retry and possibly a limit to how many times to run it
                }
            }];
            [container addOperation:fetchOperation];
        }];
        [container addOperation:fetchMetaDataOperation];
    }];
}

现在,如果我将电子邮件地址传递给此功能,则只要用户在我的联系人中并且允许发现即可,就可以成功邀请他们共享。

这时,我通过iMe​​ssage手动向用户发送了指向共享的链接。从控制台复制了URL。我的意图是提供自己的表单来处理该问题。

在接收链接时,我使用Ensembles方法:

CDECloudKitFileSystem acceptInvitationToShareWithMetadata:metadata completion:^(NSError *error)

此代码似乎无效,最初接受邀请失败。没有进行任何更改,接受的共享就开始起作用。我不确定为什么最初的失败。