Xcode で新しい Cocoa アプリケーション プロジェクトを作成し、NSOutlineView オブジェクトと NSTextView オブジェクトをウィンドウに追加しました。これら 2 つのオブジェクトは、MyOutlineView および MyTextView としてサブクラス化されました。その後、2 つのアウトレットを作成し、以下のようなコードを記述しました。
私が見つけた問題は、アプリケーションが実行時に 2 つの異なる MyOutlineView インスタンスを持っていることです。作業中の (有効な) アウトライン ビュー インスタンスは、myOutlineView アウトレット インスタンスと等しくありません。私は何が欠けていますか?
//
// AppDelegate.h
#import <Cocoa/Cocoa.h>
#import "MyOutlineView.h"
#import "MyTextView.h"
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
@property (weak) IBOutlet MyOutlineView *myOutlineView;
@property (unsafe_unretained) IBOutlet MyTextView *myTextView;
@end
//
// AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)n
{
NSLog(@"AppDelegate.myOutlineView(INVALID)::%@", _myOutlineView);
NSLog(@"AppDelegate.myTextView::%@", _myTextView);
}
@end
//
// MyOutlineView.h
#import <Cocoa/Cocoa.h>
@interface MyOutlineView : NSOutlineView <NSOutlineViewDataSource>;
@end
//
// MyOutlineView.m
#import "MyOutlineView.h"
@implementation MyOutlineView
- (id)initWithCoder:(NSCoder *)aDecoder
{
// This method is called first.
self = [super initWithCoder:aDecoder];
NSLog(@"MyOutlineView initWithCoder(INVALID)::%@", self);
return self;
}
- (id)initWithFrame:(NSRect)frame
{
// This method is also called but through a different instance with first one.
self = [super initWithFrame:frame];
NSLog(@"MyOutlineView initWithFrame(valid)::%@", self);
return self;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
NSLog(@"MyOutlineView data source delegate(valid)::%@", self);
return 0;
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
return NO;
}
@end
//
// MyTextView.h
#import <Cocoa/Cocoa.h>
@interface MyTextView : NSTextView
@end
//
// MyTextView.m
#import "MyTextView.h"
@implementation MyTextView
- (id)initWithCoder:(NSCoder *)aDecoder
{
// This method is called.
self = [super initWithCoder:aDecoder];
NSLog(@"MyTextView initWithCoder::%@", self);
return self;
}
- (id)initWithFrame:(NSRect)frame
{
// But this method is NOT called at all.
self = [super initWithFrame:frame];
NSLog(@"MyTextView initWithFrame::%@", self);
return self;
}
@end
出力:
MyTextView initWithCoder:: [MyTextView: 0x10013be80]
MyOutlineView initWithCoder(INVALID):: [MyOutlineView: 0x10014bc90]
MyOutlineView initWithFrame(valid):: [MyOutlineView: 0x1001604a0]
MyOutlineView data source delegate(valid)::[MyOutlineView: 0x1001604a0]
AppDelegate.myOutlineView(INVALID):: [MyOutlineView: 0x10014bc90]
AppDelegate.myTextView:: [MyTextView: 0x10013be80]
このため、「AppDelegate.myOutlineView = self;」を配置する必要があります。AppDelegate の関連メソッドを呼び出す場所ならどこでも、MyOutletView の実装に挿入します。それは自然ではないようです。