2011-02-10 11 views
25

私は、appdelegate、RootViewControoler、およびUIApplicationの関係を理解し​​ようとしています。ここまでは私が今までに考え出したものです:AppDelegateとRootViewControllerとUIApplicationの関係は何ですか?

アプリケーションを起動すると、main.mがロードされます。

ここからMainWindow.xibが読み込まれます。

あなたのMainWindow.xibでは、File's OwnerはUIApplicationタイプです。

UIApplicationのデリゲートをAppDelegateに設定しました。

AppDelegateのソースコードでは、RootViewControllerを最初のビューに設定できます。

これは正しいですか? AppDelegateが最初に実行するプロンプトは何ですか?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { } 

メソッド?

+1

これは正しいです! "didFinishLaunchingWithOptions"は実行する最初のメソッドです! –

答えて

44

Objective-Cアプリケーションが起動すると、main()という名前の関数を実行して起動します。それは "main.m"というファイルにある必要はありませんが、Xcodeのウィザードがこれを設定する方法です。ウィザード生産main()関数内

、このラインがあります:

int retVal = UIApplicationMain(argc, argv, nil, nil); 

アプリケーション全体を構成する「UIKitの」フレームワークを開始するものです。 UIApplicationMainの内部では、UIApplication型のオブジェクトが作成されます。また、アプリケーションの起動時にUIApplicationが行う処理の一部は、UIApplicationクラスのデリゲートメンバのapplicationDidFinishLaunchingWithOptionsメソッドを呼び出します。このデリゲートは、UIApplicationDelegateプロトコルに準拠するNSObjectのサブクラスであるProjectAppDelegateクラスのインスタンスになるようにMainWindow.xibファイルに設定されています。

は何が最初にそれはだ ラン...

ので、あなたのMainWindow.xibファイルにあなたは(うまくプロジェクトウィザードは、実際に接続をした)ファイルの所有者が(ある接続しているとAppDelegateを促しUIApplicationオブジェクト)の "delegate"コンセントを.xibファイルのUIApplicationDelegateオブジェクトに渡します。また、UIApplicationDelegateのクラスは、アプリケーションのUIApplicationDelegateサブクラスに設定されています。

"MainWindow.xib"については何も魔法はありません。 "Foo.xib"と呼ばれることがあります。Info.plistファイルの "Main nib file base name"というプロパティは "MainWindow"です。 MainWindow.xibの名前をFoo.xibに変更し、Info.plistの "Main nib file base name"を "Foo"に変更しようとすると、それはまだ動作しています。

EDIT:RootController

詳細は再び、いわゆる "RootController" について魔法何もありません。これは、Xcodeの新しいプロジェクトウィザードによって作成されたUIViewControllerサブクラスの名前です。

ウィザードは、ProjectAppDelegateとProjectViewControllerの2つのクラスのコードをプロジェクトに配置します。 ProjectAppDelegateクラスは2つの出口部材含ま:MainWindow.xibファイル内

IBOutlet UIWindow *window; 
IBOutlet ProjectViewController *viewController; 

を、UIWindowとProjectViewControllerの両方のインスタンスが配置され、そしてProjectAppDelegate上記コンセントにフックアップされています。

再び
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  

    // Override point for customization after application launch. 

    // Add the view controller's view to the window and display. 
    [self.window addSubview:viewController.view]; 
    [self.window makeKeyAndVisible]; 

    return YES; 
} 

、このことについては本当に魔法何も::プロジェクトウィザードがにあなたの「ルート」のViewControllerのビューを追加するコードを作成していない、あなたのProjectAppDelegateクラスでこのコードは何画面上に自分のものを取得します

ウィンドウのビューを表示し、ウィンドウを表示します。あなたの "ルート"ビューコントローラは.xibファイルで作成され、ProjectAppDelegateコンセントに接続されました。

ウィザードからファイルを使用せずに、自分でアプリケーションを作成することは非常に有益です。 .xibファイルの仕組みやコードオブジェクトとの関係については、多くのことを学びます。

+0

ちょうどupvotedので私はあなたが9997から10kに行くのを見ることができました:p。あまりにも悪い答えではありません。 –

+0

w00t :) Cool、thanks – Bogatyr

1

MainWindow.xibはinfo.plistにMain nib file base nameと定義されています。 MainWindow.xibでは、ロードする最初のコントローラーを定義します(ケースではRootViewController)。

didFinishLaunchingWithOptions:は、UIApplicationDelegateプロトコルの一部です。このメソッド(iOS4.0以降の)は、アプリケーションを起動するときに最初に呼び出されることが常に知られています。

1

AppDelegateは、UIApplicationの代理人です。UIApplicationクラスがライフサイクル中に投稿するすべての通知をリッスンします。 didFinishLaunching通知はその1つで、AppDelegateに前述のメソッドが呼び出されます。

+5

さて、デリゲートは実際には(NSNotificationCenterにオブザーバーとして登録する場合のように)通知を「聞いて」いません。代わりに、UIApplicationは 'respondsToSelector:'を使ってさまざまなメソッドを実装しているかどうかを調べ、それらが存在すればそれを呼び出します(ターゲットセレクタに自分自身で名前を付けることができる通知を聞くのではなく、 – DarkDust

15

iOSアプリの出発点は、常に通常のようなコードが含まれていますmain()機能(感謝@bogatyr)で、

int main(int argc, char *argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    int retVal = UIApplicationMain(argc, argv, nil, nil); 
    [pool release]; 
    return retVal; 
} 

UIApplicationMainの最後の2つのパラメータは重要であり、主要なクラス名を指定し、アプリケーションデリゲート。 nilの場合、Info.plistはメインウィンドウxib(通常MainWindow.xib)のために検索されます。

// If nil is specified for principalClassName, the value for NSPrincipalClass 
// from the Info.plist is used. If there is no NSPrincipalClass key specified, the 
// UIApplication class is used. The delegate class will be instantiated 
// using init. 
.. UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName); 

XIBを通じてファイルの所有者を設定する必要はありません、そして、彼らはこのUIApplicationMain機能で直接指定することができます。

principalClassNameは、文字列UIApplicationまたはUIApplicationのサブクラスにすることができます。同様にdelegateClassNameもこのメソッドで直接指定できます。デリゲートクラスは、ドキュメントの通り、initを使用してインスタンス化されます。文字列としてMyAppDelegate、まずのUIApplicationのインスタンスがインスタンス化され

UIApplicationMain(int argc, char *argv[], nil, @"MyAppDelegate"); 

、その後、私が思うNSClassFromStringを使用して、この文字列から委譲クラスを作成します - 私たちは私たちの委譲クラスを指定したとします。

delegateObjectがインスタンス化され、アプリケーションが準備されると、このdelegateObjectには、委任メソッドdidFinishLaunchingWithOptionsを使用して通知されます。

Class delegateClass = NSClassFromString(@"MyAppDelegate"); 
id <UIApplicationDelegate> delegateObject = [[delegateClass alloc] init]; 

// load whatever else is needed, then launch the app 
// once everything is done, call the delegate object to 
// notify app is launched 
[delegateObject application:self didFinishLaunchingWithOptions:...]; 

これは、nibが使用されていない場合、UIApplicationがプログラムで処理する方法です。真ん中のペン先を使うことはあまり変わらない。ユニバーサルのために

+0

main.mについては何も魔法はありません。foo.mと呼ばれることもあります。開始位置はint main(int argc、char * argv [])関数です。 – Bogatyr

+0

@Bogatyr - それは出発点である 'main()'関数です。あなたが言ったように 'main.m'には何も特別なものはありません。 – Anurag

1

- iPhone + iPadの - アプリを使用すると、いずれかのターゲット情報パネルにしたり、Info.plistNSMainNibFile~ipadNSMainNibFile~iphoneキーを追加することにより、各プラットフォーム上の異なるニブ負荷を指定することができます。代わりにMainWindow~ipad.xib NIBをターゲットに追加することもできます。これは、Info.plistのNSMainNibFileキーに基づいて、MainWindow.xibの代わりにiPadに読み込まれます。

ユニバーサルアプリケーションのコントロールとカスタマイズがさらに必要な場合は、手動で起動NIBを読み込むことができます。ユニバーサルプロファイルを持つ新しいiOSプロジェクトを作成するだけです。

は、Info.plist(ターゲット設定)に設定されているため、アプリケーションデリゲートが呼び出されたときにNIBが既にロードされています。通常、この設定ではMyAppDelegateオブジェクトもNIB(一部のIBOutlets)にアーカイブされ、NIBのFile's OwnerUIApplicationに設定されます。

2つの代替レイアウトに対応できるユニバーサルプロジェクトの場合、メインNIBファイルキーはInfo.plistのままです。そして、それは、UIApplicationMainでプログラムアプリケーションデリゲートオブジェクトをインスタンス化します。

#import "MYAppDelegate.h" 

int main(int argc, char *argv[]) 
{ 
    @autoreleasepool { 
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([MYAppDelegate class])); 
    } 
} 

次に、新しいステップを手動でルートMYViewControllerを作成することで、ご使用の環境や設定を確認し、application:DidFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    _window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 
    // Override point for customization after application launch. 
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
    _viewController = [[[MYViewController alloc] initWithNibName:@"MYViewController_iPhone" bundle:nil] autorelease]; 
    } else { 
    _viewController = [[[MYViewController alloc] initWithNibName:@"MYViewController_iPad" bundle:nil] autorelease]; 
    } 
    _window.rootViewController = _viewController; 
    [_window makeKeyAndVisible]; 
    return YES; 
} 

- (void)dealloc { 
    [_window release]; 
    [_viewController release]; 
    [super dealloc]; 
} 

を適切なNIBをロードし、ロード適切なNIB。この設定でFile's OwnerUIApplicationではなく、光沢のある新しいMYViewControllerです。必要に応じて、MYViewControllerは、多くの場合アプリケーションのコアモデルクラスをカプセル化し、データソースとして機能し、NIBのビューやその他のものを委譲するために、アプリケーションデリゲートを使用している可能性のあるものを多く採用することができます。

だからNIBに、いくつかのルートUIViewが期待していて、それがFile's OwnerMYViewController)のview口にフックアップする必要があります。

MYViewController.viewプロパティに初めてアクセスするまで、MYViewControllerのNIBは実際にはロードされません。それだけが[MyViewController viewDidLoad]と呼ばれます!これが発生する可能性が最も高いのは、ルートウィンドウに追加するときです。

上記のテンプレートコードでは、ルートUIWindowはアプリデリゲートによってインスタンス化されていますが、代わりにNIBに含めることができない理由はありません。これを行うことを選択した場合、注意してください。その場合、NIB内のウィンドウのrootViewControllerをファイルの所有者に設定すると、ウィンドウがアクティブになったときにコントローラのビューがウィンドウに追加されます。いずれにしても最初のNIBを構築するように注意してください。

MYViewControllerで管理したい場合は、アプリケーション代理人がルートUIWindowへの参照を持っている必要はありませんが、NIBからルートウィンドウを外してアプリケーションの代理人で管理すると、 。

それ以外(!)では、単一プラットフォームのアプローチとあまり変わりません。

関連する問題