制作Cocoa NSDocument包的方法与svn配合得很好?

时间:2010-08-24 19:03:19

标签: cocoa svn package nsdocument nsfilewrapper

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

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

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

除非我保存受版本控制的文档,否则这一切都很可爱。 (不保留.svn目录等)

在某些地方是否有一个很好的配方可以让我的文档与svn一起播放?

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

以下是基于迈克答案的解决方案!

我的文档包是捆绑包,具有通常的层次结构......所以我在保存期间有四个目录变异:

  1. 保存会创建一个新的顶级(My.bundle)
  2. 内容目录已更改(My.bundle / Contents)
  3. 更改了Resources目录(My.bundle / Contents / Resources)
  4. 更新本地化资源(My.bundle / Contents / Resources / en.lproj)
  5. 配方首先在文档类中添加一个可变字典槽,以保留每个目录的内容。

    @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工件和“其他”本地化!