この投稿が長くなって申し訳ありません。この問題で私の旅を文書化することを意図しています。
時々変更する必要がある Cocoa アプリの共有オブジェクトと、いくつかの異なる場所からアクセスできるように保存する最善の方法について質問があります。我慢してください。
クラスの実装
共有オブジェクトは、次のようなクラス クラスター (つまり、https://stackoverflow.com/a/2459385/327179 ) として実装されます (単なるクラス名であることに注意してくださいDocument。実際のクラスを必ずしも示しているわけではありませんします):
でDocument.h:
typedef enum {
DocumentTypeA,
DocumentTypeB
} DocumentType;
@interface Document : NSObject {}
- (Document *) initWithDocumentType:(NSUInteger)documentType;
- (void) methodA;
- (void) methodB;
@end
でDocument.m:
@interface DocumentA : Document
- (void) methodA;
- (void) methodB;
@end
@interface DocumentB : Document
- (void) methodA;
- (void) methodB;
@end
@implementation Document
- (Document *)initWithDocumentType:(NSUInteger)documentType;
{
id instance = nil;
switch (documentType) {
case DocumentTypeA:
instance = [[DocumentA alloc] init];
break;
case DocumentTypeB:
instance = [[DocumentB alloc] init];
break;
default:
break;
}
return instance;
}
- (void) methodA
{
return nil;
}
- (void) methodB
{
return nil;
}
@end
@implementation DocumentA
- (void) methodA
{
// ...
}
- (void) methodB
{
// ...
}
@end
@implementation DocumentB
- (void) methodA
{
// ...
}
- (void) methodB
{
// ...
}
@end
ユーザーとの対話方法Document
メニュー項目を介して、ユーザーは DocumentA と DocumentB を自由に切り替えることができます。
「スイッチ」が発生するとどうなるか
ユーザーが から に切り替えると、次の 2 つのことDocumentAがDocumentB必要になります。
- 私のプライマリ
NSViewController(MainViewController) は、新しいオブジェクトを使用できる必要があります。 - メイン ウィンドウのコンテンツ ボーダーにある
AppDelegateを更新する必要があります。NSTextField(FWIW、私はのコンセントを割り当てることしかできないようNSTextFieldですAppDelegate)
質問)
私は、シングルトンが散らかることなくグローバル参照を持つ方法としてかなり言及されているのを見てきましたAppDelegate(主にhereとhere )。そうは言っても、そのようなシングルトンの上書きに関する情報はあまり見たことがありません (私たちの場合、ユーザーが から [またはその逆] に切り替えるとDocumentA、DocumentBこのグローバル参照は新しいオブジェクトを保持する必要があります)。私はデザインパターンの専門家ではありませんが、シングルトンは破棄して再作成することを意図していないと聞いたことを覚えています...
したがって、これらすべてを考慮して、ここに私の質問があります:
- クラス クラスタをどのように保存しますか (適切にアクセスできるよう
MainViewControllerにAppDelegate)? - (頻繁
MainViewControllerに使用する人)と(プライマリウィンドウを管理する人[したがって、私の])の両方に知識を持たせることで、懸念を混合していますか?DocumentAppDelegateNSTextFieldDocument
この問題について間違って考えている場合は、遠慮なくお知らせください。この実装は、できるだけ直交的で正しいものにしたいと考えています。
ありがとう!
ステータスアップデート #1
@JackyBoy からのアドバイスのおかげで、私がたどったルートは次のとおりです。
Document「切り替え」時に「通知」AppDelegateしMainViewController、それらに新しく作成されたインスタンスを渡すものです。AppDelegateとの両方が、必要に応じて Singleton インスタンスを介してオブジェクトをMainViewController更新できます。Document
これが私の新しいファイルです(問題の核心を理解できるように簡略化されています):
でDocument.h:
#import <Foundation/Foundation.h>
@class AppDelegate;
@class MainViewController;
typedef enum {
DocumentTypeA,
DocumentTypeB
} DocumentType;
@interface Document : NSObject
@property (weak, nonatomic) MainViewController *mainViewControllerRef;
@property (weak, nonatomic) AppDelegate *appDelegateRef;
+ (Document *)sharedInstance;
- (id)initWithParser:(NSUInteger)parserType;
@end
でDocument.m:
#import "AppDelegate.h"
#import "Document.h"
#import "MainViewController.h"
@interface DocumentA : Document
// ...
@end
@interface DocumentB : Document
// ...
@end
@implementation Document
@synthesize appDelegateRef;
@synthesize mainViewControllerRef;
+ (Document *)sharedInstance
{
static XParser *globalInstance;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
// By default, I return a DocumentA object (for no particular reason).
globalInstance = [[self alloc] initWithDocumentType:DocumentA];
});
return globalInstance;
}
- (id)initWithDocumentType:(NSUInteger)documentType
{
Document *instance = nil;
switch (parserType) {
case DocumentTypeA:
instance = [[DocumentA alloc] init];
break;
case DocumentTypeB:
instance = [[DocumentB alloc] init];
break;
default:
break;
}
// QUESTION: Is this right? Do I have to store these references
// every time a new document type is initialized?
self.appDelegateRef = (AppDelegate *)[NSApp delegate];
self.mainViewControllerRef = self.appDelegateRef.mainViewController;
[self.appDelegateRef parserSwitchedWithParser:instance];
[self.mainViewControllerRef parserSwitchedWithParser:instance];
return instance;
}
@end
@implementation Xparser_NSXML
// ...
@end
@implementation DocumentA
// ...
@end
がとDocumentの存在を知っているという事実に悩まされるべきですか? さらに、オブジェクトが更新されると、両方に再通知されるという事実に悩まされる必要がありますか?AppDelegateMainViewControllerDocument AppDelegateMainViewController
いつものように、理想的な実装への探求が続く中、これに関する皆さんの注目に感謝しています。:)
ステータスアップデート #2
@Caleb からのコメントはNSNotification、この特定の問題に対して、ベースのセットアップの方がはるかに扱いにくいことを理解するのに役立ちました。
皆さんありがとう!