2016-05-06 21 views
1

私はこの本を "Mac OS X用のココアプログラミング"と呼んでいます。私は先生から始めました。代議員とのこのすべてのことはまだ私に少し不吉なことですが、私はただそれを解決させる必要があると思います。Objective-Cでこのデリゲートメソッドが自動的に呼び出されるのはなぜですか?

ただし、サイズ変更された高さが常に2xwidthであるように、メインウィンドウのデリゲートを実装する必要があるこの1つのエクササイズがありました。

だから私は4つのファイルしまっ:

  • AppDelegate.h
  • AppDelegate.m
  • WindowDelegate.h
  • WindowDelegate.m

AppDelegateがちょうど2つの標準的なファイルです新しいCocoaプロジェクトを開いたときに作成されます。私はこの作業をどのように達成するのかが分かりませんでしたので、解決策を見なければなりませんでした。 ソリューションは、単に新しいココアクラスを作成することでした、「WindowDelegat.h/.M」とそれにこれを追加しますが、実装ファイルです:

- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize { 
NSSize newSize = frameSize; 
newSize.height = newSize.width * 2; 
return newSize; 
} 

それから私は、インターフェイスビルダーを開いて、新しいオブジェクトを追加し、それ私の作っWindowDelegate。私はその後、Ctrlキーを押しながらWindowDelegateから実際のウィンドウにドラッグしてウィンドウの代理人にしなければなりませんでした。 クリックして実行したところ効果がありました。わーい!しかし、なぜ? 最初に私は、 "windowWillResize"は、ウィンドウのサイズが変更されるとすぐに呼び出されるこれらのコールバック関数の1つにすぎないと考えましたが、そうではありません。プログラムの一般的なライフサイクルはそれらを呼び出すか、@IBAction、ボタン、または異なるコントロール要素であるため、通常はメソッドが呼び出されます。 しかし、 "windowWillResize"はそれらのものではありません。だからなぜそれが呼ばれますか?

EDIT:問題解決済み!どうもありがとう!

これで、デリゲートをプログラムでウィンドウに接続しようとしています。したがって、私は、WindowDelegateの参照アウトレットをインタフェースビルダーの実際のウィンドウに削除しました。それは動作しますが、私はただ、これはどのように行うのが正しい道をそれていることを確認したい:

AppDelegate.h

#import <Cocoa/Cocoa.h> 
#import "WindowDelegate.h" 

@interface AppDelegate : NSObject <NSApplicationDelegate> 

@end 

をAppDelegate.m

#import "AppDelegate.h" 

@interface AppDelegate() 

@property (weak) IBOutlet NSWindow *window; 
@property (strong) WindowDelegate *winDeleg; 

@end 

@implementation AppDelegate 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 
    // Insert code here to initialize your application 
} 

- (void)applicationWillTerminate:(NSNotification *)aNotification { 
    // Insert code here to tear down your application 
} 

- (void)awakeFromNib { 
    [_window setOpaque:NO]; 
    NSColor *transparentColor = [NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:0.5]; 
    [_window setBackgroundColor:transparentColor]; 
    NSSize initialSize = NSMakeSize(100, 200); 
    [_window setContentSize:initialSize]; 

    _winDeleg = [[WindowDelegate alloc] init]; 
    [_window setDelegate: _winDeleg]; 
} 
@end 

WindowDelegate.h

#import <Foundation/Foundation.h> 
#import <Cocoa/Cocoa.h> 

@interface WindowDelegate : NSObject <NSWindowDelegate> 

@end 

WindowDelegate.m

#import "WindowDelegate.h" 

@implementation WindowDelegate 

- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize { 
    NSSize newSize = frameSize; 
    newSize.height = newSize.width * 2; 
    return newSize; 
} 

- (id)init { 
    self = [super init]; 
    return self; 
} 
@end 

なぜWindowDelegateの@propertyは強くなる必要がありますか? 私のwinDelegはオブジェクトではありませんか?なぜそれがオブジェクトであるのか_winDelegを通してアクセスする必要があります。私は変数にアクセスするためにアンダースコアが使用されますが?

ありがとうございました!

答えて

2

クリックして実行しました。わーい!しかし、なぜ?

NSWindow

のインスタンスはNSWindowDelegateプロトコルを実装する任意のオブジェクトを指すことができるdelegate特性を有し、かつそのプロトコルが-windowWillResize:toSize:方法を含むので。

これを数回読んでください。重要な理由は、独自のオブジェクトを作成して、NSWindowDelegateを実装し、-windowWillResize:toSize:を実装し、そのオブジェクトをウィンドウのデリゲートとして設定できるということです。次に、ユーザーがウィンドウのサイズを変更するたびに、メソッドが呼び出され、提案された新しいサイズが変更されます。

通常、プログラムのライフサイクル全体が呼び出されるため、または@IBAction、ボタン、または異なるコントロール要素であるため、メソッドが呼び出されます。しかし、 "windowWillResize"はそれらのものではありません。だからなぜそれが呼ばれますか?

これは実際にはそれほど違いはありません。デリゲートを「ヘルパーオブジェクト」と考えてください。新しいサブクラス全体を作成することなく、オブジェクトの動作をカスタマイズすることができます。 NSWindowDelegateオブジェクトは本質的にはNSWindowが約束している契約です。ユーザーがウィンドウのサイズを変更するなど、何かが起きたときはいつでも、デリゲートが存在し、それらのメソッドを実装している場合、ウィンドウはそのデリゲートオブジェクトの特定のメソッドを呼び出します。 NSApplicationの場合、これらのデリゲートメソッドの多くは、アプリケーションが起動する、または終了する、オペレーティングシステムからメッセージを受け取るなどのアプリケーションライフサイクルイベントです。 NSWindowの場合、デリゲートメソッドは、ユーザーが移動したり、非表示にしたり、表示したり、最大化したり、別の画面に移動するなど、ウィンドウに発生する可能性のある興味深いイベントに対応します。ネットワーク接続やムービープレーヤは、独自の興味深いイベントセットと独自のデリゲートプロトコルを持っています。

IBActionと表示されたメソッドは、実際には委譲メソッドではなく、ターゲット/アクションパラダイムを使用するコントロールのようなオブジェクトによって呼び出されるメソッドに過ぎないことに注意してください。 IBActionキーワードを使用すると、ボタンのようなものに対して可能なアクションとして表示するメソッドをIDEに知らせることができます。ウィンドウコントローラーとビューコントローラーでアクションを見つけることが多く、それらのオブジェクトは他のオブジェクトのデリゲートとして頻繁に動作しますが、アクション自体はデリゲートプロトコルの一部ではありません。たとえば、NSTableViewは、テーブルがどのように動作し、そのテーブルに表示されるかを決定するデリゲートオブジェクトを受け取ります。テーブルを管理するビューコントローラがテーブルのデリゲートであることがよくあり、同じビューコントローラがいくつかのボタンを管理し、ボタンがトリガするアクションメソッドを含むこともありますが、アクションはNSTableViewDelegateプロトコルの一部ではありません。したがって、あなたは彼らと呼ぶことはありませんdelegate methods.

+0

そして、インターフェイスビルダーでオブジェクトからウィンドウにドラッグすることによって、作成したWindowDelegateにデリゲートプロパティを自動的に設定します。 これを行うことで、 ":NSObject "プロトコルも私のWindowDelegateクラスに追加されますか?私はそれを見ることができないので、それだけで動作します。 – user148013

+0

正確です。あなたはクラス( 'WindowDelegate')を定義し、そのクラスのインスタンスを作成してそれをウィンドウのデリゲートにしました。 – Caleb

+0

プロトコルはインターフェイスを定義するだけで、オブジェクトが実装する必要のあるメソッドまたは実装できるメソッドのリストです。オブジェクトがプロトコルに準拠しているかどうか(すべてのオブジェクトに '-conformsToProtocol:'メソッドがあるかどうか)と、それが与えられたメソッドを実装しているかどうか( '-respondsToSelector:')を調べることができます。あなたは通常、デリゲートオブジェクトがどのような型であるか気にしません。あなたはそれが実装するメソッドだけを気にします。 – Caleb

関連する問題