2013-02-13 9 views
7

resume(ユーザーインターフェースの保存)の目的で、NSViewControllerをウィンドウ内に保存するベストプラクティスはありますか?私はウィンドウコントローラのencodeRestorableStateWithCoder:メソッドでそれをアーカイブしようとしましたが、restoreStateWithCoder:が呼び出されたときにView Controllerがアーカイブ解除されないことがわかりました。単にアーカイブ内の名前の衝突が発生します提供coderオブジェクトの下方に渡す - このビューコントローラがNSCoderインスタンス内のいくつかのスコープが必要になりますので、自分のサブビューを管理し、他のビューコントローラが含まれていることをNSViewControllerをエンコードしてLionのユーザーインターフェイスを再開する機能

// NSWindowController subclass 

-(void)encodeRestorableStateWithCoder:(NSCoder *)coder 
{ 
    [super encodeRestorableStateWithCoder:coder]; 
    NSViewController* contentViewController = self.contentViewController; 
    if (contentViewController) { 
     [coder encodeObject:contentViewController forKey:BSContentViewControllerResumeKey]; 
    } 
} 

-(void)restoreStateWithCoder:(NSCoder *)coder 
{ 
    [super restoreStateWithCoder:coder]; 
    NSViewController* contentViewController = [coder decodeObjectForKey:BSContentViewControllerResumeKey]; 
    if (contentViewController) { 
     // somehow this never get executed since contentViewController always comes out nil 
     self.contentViewController = contentViewController; 
    } 
} 

注意。

ありがとうございます!

+0

セキュリティで保護されたコードを使用している可能性がありますが、代わりに '-decodeObjectOfClass:forKey:'を試しましたか? – Pol

答えて

5

状態の復元はNSView上の自由のために動作しますが、それはNSResponderのサブクラスとしてのメソッドを実装していてもNSViewControllerでは無視されます。私はそれが含まれているビューのいくつかを所有している可能性のあるNSViewControllerについてウィンドウがわからないためだと思います。

OS X Yosemiteでは、NSWindowがNSViewControllersを実際にサポートしているので動作するはずですが、テストケースには含まれていません。私は、新しいAPIを使用してNSViewControllersを追加/削除したり、サイドに作成したり、ビューを直接ウィンドウに追加したりする必要があるためだと思います。とにかくあなたのアプリがヨセミテ以前のシステムで動かされるようにしたいのなら、後者は実際に必要です。

これは、常に機能するようにする方法です。復旧API呼び出しをNSViewNSViewControllerの間でプロキシするだけです。このような

@interface GIView : NSView 
@property(nonatomic, weak) GIViewController* viewController; // Avoid retain-loops! 
@end 

@implementation GIView 

- (void)setViewController:(GIViewController*)viewController { 
    _viewController = viewController; 
} 

- (void)encodeRestorableStateWithCoder:(NSCoder*)coder { 
    [super encodeRestorableStateWithCoder:coder]; 

    [_viewController encodeRestorableStateWithCoder:coder]; 
} 

- (void)restoreStateWithCoder:(NSCoder*)coder { 
    [super restoreStateWithCoder:coder]; 

    [_viewController restoreStateWithCoder:coder]; 
} 

@end 

そしてNSViewController

@interface GIViewController : NSViewController 
@end 

@implementation GIViewController 

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 
    self.view.viewController = self; // This loads the view immediately as a side-effect 
    } 
    return self; 
} 

- (void)dealloc { 
    self.view.viewController = nil; // In case someone is still retaining the view 
} 

- (void)invalidateRestorableState { 
    [self.view invalidateRestorableState]; 
} 

@end 

今、あなたは自動的に呼び出されます、それはNSViewに話して考えて、NSViewControllerサブクラスとCocoaから-invalidateRestorableStateを呼び出すことができます。このような

サブクラスNSView必要に応じてNSViewControllerサブクラスに-encodeRestorableStateWithCoder:-restoreStateWithCoder:を追加します。

+0

こんにちは、これはすてきなトリックです:)私はMacアプリケーションでも復元を実装しようとしています。NSViewサブクラスでも復旧呼び出しを取得できません。それが何であるか、どんな考えですか?私はそれのための新しいスレッドを作成しました:http://stackoverflow.com/q/42010026/3251155 –

0

例えば、私は復元状態であまり混乱していない(ジョナサン麻雀はDL3のためにそれをやった)が、私はこれをやっていた場合、私は、これらの2つのメソッドを削除しようとすると、+ restorableStateKeyPathsを実装したい:

+ (NSArray *)restorableStateKeyPaths; 
{ 
    return @[@“contentViewController.firstInterestingStateProperty”, @“contentViewController.secondInterestingStateProperty”]; 
} 

をと機械がそれを私のためにすべて処理したかどうかだけを見てください。

+ (NSArray *)restorableStateKeyPaths; 

は永続的でなければならない特性の経路を表す、キーパスのセットを返します。フレームワークは KVOを介してこれらのキーパスを観察し、永続的な 状態の一部としてその値を自動的に保持し、再起動時にそれらの値を復元します。キーパス の値は、キー付きアーカイブを実装する必要があります。基本実装は の空の配列を返します。

+0

これは 'contentViewController'がウィンドウコントローラの同じクラス(復元可能なプロパティの同じセット)である場合に機能します。残念なことに、View Controllerは数多くのクラスの間で交換可能です。左の「タブ」バーで選択した内容に応じて、スワップ可能なビューを持つ公式Twitterアプリを考えてみましょう。同様に、ビューコントローラは、それらが制御する最上位ビューに従ってスワップ可能である。 – adib

関連する問題