NSSharingService executeWithItems Зависает - PullRequest
0 голосов
/ 07 мая 2018

У меня была рутина рабочей доли, и теперь она нарушена. Некоторое время он не проверял и не изменял его, а теперь обнаружил, что он не работает. Когда я звоню

[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:

Inoperable Dialog for CKShare Process

1 Ответ

0 голосов
/ 11 июля 2018

Я публикую это как ответ, это больше похоже на работу, которую мне удалось получить. До сих пор нет ответа на вопрос, почему пользовательский интерфейс Apple не отвечает.

См. Код для приглашения участников без интерфейса Apple.

-(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)

Этот код, похоже, не работал, так как при приеме приглашений сначала ничего не получалось. Ничего не изменив, принимающие акции начали работать. Я не уверен, почему первоначальный сбой.

...