Cocoa nsdocumentパッケージをSVNでうまく機能させるためのレシピ?
-
01-10-2019 - |
質問
パッケージスタイルのドキュメントを書くツールがあります。 NSDocumentを使用して実装され、次のNSDocumentメソッドをオーバーライドします。
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
error:(NSError **)outError;
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
ofType:(NSString *)typeName
error:(NSError **)outError;
これはすべて素敵ですが、バージョン管理下にあるドキュメントを保存する場合を除きます。 (.SVNディレクトリは保存されていません。
私のドキュメントをSVNでうまく機能させるための良いレシピはどこかにありますか?
解決
私はあなたのコードが毎回新鮮なファイルラッパーを作成することで機能すると推測しています -fileWrapperOfType:error:
呼ばれています。これは便利ですが、パッケージ内のディスクに存在する可能性のある追加ファイルを無視します。
代わりに、ディスク上の既存のコンテンツを指すファイルラッパーを作成/使用することから始めたらどうでしょう。ドキュメントの現在の状態に一致するようにラッパーを変更し、結果を返します。そのラッパーがディスクに書き出される場合、SVNファイルを適切に維持する必要があります。
他のヒント
これがマイクの答えに基づいた私の解決策です!
私のドキュメントパッケージは、通常の階層構造を備えたバンドルです。したがって、セーブ中に変異する4つのディレクトリがあります。
- セーブは新しいトップレベル(my.bundle)を作成します
- コンテンツディレクトリが変更されます(my.bundle/contents)
- リソースディレクトリが変更されます(my.bundle/contents/resources)
- ローカライズされたリソースが更新されます(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アーティファクトや「その他の」ローカリゼーションなど、バンドルに追加されなかったファイルを保存します。