8

履歴書(ユーザーインターフェイスの保存)の目的でNSViewControllerウィンドウ内をアーカイブするためのベストプラクティスは何ですか?私はそれをウィンドウコントローラーのメソッドでアーカイブしようとしましたが 、が呼び出されたときにビューコントローラーがアーカイブ解除されないことを確認しました 。encodeRestorableStateWithCoder:restoreStateWithCoder:

// 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;
    }
}

このビューコントローラには、独自のサブビューを管理する他のビューコントローラが含まれているため、NSCoderインスタンスでスコープが必要になることに注意してください。指定されたオブジェクトを下に渡すだけcoderで、アーカイブで名前が衝突します。

前もって感謝します!

4

2 に答える 2

6

状態の復元はで無料で機能しますが、のサブクラスとしてメソッドを実装している場合でもNSView無視されます。これは、ウィンドウに含まれるビューの一部を所有している可能性のあるNSViewControllerについてウィンドウが認識していないためだと思います。NSViewControllerNSResponder

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

常に機能させる方法は次のとおりです。復元API呼び出しをとの間NSViewでプロキシするだけNSViewControllerです。

このようなサブクラスNSView

@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

-invalidateRestorableStateこれで、サブクラスから呼び出すことができますNSViewController。Cocoaは、と話していると考えて、必要に応じてサブクラスをNSView自動的に呼び出します。-encodeRestorableStateWithCoder:-restoreStateWithCoder:NSViewController

于 2015-02-21T01:07:58.423 に答える
0

私は復元可能な状態をあまりいじりませんでした(Jonathon MahがDL3でそれを行いました)が、これを行う場合は、これら2つのメソッドを削除して、+ restoreableStateKeyPathsを実装してみます。例:

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

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

+ (NSArray *)restorableStateKeyPaths;

永続的である必要があるプロパティのパスを表す、キーパスのセットを返します。フレームワークは、KVOを介してこれらのキーパスを監視し、永続状態の一部としてそれらの値を自動的に永続化し、再起動時にそれらを復元します。キーパスの値は、キー付きアーカイブを実装する必要があります。基本実装は空の配列を返します。

于 2014-01-14T08:19:29.807 に答える