13

NSDocumentController サブクラスを持つ NSDocument に基づくアプリケーションがあります。私の NSDocument は、ファイル URL と Web サービスを使用するカスタム スキームの URL の両方で動作します。

を含むカスタム コードを使用して、読み込みと保存の多くを処理します-saveToURL:ofType:forSaveOperation:completionHandler:+autosavesInPlace戻りますYES

私が抱えている問題: カスタム URL スキームのドキュメントが起動時に復元されません。ファイル URL スキームを持つドキュメントは、ファイルに保存される通常のドキュメントと、自動保存される無題のドキュメントの両方です。

サーバーベースのドキュメントを開いたままアプリを終了すると、再起動時に NSDocument メソッドが呼び出されないように見えます。特に、4 つの初期化子はどれも呼び出されません。

  • -初期化
  • –initWithContentsOfURL:ofType:エラー:
  • –initForURL:withContentsOfURL:ofType:エラー:
  • –initWithType:エラー:

NSDocumentController メソッド-reopenDocumentForURL:withContentsOfURL:display:completionHandler:も呼び出されません。

ドキュメントの復元可能な状態はいつ、どのようにエンコードされますか? それらはいつ、どのようにデコードされますか?

4

2 に答える 2

14

NSDocument は で復元可能な状態をエンコードし-encodeRestorableStateWithCoder:、 NSDocumentController はドキュメントの復元可能な状態をデコードし、 でドキュメントを再度開く役割を果たし+restoreWindowWithIdentifier:state:completionHandler:ます。の役立つコメントを参照してくださいNSDocumentRestoration.h

NSDocument が URL をエンコードするとき、NSURL のブックマーク メソッドを使用しているように見えます。問題は、これらの方法がファイル システムの URL でしか機能しないことです。(ファイル以外の URL はエンコードされる可能性がありますが、適切にデコードされません。)

この問題を解決するには、カスタム スキームを使用する NSDocument インスタンスのエンコードをオーバーライドし、同様にそれらのドキュメントのデコードをオーバーライドします。

NSDocument サブクラス:

- (void) encodeRestorableStateWithCoder:(NSCoder *) coder {
    if ([self.fileURL.scheme isEqualToString:@"customscheme"])
        [coder encodeObject:self.fileURL forKey:@"MyDocumentAutoreopenURL"];
    else
        [super encodeRestorableStateWithCoder:coder];
}

NSDocumentController サブクラス:

+ (void) restoreWindowWithIdentifier:(NSString *) identifier
                               state:(NSCoder *) state
                   completionHandler:(void (^)(NSWindow *, NSError *)) completionHandler {

    NSURL *autoreopenURL = [state decodeObjectForKey:@"MyDocumentAutoreopenURL"];
    if (autoreopenURL) {
        [[self sharedDocumentController]
         reopenDocumentForURL:autoreopenURL
         withContentsOfURL:autoreopenURL
         display:NO
         completionHandler:^(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error) {

             NSWindow *resultWindow = nil;
             if (!documentWasAlreadyOpen) {

                 if (![[document windowControllers] count])
                     [document makeWindowControllers];

                 if (1 == document.windowControllers.count)
                     resultWindow = [[document.windowControllers objectAtIndex:0] window];
                 else {
                     for (NSWindowController *wc in document.windowControllers)
                         if ([wc.window.identifier isEqual:identifier]) {
                             resultWindow = wc.window;
                             break;
                         }
                 }
             }
             completionHandler(resultWindow, error);
         }
         ];
    } else
        [super restoreWindowWithIdentifier:identifier
                                     state:state
                         completionHandler:completionHandler];
}

動作または完了ハンドラーは、NSDocumentRestoration.h の Apple のメソッド コメントに従い、のとほぼ同じである必要がありますsuper

于 2012-12-20T19:15:04.643 に答える
5

ウィンドウ状態のエンコードは、 の 2 つの方法で有効になりNSWindowます。ウィンドウを呼び出すsetRestorable:と、再起動時に保存および復元できるウィンドウとしてマークされ、呼び出しsetRestorationClass:により、保存されたウィンドウの再作成を処理するクラスを指定できます。

デフォルトでは、AppKit は、オブジェクトNSDocumentControllerによって制御されるウィンドウの復元クラスとして設定されNSDocumentます。実際の復元は、プロトコル+restoreWindowWithIdentifier:state:completionHandler:で定義されたメソッドを呼び出すことによって行われます。NSWindowRestorationドキュメントの場合、NSDocumentControllerそのメソッドを実装し、メソッドに渡されNSDocumentたインスタンスでエンコードされた状態に基づいてオブジェクトを再作成します。NSCoder

したがって、理論的には、NSDocumentControllerそのメソッドをサブクラス化してオーバーライドすると、状態復元メカニズムによって保存されたドキュメントを復元する機会が得られます。ただし、私が知る限り、NSDocumentController状態を保存するために使用されるキーはどこにも文書化されていないため、保存されている状態から直接復元する信頼できる方法はないと思いますNSDocumentController

-encodeRestorableStateWithCoder:これをサポートするには、おそらく、エンコードされているものを実装することによって、ドキュメントの状態全体を自分でエンコードするか、ウィンドウのデリゲート メソッドをNSWindow実装する必要があります。window:willEncodeRestorableState:これらのメソッドは両方とも、NSCoder状態をエンコードするために使用できるインスタンスを渡します。ここで、状態を保存/復元するために必要なその他の関連データとともに、カスタム スキームの URL をエンコードします。次に、メソッドでその状態をデコードしrestoreWindowWithIdentifier:state:completionHandler:ます。

通常のファイル URL を持つドキュメントとカスタム URL を持つドキュメントがあるため、ドキュメントの状態のデコードを担当する別のクラスを作成し、それをカスタム URL を持つドキュメント専用の復元クラスとして設定することでアプローチします。NSDocumentControllerファイル URL を含むドキュメントを処理します。

于 2012-12-18T16:11:43.207 に答える