6

私のアプリケーションでは、ユーザーは現在開いているドキュメントの名前を変更できます。これは些細なことで、問題なく動作しますが、私には理解できない本当に厄介なバグが 1 つあります。ファイルの名前が変更されると、ユーザーが次にドキュメントを保存しようとしたときに、AppKit が (親切に) 警告します。ユーザーが「OK」と言うと、すべてが通常どおり続行されます。これは、アプリケーションの外部の何かがドキュメントを変更した場合には意味がありますが、実際にドキュメント自体によって変更された場合には意味がありません。

コードは次のようになります。

-(void)renameDocumentTo:(NSString *)newName {
  NSURL *newURL = [[[self fileURL] URLByDeletingLastPathComponent]
                                   URLByAppendingPathComponent:newName];

  NSFileManager *fileManager = [NSFileManager defaultManager];
  [fileManager moveItemAtURL:[self fileURL] toURL:newURL];
  NSDictionary *attrs = [fileManager attributesForItemAtPath:[newURL path] error:NULL];

  [self setFileURL:newURL];
  [self setFileModificationDate:[attrs fileModificationDate]];
}

ドキュメントに新しい URL と変更日を明示的に設定するだけで十分だと思う人もいるかもしれませんが、残念ながらそうではありません。Cocoa は引き続き警告を生成します。

順序を変更してみました (ドキュメントに新しい URL を設定し、ファイルの名前を変更します) が、これは役に立ちません。

CocoaDev の古い投稿でユーザーが提案した修正も試しました。

[self performSelector:@selector(_resetMoveAndRenameSensing)];

ただし、これでも警告は止まりません。文書化された API を使用してこれを行う適切な方法が必要だと思いますユーザーがプロジェクト ツリーのファイルをクリックして別の名前に変更した場合、Xcode はどのように処理しますか。ユーザーが実際に名前変更を実行したため、名前変更についてユーザーに警告しません。

私は何をする必要がありますか?

4

3 に答える 3

3

これについては、メイン ドキュメントにはあまり記載されていません。代わりに、10.5 リリース ノートを参照してください

(Xcode の場合は長い歴史があり、if がNSDocumentプロジェクト内のファイルに使用されていなくても不思議ではありません)

ファイルを移動しても変更日は変わらないことに注意してください-setFileModificationDate:

したがって、1つの可能性は、NSDocumentの通常の警告を次のようにバイパスすることです。

- (void)saveDocument:(id)sender;
{
    if (wasRenamed)
    {
        [self saveToURL:[self fileURL] ofType:[self fileType] forSaveOperation:NSSaveOperation delegate:nil didSaveSelector:nil contextInfo:NULL];
        wasRenamed = NO;
    }
    else
    {
        [super saveDocument:sender];
    }
}

理想的には、次の可能性も確認する必要があります。

  1. ドキュメントの名前を変更するようにアプリに依頼する
  2. 名前が変更されたファイルは、別のアプリによって変更/移動されます
  3. ユーザーがドキュメントを保存する

その時点で、通常の警告シートが表示されるようにします。おそらく次のような方法で実現できます。

- (void)renameDocumentTo:(NSString *)newName
{
    // Do the rename

    [self setFileURL:newURL];
    wasRenamed = YES; // MUST happen after -setFileURL:
}

- (void)setFileURL:(NSURL *)absoluteURL;
{
    if (![absoluteURL isEqual:[self fileURL]]) wasRenamed = NO;
    [super setFileURL:absoluteURL];
}

- (void)setFileModificationDate:(NSDate *)modificationDate;
{
    if (![modificationDate isEqualToDate:[self fileModificationDate]]) wasRenamed = NO;
    [super setFileModificationDate:modificationDate];
}

それ以外の場合、私が見ることができる他の唯一の選択肢は、ドキュメントのサブクラスに実際に保存するのではなく、現在のドキュメントを移動するように促すいくつかのカスタム パラメーターを使用して、標準の保存/書き込みメソッドの 1 つを呼び出すことです。もっとトリッキーだと思います。おそらくあなた自身を定義しますNSSaveOperationTypeか?

この手法を使用すると、ドキュメント システムは、名前の変更が保存に似た操作の一部であることを理解する必要がありますが、確認するにはかなりの実験が必要です。

于 2010-12-10T12:38:38.287 に答える
1

NSSaveOperation@Mike's answer から多くのインスピレーションを得て、に再ルーティングすることで「移動」メッセージが表示されないようになりましたNSSaveAsOperation。私の NSDocument サブクラスでは:

  • オーバーロードsaveDocumentWithDelegate:didSaveSelector:contextInfo:して、保存 URL とドキュメント タイプを決定します (これらを に割り当てますself)。古い fileURL が存在する場合は、それを新しい場所に移動します
  • 内部では、代わりにsaveDocumentWithDelegate:didSaveSelector:contextInfo:呼び出しをリダイレクトします[self saveToURL:self.fileURL ofType:self.fileType forSaveOperation:NSSaveAsOperation completionHandler: ...][super saveDocumentWithDelegate:didSaveSelector:contextInfo:]

これは私にとってはうまくいきます。

于 2015-12-11T07:45:39.340 に答える
0

ユーザーの質問にプログラムで回答することはできませんか? または、名前を変更した直後に保存することもできます。この方法では、ユーザーはすべての回答を一度に取得できます。

この問題はしばらくの間発生していることがわかりました。そのため、参照を読むように言っても何の役にも立たないと思います..

あなたの問題を直接解決するわけではありませんが、私が少し助けてくれることを願っています

于 2010-12-10T12:46:58.670 に答える