1

我有一个工作共享程序,现在它被打破了。有段时间没有检查或修改它,现在发现它无法使用。当我打电话

[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];
            }];
        }
    }
}

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

这是 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 的屏幕截图:

CKShare 进程无法操作的对话框

4

1 回答 1

1

我将其发布为答案,更像是我设法开始工作的解决方法。仍然没有回答为什么 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];
    }];
}

现在看来,如果我将电子邮件地址传递给此功能,他们就会被成功邀请分享,前提是用户在我的联系人中并且允许被发现。

此时,我通过 iMessage 手动向用户发送共享链接。从控制台复制 URL。我的目的是提供我自己的表格来处理这个问题。

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

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

此代码似乎不起作用,接受邀请最初失败。在没有改变任何东西的情况下,接受股票开始起作用。我不确定为什么初始失败。

于 2018-07-11T13:21:36.633 回答