2010-12-03 11 views
5

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

コードは次のようなものだ:

-(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と変更日時を設定すると思うだろう、残念ながらそうではありません。ココアは警告を生成します。

私は順序を変更しようとしましたが(文書の新しいURLを設定してからファイルの名前を変更しています)、これは役に立ちません。

私もCocoaDevで古いポスト上のユーザを超えるによって提案された修正を試してみた:

[self performSelector:@selector(_resetMoveAndRenameSensing)]; 

でも、これはしかし、警告を停止していない、と私はそこを推測しているがあることをを持っています文書化されたAPIを使用してこれを行う適切な方法。ユーザーがプロジェクトツリー上のファイルをクリックして名前を変更すると、Xcodeはどのように処理するのですか?ユーザーが実際に名前を変更したため、ユーザーに名前の変更について警告することはありません。

誰かが私がする必要があるかもしれない光を放つことができれば、それはすばらしいでしょう、ありがとう!

+0

私はこれに助けを求める賞金を始めました。残念ながら、私は本当にどこにも行きません。単純なテストケースは、.txtファイル(または実際には何か)を開く空のドキュメントアプリケーションを作成するだけです。開いたファイルの名前を変更して新しいURLでドキュメントオブジェクトを更新するメニュー項目を追加します。名前の変更後に初めてファイルを保存しようとすると、警告を回避しようとしています。 – d11wtq

+0

ああ、これは文書が現在編集されている場合には動作する必要があります。保存されていない変更が存在する場合、ディスクに保存し、文書を閉じ、ファイルを移動してから再度開くと、望ましくない効果が生じる可能性があります。 – d11wtq

答えて

3

メイン文書にはそれほど多くはありません。代わりに、10.5リリースノート:http://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html%23X10_5Notesを見てください。「NSDocumentは時間を節約して変更されたファイルを確認しています」

(Xcodeの場合は長い歴史を持っていて、

ファイルを移動しても変更日は変更されないので、-setFileModificationDate:を呼び出すことは効果がない可能性があります。

だから、一つの可能​​性はとても似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. ユーザーは文書を保存します

その時点で、通常の警告シートが必要になります。そうでなければ、私が見ることができる唯一の他の選択肢を移動するには、ドキュメントのサブクラスを促し、いくつかのカスタムパラメータを持つ標準の保存/書き込みメソッドのいずれかを呼び出すことです

- (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]; 
} 

:おそらくのようなものによって達成することができます現在の文書を実際に保存するのではなく、私は考えるのが面倒だろう。おそらくあなた自身のNSSaveOperationTypeを定義しますか?

このテクニックでは、リネームは保存のような操作の一部であることを理解する必要がありますが、確かめるにはかなりの実験が必要です。

+0

良い答え、ありがとう。私はすでに成功していないのに、あなたの2番目の提案を試していました。私はあなたの最初の提案(saveDocumentをオーバーライド:と一時的なwasRenamedフラグを使用して)うまくいくはずだと思います。ちょうど今それをテストしようとしています。 – d11wtq

+0

それは動作します!どうもありがとうございました :) – d11wtq

0

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

私はそう

が、それは修正されませんが、私は少しを助けた希望... referenceは私が推測する何か良いを行うことはありません読み取るためにあなたを伝える、この問題が稼働していくつかの時間のためであることがわかり

あなたの問題を直接

0

@ Mikeの回答から多くのインスピレーションを得て、NSSaveOperationNSSaveAsOperationに再ルーティングすることで、もうメッセージが表示されなくなりました。私のNSDocumentのサブクラスで:

  • 私は(selfにそれらを割り当てること)保存URLおよびドキュメントの種類を決定するためにsaveDocumentWithDelegate:didSaveSelector:contextInfo:をオーバーロード。古いfileURLが存在する場合、私は新しい場所saveDocumentWithDelegate:didSaveSelector:contextInfo:インサイド
  • に私は[self saveToURL:self.fileURL ofType:self.fileType forSaveOperation:NSSaveAsOperation completionHandler: ...]代わりの[super saveDocumentWithDelegate:didSaveSelector:contextInfo:]これが私の作品

にコールをリダイレクトすることを移動します。

関連する問題