首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >合并用于UIDocument冲突的iCloud更改

合并用于UIDocument冲突的iCloud更改
EN

Stack Overflow用户
提问于 2018-06-02 04:01:02
回答 2查看 658关注 0票数 4

我已经花了几天的时间试图找到或者自己搞清楚,当通知UIDocumentStateChangedNotification触发并且文档的状态具有UIDocumentStateInConflict集时,如何以编程方式合并UIDocument更改。

我能找到的所有示例(Apples、等)都详细介绍了提示用户选择版本的方法。我找不到任何演示以编程方式合并的正确方法。这让我担心,因为它让我觉得它太不稳定,不值得信任,而且作为解决方案通常是避免的?到目前为止,我的经验加强了这一地位。

让我详细说明我的尝试中每一个有问题的领域。

1)为了合并目的,读取当前文档内容和NSFileVersion冲突版本的正确方法是什么?在同步过程中,使用任何带有完成块的东西都是非常麻烦的。谷歌(UIDocument)的UIDocument并不容易使用。实际上,作为一项规则,只读取UIDocument的推荐方法是什么?为什么只为阅读而打开文档?我试过使用UIDocument's readFromURL:,这对当前文档来说很好,但是如果我尝试在任何一个NSFileVersion's冲突版本上使用它,它就会读取当前版本,而不是URL上的版本(我已经使用MacOS终端深入挖掘./data/..DocumentRevisions V 100/PerUID/.文件来确认这一点。)。对于冲突版本,它的唯一工作方式是直接读取访问这些文件。(例如initWithContentsOfFile:) NSData )

2)一旦通过读取文件的变体,并设法合并,如何正确保存合并?这个真的没有我能找到的任何地方的记录。我唯一成功的方法是重新使用其中一个NSFileVersion's冲突文件,覆盖它,然后使用UIDocument's replaceItemAtURL:使其当前。我还尝试在使用replaceItemAtURL:之后使用UIDocument's revertToContentsOfURL:,但它只是在没有任何原因的情况下崩溃。由于合并似乎没有问题,所以我并不担心,但我认为我会把这个细节包括进来。

3) iPhone/iPad模拟器(V10.0)在我重新启动应用程序之前不会通知冲突。这是意料之中的还是我做错了什么?我之所以这样问是因为模拟器的调试菜单下有触发器iCloud Sync,它可以同步,但是冲突在下一个应用程序重新启动之前不会被标记出来。这仅仅是模拟器的限制吗?

谢谢,

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-11 05:30:03

经过几周的测试,我已经简化了我的UIDocument合并代码,并了解了哪些有效哪些不起作用。我做出的错误假设之一是,有必要将UIDocumentUIDocument的合并代码作为解决方案的一部分。这是一个非常不稳定的API调用,我发现最好避免,即使在@try()中使用它也不能防止不必要的崩溃。这让我移除它只是为了看看会发生什么,没有它的话冲突就会很好地解决。在developer.apple.com上,有文档冲突解决的示例代码,这意味着应该使用它。它似乎在post 2018年之后消失了。

剩下的唯一问题是,如果您有两个同时打开的设备,您可以进入一个竞争状态,因为两个设备都在不断地合并文档。

之前,我经历过零冲突版本,尽管文档标记为冲突,但最近我还没有看到这种情况发生。一定是我之前做错了什么。不过,我把代码保存在里面,因为它没有坏处。

我认为值得在这里提到的另一个问题是,如果您是UIDocument新手,那么值得记住的是,它是UIKit的一部分,您需要确保更新是在主线程上完成的。我发现this useful tip解决了我仍然存在的一些问题。

代码语言:javascript
复制
- (void) foobar {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleDocumentStateChange:)
                                                 name:UIDocumentStateChangedNotification
                                               object:_myDocument];
}

- (void) handleDocumentStateChange: (NSNotification *) notification {
    if (_myDocument.documentState & UIDocumentStateInConflict) {
        if (_resolvingConflicts) {
            return;
        }

        NSArray *conflictVersions = [NSFileVersion unresolvedConflictVersionsOfItemAtURL:_myDocument.fileURL];
        if ([conflictVersions count] == 0) {
            return;
        }
        NSMutableArray *docs = [NSMutableArray new];
        [docsData addObject:_myDocument.data]; // Current document data
        _resolvingConflicts = YES;
        for (NSFileVersion *conflictVersion in conflictVersions) {
            MyDocument *myDoc = [[MyDocument alloc] initWithFileURL:conflictVersion.URL];
            NSError *error;
            [myDoc readFromURL:conflictVersion.URL error:&error];
            if ((error == Nil) && (myDoc.data != Nil)) {
                [docs addObject:myDoc.data];
            }
        }

        if ([self mergeDocuments:docs]) {
            [self saveChangesToDocument];
        }

        for (NSFileVersion *fileVersion in conflictVersions) {
            fileVersion.resolved = YES;
        }
        [self deleteiCloudConflictVersionsOfFile:_myDocument.fileURL
                                      completion:^(BOOL success){
                                          self.resolvingConflicts = NO;
                                          dispatch_async(dispatch_get_main_queue(), ^{
                                              // On main thread for UI updates
                                              [[NSNotificationCenter defaultCenter] postNotificationName:kMyDocsUpdateNotification object:nil];
                                          });
                                      }];
    }
}

- (void) deleteiCloudConflictVersionsOfFile : (NSURL *) fileURL {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
        [fileCoordinator coordinateWritingItemAtURL:fileURL
                                            options:NSFileCoordinatorWritingForDeleting
                                              error:nil
                                         byAccessor:^(NSURL* writingURL) {
                                             NSError *error;
                                             if ([NSFileVersion removeOtherVersionsOfItemAtURL:writingURL error:&error]) {
                                                 NSLog(@"deleteiCloudConflictVersionsOfFile: success");
                                             } else {
                                                 NSLog(@"deleteiCloudConflictVersionsOfFile: error; %@", [error description]);
                                             }
                                         }];
    });
}
票数 2
EN

Stack Overflow用户

发布于 2018-06-09 06:46:56

这是对“为什么只为阅读而打开文档”部分的回答。

您只需要确保读取是“协调的”,即不与已被另一个进程打开且可能有未保存的更改的文件冲突。

下面是一种迭代NSDocument urls数组并以同步方式读取每个urls的方法,即这个例程在读取所有文件之前不会返回。它强制所有未保存更改的文件在进行任何读取之前保存自己。

代码语言:javascript
复制
// NSArray *urls - the urls of UIDocument files you want to read in bulk
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
NSError *error = nil;
[coordinator prepareForReadingItemsAtURLs:urls options:NSFileCoordinatorReadingWithoutChanges writingItemsAtURLs:@[] options:0 error:&error byAccessor:^(void (^ _Nonnull completionHandler)(void)) {
    for (NSURL *url in self->_urls) {
        NSError *error = nil;
        [coordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL * _Nonnull newURL) {
            // Read contents of newURL here and process as required
            // ...

        }];
        if (error) {
            NSLog(@"Error reading: %@ %@", url.path, error.localizedDescription);
        }
    }
    completionHandler();
}];
if (error) {
    NSLog(@"Error preparing for read: %@", error.localizedDescription);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50653387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档