使 Cocoa NSDocument 包与 svn 兼容的秘诀?

发布于 2024-09-16 04:15:26 字数 447 浏览 3 评论 0原文

我有一个可以编写包式文档的工具。它是使用 NSDocument 实现的,并覆盖以下 NSDocument 方法:

- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
                              error:(NSError **)outError;

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
                    ofType:(NSString *)typeName
                     error:(NSError **)outError;

这一切都很可爱,除了当我保存受版本控制的文档时。 (.svn 目录没有保留,等等)

是否有一个好的方法可以让我的文档在 svn 中正常运行?

I have a tool that writes package-style documents. It's implemented using NSDocument and overrides the following NSDocument methods:

- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
                              error:(NSError **)outError;

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
                    ofType:(NSString *)typeName
                     error:(NSError **)outError;

This is all lovely, except when I save a document that's under version control. (The .svn directories aren't preserved, etc.)

Is there a good recipe somewhere for making my documents play well with svn?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

像你 2024-09-23 04:15:26

我猜你的代码是通过每次调用 -fileWrapperOfType:error: 时创建一个新的文件包装器来工作的。这很方便,但会忽略包内磁盘上可能存在的任何其他文件。

因此,如果您首先创建/使用引用磁盘上现有内容的文件包装器,该怎么办?修改该包装器以匹配文档的当前状态,并返回结果。当该包装器写入磁盘时,应正确维护 svn 文件。

I'm guessing your code works by creating a fresh file wrapper each time -fileWrapperOfType:error: is called. This is convenient, but disregards any additional files that may exist on disk inside the package.

So instead, what if you start by creating/using a file wrapper that refers to the existing contents on disk. Modify that wrapper to match the document's current state, and return the result. When that wrapper is written out to disk, svn files should be properly maintained.

倾其所爱 2024-09-23 04:15:26

这是我根据迈克的回答提出的解决方案!

我的文档包是捆绑包,具有通常的层次结构...因此,在保存过程中我会更改四个目录:

  1. 保存创建一个新的顶级 (My.bundle)
  2. 内容目录已更改 (My.bundle/Contents)
  3. 资源目录已更改 (My.bundle/Contents/Resources)
  4. 本地化资源已更新 (My.bundle/Contents/Resources/en.lproj)

配方首先向文档类添加可变字典槽,以保留每个的内容这些目录。

@interface LMDocument : NSDocument {
@private
    // All this is for preserving SCM artifacts across saves…
    NSMutableDictionary * bundleWrappers;
    NSMutableDictionary * contentsWrappers;
    NSMutableDictionary * resourcesWrappers;
    NSMutableDictionary * localizedWrappers;
}

创建新文档时,它们一开始是空字典。

- (id)init;
{
    if ((self = [super init]) != nil) {
        bundleWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
        contentsWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
        resourcesWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
        localizedWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
    }
    return self;
}

读取现有文档时,将其替换为相关 fileWrapper 内容的可变副本。

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
                     ofType:(NSString *)typeName
                      error:(NSError **)outError;
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    bundleWrappers = [[fileWrapper fileWrappers] mutableCopy];
    contentsWrappers = [[[bundleWrappers objectForKey:@"Contents"] fileWrappers] mutableCopy];
    resourcesWrappers = [[[contentsWrappers objectForKey:@"Resources"] fileWrappers] mutableCopy];
    localizedWrappers = [[[resourcesWrappers objectForKey:@"en.lproj"] fileWrappers] mutableCopy];
    NSFileWrapper * infoPlistWrapper = [contentsWrappers objectForKey:@"Info.plist"];
    [contentsWrappers removeObjectForKey:@"Info.plist"]; // Replaced during save…
    // …
    NSMutableDictionary * localizedWrappersCopy = [localizedWrappers mutableCopy];
    [localizedWrappers enumerateKeysAndObjectsUsingBlock:^(id key,
                                                           id obj,
                                                           BOOL * stop)
     {
         if (mumble) { // If it's a file that will be replaced during save…
             [localizedWrappersCopy removeObjectForKey:key]; // Replaced during save…
             // …
         }
     }];
    localizedWrappers = localizedWrappersCopy;
    [pool drain];
    return YES;
}

最后,在保存文档时使用精心准备的字典。

- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
                               error:(NSError **)outError;
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSFileWrapper * localizedWrapper =
    [[NSFileWrapper alloc] initDirectoryWithFileWrappers:localizedWrappers];
    [resourcesWrappers setObject:localizedWrapper
                          forKey:@"en.lproj"];
    NSFileWrapper * resourcesWrapper =
    [[NSFileWrapper alloc] initDirectoryWithFileWrappers:resourcesWrappers];
    [contentsWrappers setObject:resourcesWrapper
                         forKey:@"Resources"];
    NSFileWrapper * contentsWrapper =
    [[NSFileWrapper alloc] initDirectoryWithFileWrappers:contentsWrappers];
    // …
    for (id item in mumble) {
        NSString * filename = [item filename];
        NSData * data = [item data];
        [localizedWrapper addRegularFileWithContents:data
                                   preferredFilename:filename];
    }
    [contentsWrapper addRegularFileWithContents:[self infoPlistData]
                              preferredFilename:@"Info.plist"];
    [pool drain];
    [bundleWrappers setObject:contentsWrapper
                       forKey:@"Contents"];
    NSFileWrapper * bundleWrapper =
    [[[NSFileWrapper alloc] initDirectoryWithFileWrappers:bundleWrappers] autorelease];
    return bundleWrapper;
}

现在,当编辑包文档时,应用程序会保留未添加到包中的所有文件,包括 SCM 工件和“其他”本地化!

Here is my solution based on Mike's answer!

My document packages are bundles, with the usual hierarchical structure… So there are four directories that I mutate during saves:

  1. The save creates a new top-level (My.bundle)
  2. The Contents directory is changed (My.bundle/Contents)
  3. The Resources directory is changed (My.bundle/Contents/Resources)
  4. The localized resources are updated (My.bundle/Contents/Resources/en.lproj)

The recipe starts with adding a mutable dictionary slot to your document class to preserve the contents of each of these directories.

@interface LMDocument : NSDocument {
@private
    // All this is for preserving SCM artifacts across saves…
    NSMutableDictionary * bundleWrappers;
    NSMutableDictionary * contentsWrappers;
    NSMutableDictionary * resourcesWrappers;
    NSMutableDictionary * localizedWrappers;
}

When creating a new document, these start out as empty dictionaries.

- (id)init;
{
    if ((self = [super init]) != nil) {
        bundleWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
        contentsWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
        resourcesWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
        localizedWrappers = [[NSMutableDictionary alloc] initWithCapacity:0];
    }
    return self;
}

When reading in an existing document, replace these with mutable copies of the relevant fileWrapper contents.

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
                     ofType:(NSString *)typeName
                      error:(NSError **)outError;
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    bundleWrappers = [[fileWrapper fileWrappers] mutableCopy];
    contentsWrappers = [[[bundleWrappers objectForKey:@"Contents"] fileWrappers] mutableCopy];
    resourcesWrappers = [[[contentsWrappers objectForKey:@"Resources"] fileWrappers] mutableCopy];
    localizedWrappers = [[[resourcesWrappers objectForKey:@"en.lproj"] fileWrappers] mutableCopy];
    NSFileWrapper * infoPlistWrapper = [contentsWrappers objectForKey:@"Info.plist"];
    [contentsWrappers removeObjectForKey:@"Info.plist"]; // Replaced during save…
    // …
    NSMutableDictionary * localizedWrappersCopy = [localizedWrappers mutableCopy];
    [localizedWrappers enumerateKeysAndObjectsUsingBlock:^(id key,
                                                           id obj,
                                                           BOOL * stop)
     {
         if (mumble) { // If it's a file that will be replaced during save…
             [localizedWrappersCopy removeObjectForKey:key]; // Replaced during save…
             // …
         }
     }];
    localizedWrappers = localizedWrappersCopy;
    [pool drain];
    return YES;
}

And finally, when saving a document use the dictionaries so painstakingly prepared.

- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
                               error:(NSError **)outError;
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSFileWrapper * localizedWrapper =
    [[NSFileWrapper alloc] initDirectoryWithFileWrappers:localizedWrappers];
    [resourcesWrappers setObject:localizedWrapper
                          forKey:@"en.lproj"];
    NSFileWrapper * resourcesWrapper =
    [[NSFileWrapper alloc] initDirectoryWithFileWrappers:resourcesWrappers];
    [contentsWrappers setObject:resourcesWrapper
                         forKey:@"Resources"];
    NSFileWrapper * contentsWrapper =
    [[NSFileWrapper alloc] initDirectoryWithFileWrappers:contentsWrappers];
    // …
    for (id item in mumble) {
        NSString * filename = [item filename];
        NSData * data = [item data];
        [localizedWrapper addRegularFileWithContents:data
                                   preferredFilename:filename];
    }
    [contentsWrapper addRegularFileWithContents:[self infoPlistData]
                              preferredFilename:@"Info.plist"];
    [pool drain];
    [bundleWrappers setObject:contentsWrapper
                       forKey:@"Contents"];
    NSFileWrapper * bundleWrapper =
    [[[NSFileWrapper alloc] initDirectoryWithFileWrappers:bundleWrappers] autorelease];
    return bundleWrapper;
}

Now when a package document is edited, the application preserves any files it didn't add to the bundle, including SCM artifacts and "other" localizations!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文