25

appdelegate、RootViewControoler、およびUIApplicationの間の関係を理解し​​ようとしています。これが私がこれまでにちょっと理解したことです:

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

ここから、MainWindow.xibがロードされます。

MainWindow.xibでは、ファイルの所有者はUIApplicationタイプです。

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

AppDelegateのソースコードで、RootViewControllerを最初に表示されるビューに設定できます。

これは正しいですか?AppDelegateに最初に実行するように促すもの

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

方法?

4

5 に答える 5

45

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

ウィザードで生成されたmain()関数の中には、次の行があります。

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

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

AppDelegateに最初に実行するように促すものは...

MainWindow.xibファイルで接続したため(プロジェクトウィザードが実際に接続を行いました)、ファイルの所有者(UIApplicationオブジェクト)の「デリゲート」アウトレットを.xibファイルのUIApplicationDelegateオブジェクトとクラスに接続しました。 UIApplicationDelegateのは、アプリのUIApplicationDelegateサブクラスに設定されます。

また、「MainWindow.xib」には魔法はありません。「Foo.xib」と呼ぶことができます。重要なのは、Info.plistファイルの「Mainnibfilebasename」というプロパティが「MainWindow」であるということです。MainWindow.xibの名前をFoo.xibに変更し、Info.plistの「Mainnib file base name」を「Foo」に変更しようとすると、引き続き機能することがわかります。

編集:RootControllerの詳細

繰り返しますが、いわゆる「RootController」には何の魔法もありません。これは、Xcodeの新しいプロジェクトウィザードによって作成されたUIViewControllerサブクラスの名前にすぎません。

ウィザードは、ProjectAppDelegateとProjectViewControllerの2つのクラスのコードをプロジェクトに配置します。ProjectAppDelegateクラスには、次の2つのアウトレットメンバーが含まれています。

IBOutlet UIWindow *window;
IBOutlet ProjectViewController *viewController;

MainWindow.xibファイルでは、UIWindowとProjectViewControllerの両方のインスタンスが配置され、ProjectAppDelegateの上記のアウトレットに接続されます。

画面に表示されるのは、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のビューをウィンドウのビューに追加し、ウィンドウを表示するコードを作成しました。「ルート」ビューコントローラーは.xibファイルに作成され、ProjectAppDelegateアウトレットに接続されました。

ウィザードのファイルを使用せずに、完全に自分でアプリケーションを作成することは非常に有益です。.xibファイルがどのように機能し、それらがコードオブジェクトにどのように関連するかについて多くを学びます。

于 2011-02-10T06:43:08.647 に答える
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;
}

の最後の2つのパラメーターUIApplicationMainは重要であり、プリンシパルクラス名とアプリケーションデリゲートを指定します。の場合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);

UIApplicationMainxibを介してファイル所有者を設定する必要はなく、この関数で直接指定できます。

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

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

最初にUIApplicationのインスタンスがインスタンス化され、次に、NSClassFromString私が推測するを使用して、この文字列からデリゲートクラスが作成されます。

デリゲートオブジェクトがインスタンス化され、アプリケーションの準備が整うと、デリゲートメソッドを使用してこのデリゲートオブジェクトに通知され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:...];

これは、ペン先が使用されていない場合にUIApplicationがプログラムで処理する方法です。真ん中にペン先を使用することはそれほど違いはありません。

于 2011-02-10T06:49:18.820 に答える
1

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

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

于 2011-02-10T06:41:23.890 に答える
1

あなたAppDelegateはUIApplicationのデリゲートであるため、UIApplicationライフサイクル中にクラスが投稿するすべての通知をリッスンします。通知はその1つであり、前述のメソッドを呼び出すようdidFinishLaunchingになります。AppDelegate

于 2011-02-10T06:41:50.723 に答える
1

Universal — iPhone + iPad —アプリの場合、ターゲットの情報パネルで、またはにキーを追加することで、プラットフォームごとに異なるNIBをロードするように指定NSMainNibFile~ipadできNSMainNibFile~iphoneますInfo.plistMainWindow~ipad.xibまたは、 NIBをターゲットに追加することもできます。これは、Info.plistMainWindow.xibのキーに基づいて、ではなくiPadに読み込まれます。NSMainNibFile

ユニバーサルアプリの制御とカスタマイズをさらに必要とする場合は、開始NIBを手動でロードできます。「ユニバーサル」プロジェクトテンプレートには、この方法の定型文が含まれているため、この手法の使用を開始する最も簡単な方法は、ユニバーサルプロファイルを使用して新しいiOSプロジェクトを作成することです。

上記の例でMain NIB Fileは、がInfo.plist(ターゲット設定)に設定されているため、アプリケーションデリゲートが呼び出されたときにNIBがすでにロードされています。通常、この設定では、MyAppDelegateオブジェクトもNIBにアーカイブされ(いくつかありますIBOutlets)、NIBFile's Ownerはに設定されUIApplicationます。

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

#import "MYAppDelegate.h"

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

次に、環境と設定を確認し、適切なNIBをロードします。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];
}

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

UIViewしたがって、NIBにある程度のルートがあることが期待され、 ( )のview出口に接続する必要があります。File's OwnerMYViewController

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

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

UIWindowMYViewControllerでルートを管理する場合、アプリデリゲートは必ずしもルートへの参照を持っている必要はありませんが、ルートウィンドウをNIBから除外し、アプリデリゲートで管理する方が全体的にクリーンな場合があります。

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

于 2012-08-19T22:34:44.467 に答える